Skip to content

Commit 310819d

Browse files
committed
Python: fix dataflow inconsistencies
- adjust scope of argument, the argument is outside the called function - add missing post-update nodes for the new arguments
1 parent d4ea62e commit 310819d

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1752,13 +1752,25 @@ class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVar
17521752

17531753
override string toString() { result = "Capturing closure argument (comp)" }
17541754

1755-
override Scope getScope() { result = comp.getFunction() }
1755+
override Scope getScope() { result = comp.getScope() }
17561756

17571757
override Location getLocation() { result = comp.getLocation() }
17581758

17591759
Comp getComprehension() { result = comp }
17601760
}
17611761

1762+
class SynthCompCapturedVariablesArgumentPostUpdateNode extends PostUpdateNodeImpl,
1763+
TSynthCompCapturedVariablesArgumentPostUpdateNode
1764+
{
1765+
Comp comp;
1766+
1767+
SynthCompCapturedVariablesArgumentPostUpdateNode() {
1768+
this = TSynthCompCapturedVariablesArgumentPostUpdateNode(comp)
1769+
}
1770+
1771+
override Node getPreUpdateNode() { result = TSynthCompCapturedVariablesArgumentNode(comp) }
1772+
}
1773+
17621774
/** Gets a viable run-time target for the call `call`. */
17631775
DataFlowCallable viableCallable(DataFlowCall call) {
17641776
call instanceof ExtractedDataFlowCall and

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,12 @@ abstract class PostUpdateNodeImpl extends Node {
287287
abstract Node getPreUpdateNode();
288288
}
289289

290+
/**
291+
* A post-update node synthesised for an existing control flow node.
292+
* Add to `TSyntheticPostUpdateNode` to get the synthetic post-update node synthesised.
293+
*
294+
* Synthetic post-update nodes for synthetic nodes need to be listed one by one.
295+
*/
290296
class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNode {
291297
ControlFlowNode node;
292298

@@ -301,6 +307,11 @@ class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNo
301307
override Location getLocation() { result = node.getLocation() }
302308
}
303309

310+
/**
311+
* An existsing control flow node being the post-update node of a synthetic pre-update node.
312+
*
313+
* Synthetic post-update nodes for synthetic nodes need to be listed one by one.
314+
*/
304315
class NonSyntheticPostUpdateNode extends PostUpdateNodeImpl, CfgNode {
305316
SyntheticPreUpdateNode pre;
306317

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ newtype TNode =
7171
def.getDefiningNode() = node and
7272
def.getParameter() = func.getArg(0)
7373
)
74+
or
75+
// the iterable argument to the implicit comprehension function
76+
node.getNode() = any(Comp c).getIterable()
7477
} or
7578
/** A node representing a global (module-level) variable in a specific module. */
7679
TModuleVariableNode(Module m, GlobalVariable v) {
@@ -129,6 +132,9 @@ newtype TNode =
129132
TSynthCompCapturedVariablesArgumentNode(Comp comp) {
130133
comp.getFunction() = any(VariableCapture::CapturedVariable v).getACapturingScope()
131134
} or
135+
TSynthCompCapturedVariablesArgumentPostUpdateNode(Comp comp) {
136+
comp.getFunction() = any(VariableCapture::CapturedVariable v).getACapturingScope()
137+
} or
132138
/** An empty, unused node type that exists to prevent unwanted dependencies on data flow nodes. */
133139
TForbiddenRecursionGuard() {
134140
none() and

0 commit comments

Comments
 (0)