@@ -281,28 +281,33 @@ class DataFlowExpr = Expr;
281281/**
282282 * A module to compute local flow.
283283 *
284- * Flow will generally go from control flow nodes into essa variables at definitions,
284+ * Flow will generally go from control flow nodes for expressions into
285+ * control flow nodes for variables at definitions,
285286 * and from there via use-use flow to other control flow nodes.
286287 *
287288 * Some syntaxtic constructs are handled separately.
288289 */
289290module LocalFlow {
290- /** Holds if `nodeFrom` is the control flow node defining the essa variable `nodeTo`. */
291+ /** Holds if `nodeFrom` is the expression defining the value for the variable `nodeTo`. */
291292 predicate definitionFlowStep ( Node nodeFrom , Node nodeTo ) {
292293 // Definition
293294 // `x = f(42)`
294- // nodeFrom is `f(42)`, cfg node
295- // nodeTo is `x`, essa var
296- nodeFrom .( CfgNode ) .getNode ( ) =
297- nodeTo .( EssaNode ) .getVar ( ) .getDefinition ( ) .( AssignmentDefinition ) .getValue ( )
295+ // nodeFrom is `f(42)`
296+ // nodeTo is `x`
297+ exists ( AssignmentDefinition def |
298+ nodeFrom .( CfgNode ) .getNode ( ) = def .getValue ( ) and
299+ nodeTo .( CfgNode ) .getNode ( ) = def .getDefiningNode ( )
300+ )
298301 or
299302 // With definition
300303 // `with f(42) as x:`
301- // nodeFrom is `f(42)`, cfg node
302- // nodeTo is `x`, essa var
303- exists ( With with , ControlFlowNode contextManager , ControlFlowNode var |
304+ // nodeFrom is `f(42)`
305+ // nodeTo is `x`
306+ exists ( With with , ControlFlowNode contextManager , WithDefinition withDef , ControlFlowNode var |
307+ var = withDef .getDefiningNode ( )
308+ |
304309 nodeFrom .( CfgNode ) .getNode ( ) = contextManager and
305- nodeTo .( EssaNode ) . getVar ( ) . getDefinition ( ) . ( WithDefinition ) . getDefiningNode ( ) = var and
310+ nodeTo .( CfgNode ) . getNode ( ) = var and
306311 // see `with_flow` in `python/ql/src/semmle/python/dataflow/Implementation.qll`
307312 with .getContextExpr ( ) = contextManager .getNode ( ) and
308313 with .getOptionalVars ( ) = var .getNode ( ) and
@@ -313,34 +318,6 @@ module LocalFlow {
313318 // * `foo = x.foo(); await foo.async_method(); foo.close()` and
314319 // * `async with x.foo() as foo: await foo.async_method()`.
315320 )
316- or
317- // Async with var definition
318- // `async with f(42) as x:`
319- // nodeFrom is `x`, cfg node
320- // nodeTo is `x`, essa var
321- //
322- // This makes the cfg node the local source of the awaited value.
323- //
324- // We have this step in addition to the step above, to handle cases where the QL
325- // modeling of `f(42)` requires a `.getAwaited()` step (in API graphs) when not
326- // using `async with`, so you can do both:
327- // * `foo = await x.foo(); await foo.async_method(); foo.close()` and
328- // * `async with x.foo() as foo: await foo.async_method()`.
329- exists ( With with , ControlFlowNode var |
330- nodeFrom .( CfgNode ) .getNode ( ) = var and
331- nodeTo .( EssaNode ) .getVar ( ) .getDefinition ( ) .( WithDefinition ) .getDefiningNode ( ) = var and
332- with .getOptionalVars ( ) = var .getNode ( ) and
333- with .isAsync ( )
334- )
335- or
336- // Parameter definition
337- // `def foo(x):`
338- // nodeFrom is `x`, cfgNode
339- // nodeTo is `x`, essa var
340- exists ( ParameterDefinition pd |
341- nodeFrom .( CfgNode ) .getNode ( ) = pd .getDefiningNode ( ) and
342- nodeTo .( EssaNode ) .getVar ( ) = pd .getVariable ( )
343- )
344321 }
345322
346323 predicate expressionFlowStep ( Node nodeFrom , Node nodeTo ) {
@@ -372,9 +349,12 @@ module LocalFlow {
372349 // First use after definition
373350 // `y = 42`
374351 // `x = f(y)`
375- // nodeFrom is `y` on first line, essa var
376- // nodeTo is `y` on second line, cfg node
377- defToFirstUse ( nodeFrom .asVar ( ) , nodeTo .asCfgNode ( ) )
352+ // nodeFrom is `y` on first line
353+ // nodeTo is `y` on second line
354+ exists ( EssaDefinition def |
355+ nodeFrom .( CfgNode ) .getNode ( ) = def .( EssaNodeDefinition ) .getDefiningNode ( ) and
356+ AdjacentUses:: firstUse ( def , nodeTo .( CfgNode ) .getNode ( ) )
357+ )
378358 or
379359 // Next use after use
380360 // `x = f(y)`
@@ -565,11 +545,7 @@ predicate neverSkipInPathGraph(Node n) {
565545 // ```
566546 // we would end up saying that the path MUST not skip the x in `y = x`, which is just
567547 // annoying and doesn't help the path explanation become clearer.
568- n .asVar ( ) instanceof EssaDefinition and
569- // For a parameter we have flow from ControlFlowNode to SSA node, and then onwards
570- // with use-use flow, and since the CFN is already part of the path graph, we don't
571- // want to force showing the SSA node as well.
572- not n .asVar ( ) instanceof ParameterDefinition
548+ n .asCfgNode ( ) = any ( EssaNodeDefinition def ) .getDefiningNode ( )
573549}
574550
575551/**
@@ -916,7 +892,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
916892predicate forReadStep ( CfgNode nodeFrom , Content c , Node nodeTo ) {
917893 exists ( ForTarget target |
918894 nodeFrom .asExpr ( ) = target .getSource ( ) and
919- nodeTo .asVar ( ) . ( EssaNodeDefinition ) . getDefiningNode ( ) = target
895+ nodeTo .asCfgNode ( ) = target
920896 ) and
921897 (
922898 c instanceof ListElementContent
0 commit comments