Python: Add call-graph to cached dataflow stage

I didn't do any performance investigation on this, since it just seems
so much like the right approach.
This commit is contained in:
Rasmus Wriedt Larsen
2022-10-20 21:19:12 +02:00
parent fc0545561e
commit 36e8b8bfb9
2 changed files with 88 additions and 76 deletions

View File

@@ -37,6 +37,7 @@ private import DataFlowPublic
private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
private import semmle.python.internal.CachedStages
newtype TParameterPosition =
/** Used for `self` in methods, and `cls` in classmethods. */
@@ -1041,6 +1042,8 @@ predicate resolveClassInstanceCall(CallNode call, Function target, Node self) {
*/
cached
predicate resolveCall(ControlFlowNode call, Function target, CallType type) {
Stages::DataFlow::ref() and
(
type instanceof CallTypePlainFunction and
call.(CallNode).getFunction() = functionTracker(target).asCfgNode() and
not exists(Class cls | cls.getAMethod() = target)
@@ -1055,6 +1058,7 @@ predicate resolveCall(ControlFlowNode call, Function target, CallType type) {
or
type instanceof CallTypeClassInstanceCall and
resolveClassInstanceCall(call, target, _)
)
}
// =============================================================================
@@ -1119,6 +1123,8 @@ cached
predicate getCallArg(
ControlFlowNode call, Function target, CallType type, Node arg, ArgumentPosition apos
) {
Stages::DataFlow::ref() and
(
// normal calls with a real call node
resolveCall(call, target, type) and
call instanceof CallNode and
@@ -1192,6 +1198,7 @@ predicate getCallArg(
normalCallArg(call, arg, apos)
)
)
)
}
// =============================================================================

View File

@@ -180,6 +180,7 @@ module Stages {
predicate ref() { 1 = 1 }
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
private import semmle.python.dataflow.new.internal.DataFlowDispatch as DataFlowDispatch
private import semmle.python.dataflow.new.internal.LocalSources as LocalSources
private import semmle.python.internal.Awaited as Awaited
@@ -195,6 +196,10 @@ module Stages {
or
any(DataFlowPublic::Node node).hasLocationInfo(_, _, _, _, _)
or
DataFlowDispatch::resolveCall(_, _, _)
or
DataFlowDispatch::getCallArg(_, _, _, _, _)
or
any(LocalSources::LocalSourceNode n).flowsTo(_)
or
exists(Awaited::awaited(_))