Skip to content

Commit c7a8083

Browse files
committed
Python: Make ExtractedArgumentNode local
Explicitly adds a bunch of nodes that were previously (using a global analysis) identified as `ExtractedArgumentNode`s. These are then subsequently filtered out in `argumentOf` (which is global) by putting the call to `getCallArg` there instead of in the charpred.
1 parent 442146b commit c7a8083

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -339,27 +339,51 @@ abstract class ArgumentNode extends Node {
339339
final ExtractedDataFlowCall getCall() { this.argumentOf(result, _) }
340340
}
341341

342+
/** Gets an overapproximation of the argument nodes that are included in `getCallArg`. */
343+
Node getCallArgApproximation() {
344+
// pre-update nodes for calls
345+
result = any(CallCfgNode c).(PostUpdateNode).getPreUpdateNode()
346+
or
347+
// self parameters in methods
348+
exists(Class c | result.asExpr() = c.getAMethod().getArg(0))
349+
or
350+
// the object part of an attribute expression (which might be a bound method)
351+
result.asCfgNode() = any(AttrNode a).getObject()
352+
or
353+
// the function part of any call
354+
result.asCfgNode() = any(CallNode c).getFunction()
355+
}
356+
357+
/** Gets the extracted argument nodes that do not rely on `getCallArg`. */
358+
private Node otherArgs() {
359+
// for potential summaries we allow all normal call arguments
360+
normalCallArg(_, result, _)
361+
or
362+
// and self arguments
363+
result.asCfgNode() = any(CallNode c).getFunction().(AttrNode).getObject()
364+
or
365+
// for comprehensions, we allow the synthetic `iterable` argument
366+
result.asExpr() = any(Comp c).getIterable()
367+
}
368+
342369
/**
343370
* A data flow node that represents a call argument found in the source code.
344371
*/
345372
class ExtractedArgumentNode extends ArgumentNode {
346373
ExtractedArgumentNode() {
347-
// for resolved calls, we need to allow all argument nodes
348-
getCallArg(_, _, _, this, _)
349-
or
350-
// for potential summaries we allow all normal call arguments
351-
normalCallArg(_, this, _)
374+
this = getCallArgApproximation()
352375
or
353-
// and self arguments
354-
this.asCfgNode() = any(CallNode c).getFunction().(AttrNode).getObject()
355-
or
356-
// for comprehensions, we allow the synthetic `iterable` argument
357-
this.asExpr() = any(Comp c).getIterable()
376+
this = otherArgs()
358377
}
359378

360379
final override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
361380
this = call.getArgument(pos) and
362-
call instanceof ExtractedDataFlowCall
381+
call instanceof ExtractedDataFlowCall and
382+
(
383+
this = otherArgs()
384+
or
385+
this = getCallArgApproximation() and getCallArg(_, _, _, this, _)
386+
)
363387
}
364388
}
365389

0 commit comments

Comments
 (0)