Skip to content

Commit dacc0ab

Browse files
committed
Python: docs and a simplification
1 parent 438e664 commit dacc0ab

File tree

2 files changed

+24
-23
lines changed

2 files changed

+24
-23
lines changed

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

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,10 @@ newtype TDataFlowCallable =
318318
* class instantiations, and (in the future) special methods.
319319
*/
320320
TFunction(Function func) {
321-
// For generators/list-comprehensions we create a synthetic function. In the
322-
// points-to call-graph these were not considered callable, and instead we added
323-
// data-flow steps (read/write) for these. As an easy solution for now, we do the
324-
// same to keep things easy to reason about (and therefore exclude things that do
325-
// not have a definition)
321+
// Functions with an explicit definition
326322
exists(func.getDefinition())
327323
or
328-
// ...scratch that, variable capture requires a callable
324+
// For generators/list-comprehensions we create a synthetic function.
329325
exists(Comp c | c.getFunction() = func)
330326
} or
331327
/** see QLDoc for `DataFlowModuleScope` for why we need this. */
@@ -1389,6 +1385,7 @@ private predicate sameEnclosingCallable(Node node1, Node node2) {
13891385
// =============================================================================
13901386
newtype TDataFlowCall =
13911387
TNormalCall(CallNode call, Function target, CallType type) { resolveCall(call, target, type) } or
1388+
/** A call to the generated function inside a comprhension */
13921389
TComprehensionCall(Comp c) or
13931390
TPotentialLibraryCall(CallNode call) or
13941391
/** A synthesized call inside a summarized callable */
@@ -1476,6 +1473,7 @@ class NormalCall extends ExtractedDataFlowCall, TNormalCall {
14761473
CallType getCallType() { result = type }
14771474
}
14781475

1476+
/** A call to the generated function inside a comprhension */
14791477
class ComprehensionCall extends ExtractedDataFlowCall, TComprehensionCall {
14801478
Comp c;
14811479
Function target;
@@ -1733,23 +1731,10 @@ class CapturedVariablesArgumentNode extends CfgNode, ArgumentNode {
17331731
}
17341732
}
17351733

1736-
class ComprehensionCapturedVariablesArgumentNode extends Node, ArgumentNode {
1737-
Comp comp;
1738-
1739-
ComprehensionCapturedVariablesArgumentNode() {
1740-
this = TSynthCompCapturedVariablesArgumentNode(comp) and
1741-
exists(Function target | target = comp.getFunction() |
1742-
target = any(VariableCapture::CapturedVariable v).getACapturingScope()
1743-
)
1744-
}
1745-
1746-
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
1747-
call.(ComprehensionCall).getComprehension() = comp and
1748-
pos.isLambdaSelf()
1749-
}
1750-
}
1751-
1752-
class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVariablesArgumentNode {
1734+
/** A synthetic node representing the values of variables captured by a comprehension. */
1735+
class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVariablesArgumentNode,
1736+
ArgumentNode
1737+
{
17531738
Comp comp;
17541739

17551740
SynthCompCapturedVariablesArgumentNode() { this = TSynthCompCapturedVariablesArgumentNode(comp) }
@@ -1761,8 +1746,14 @@ class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVar
17611746
override Location getLocation() { result = comp.getLocation() }
17621747

17631748
Comp getComprehension() { result = comp }
1749+
1750+
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
1751+
call.(ComprehensionCall).getComprehension() = comp and
1752+
pos.isLambdaSelf()
1753+
}
17641754
}
17651755

1756+
/** A synthetic node representing the values of variables captured by a comprehension after the output has been computed. */
17661757
class SynthCompCapturedVariablesArgumentPostUpdateNode extends PostUpdateNodeImpl,
17671758
TSynthCompCapturedVariablesArgumentPostUpdateNode
17681759
{

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ private predicate synthDictSplatArgumentNodeStoreStep(
168168
)
169169
}
170170

171+
/**
172+
* Holds if `nodeFrom` is the value yielded by the `yield` found at `nodeTo`.
173+
*
174+
* For example, in
175+
* ```python
176+
* for x in l:
177+
* yield x.name
178+
* ```
179+
* data from `x.name` is stored into the `yield` (and can subsequently be read out of the iterable).
180+
*/
171181
predicate yieldStoreStep(Node nodeFrom, Content c, Node nodeTo) {
172182
exists(Yield yield, Function func |
173183
nodeTo.asCfgNode() = yield.getAFlowNode() and

0 commit comments

Comments
 (0)