Python: Added recursion guard

to ensure that the call graph seen by type tracking
does not include summary calls resolved by type tracking.

(I tried inserting a similar test into the Ruby codebase,
 and it still compiled)

To get this to compile, I had to move the resolution of summary calls
out of the data flow nodes and into the `viableCallable` predicate.
This means that we now have a potential summary call for each
cfg call node. (I tried using the base class, `DataFlowCall`, for this
but calls to `map` got identified as class calls and would no longer
be associated with a summary.)

It is possible that the "NonLIbrary"-layers the were inserted into the
hierarchy can be removed again.
This commit is contained in:
Rasmus Lerchedahl Petersen
2022-09-09 22:47:47 +02:00
parent 1649ec7cd7
commit 895f5480c2
3 changed files with 50 additions and 8 deletions

View File

@@ -2,6 +2,25 @@ private import python
private import semmle.python.dataflow.new.FlowSummary
private import semmle.python.ApiGraphs
/** This module ensures that the `callStep` predicate in
* our type tracker implelemtation does not refer to the
* `getACall` predicate on `SummarizedCallable`.
*/
module RecursionGuard {
private import semmle.python.dataflow.new.internal.TypeTrackerSpecific as TT
private class RecursionGuard extends SummarizedCallable {
RecursionGuard() { this = "RecursionGuard" }
override CallNode getACall() {
result.getFunction().(NameNode).getId() = this and
(TT::callStep(_, _) implies any())
}
override DataFlow::ArgumentNode getACallback() { result.asExpr().(Name).getId() = this }
}
}
private class SummarizedCallableIdentity extends SummarizedCallable {
SummarizedCallableIdentity() { this = "identity" }