Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 182d435

Browse files
committed
Python: Replace comprehension read-step by for
read-step. Add a version targetting sequence nodes.
1 parent c9537f2 commit 182d435

5 files changed

Lines changed: 188 additions & 45 deletions

File tree

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

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,6 @@ module EssaFlow {
161161
nodeFrom.(CfgNode).getNode() =
162162
nodeTo.(EssaNode).getVar().getDefinition().(AssignmentDefinition).getValue()
163163
or
164-
// Definition
165-
// `[a, b] = iterable`
166-
// nodeFrom = `iterable`, cfg node
167-
// nodeTo = `TIterableSequence([a, b])`
168-
exists(UnpackingAssignmentDirectTarget target |
169-
nodeFrom.asExpr() = target.getValue() and
170-
nodeTo = TIterableSequenceNode(target)
171-
)
172-
or
173164
// With definition
174165
// `with f(42) as x:`
175166
// nodeFrom is `f(42)`, cfg node
@@ -1045,7 +1036,7 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
10451036
or
10461037
popReadStep(nodeFrom, c, nodeTo)
10471038
or
1048-
comprehensionReadStep(nodeFrom, c, nodeTo)
1039+
forReadStep(nodeFrom, c, nodeTo)
10491040
or
10501041
attributeReadStep(nodeFrom, c, nodeTo)
10511042
or
@@ -1142,9 +1133,15 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
11421133
* also transfer other content, but only tuple content is further read from `sequence` into its elements.
11431134
*
11441135
* The strategy is then via several read-, store-, and flow steps:
1145-
* 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a
1136+
* 1. a) [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a
11461137
* flow step. From here, everything happens on the LHS.
11471138
*
1139+
* b) [Read] If the unpacking happens inside a for as in
1140+
* ```python
1141+
* for sequence in iterable
1142+
* ```
1143+
* then content is read from `iterable` to `TIterableSequence(sequence)`.
1144+
*
11481145
* 2. [Flow] Content is transferred from `TIterableSequence(sequence)` to `sequence` via a
11491146
* flow step. (Here only tuple content is relevant.)
11501147
*
@@ -1179,7 +1176,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
11791176
* Looking at the content propagation to `a`:
11801177
* `["a", SOURCE]`: [ListElementContent]
11811178
*
1182-
* --Step 1-->
1179+
* --Step 1a-->
11831180
*
11841181
* `TIterableSequence((a, b))`: [ListElementContent]
11851182
*
@@ -1205,7 +1202,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
12051202
*
12061203
* `["a", [SOURCE]]`: [ListElementContent; ListElementContent]
12071204
*
1208-
* --Step 1-->
1205+
* --Step 1a-->
12091206
*
12101207
* `TIterableSequence((a, [b, *c]))`: [ListElementContent; ListElementContent]
12111208
*
@@ -1238,13 +1235,53 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
12381235
* `c`: [ListElementContent]
12391236
*/
12401237
module UnpackingAssignment {
1238+
/**
1239+
* The target of a `for`, e.g. `x` in `for x in list` or in `[42 for x in list]`.
1240+
* This class also records the source, which in both above cases is `list`.
1241+
* This class abstracts away the differing representations of comprehensions and
1242+
* for statements.
1243+
*/
1244+
class ForTarget extends ControlFlowNode {
1245+
Expr source;
1246+
1247+
ForTarget() {
1248+
exists(For for |
1249+
source = for.getIter() and
1250+
this.getNode() = for.getTarget() and
1251+
not for = any(Comp comp).getNthInnerLoop(0)
1252+
)
1253+
or
1254+
exists(Comp comp |
1255+
source = comp.getIterable() and
1256+
this.getNode() = comp.getIterationVariable(0).getAStore()
1257+
)
1258+
}
1259+
1260+
Expr getSource() { result = source }
1261+
}
1262+
1263+
/** The LHS of an assignemnt, it also records the assigned value. */
1264+
class AssignmentTarget extends ControlFlowNode {
1265+
Expr value;
1266+
1267+
AssignmentTarget() {
1268+
exists(Assign assign | this.getNode() = assign.getATarget() | value = assign.getValue())
1269+
}
1270+
1271+
Expr getValue() { result = value }
1272+
}
1273+
12411274
/** A direct (or top-level) target of an unpacking assignment. */
12421275
class UnpackingAssignmentDirectTarget extends ControlFlowNode {
12431276
Expr value;
12441277

12451278
UnpackingAssignmentDirectTarget() {
12461279
this instanceof SequenceNode and
1247-
exists(Assign assign | this.getNode() = assign.getATarget() | value = assign.getValue())
1280+
(
1281+
value = this.(AssignmentTarget).getValue()
1282+
or
1283+
value = this.(ForTarget).getSource()
1284+
)
12481285
}
12491286

12501287
Expr getValue() { result = value }
@@ -1268,11 +1305,38 @@ module UnpackingAssignment {
12681305
ControlFlowNode getAnElement() { result = this.getElement(_) }
12691306
}
12701307

1308+
/**
1309+
* Step 1a
1310+
* Data flows from `iterable` to `TIterableSequence(sequence)`
1311+
*/
1312+
predicate unpackingAssignmentAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
1313+
exists(AssignmentTarget target |
1314+
nodeFrom.asExpr() = target.getValue() and
1315+
nodeTo = TIterableSequenceNode(target)
1316+
)
1317+
}
1318+
1319+
/**
1320+
* Step 1b
1321+
* Data is read from `iterable` to `TIterableSequence(sequence)`
1322+
*/
1323+
predicate unpackingAssignmentForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
1324+
exists(ForTarget target |
1325+
nodeFrom.asExpr() = target.getSource() and
1326+
nodeTo = TIterableSequenceNode(target.(SequenceNode))
1327+
) and
1328+
(
1329+
c instanceof ListElementContent
1330+
or
1331+
c instanceof SetElementContent
1332+
)
1333+
}
1334+
12711335
/**
12721336
* Step 2
12731337
* Data flows from `TIterableSequence(sequence)` to `sequence`
12741338
*/
1275-
predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
1339+
predicate unpackingAssignmentTupleFlowStep(Node nodeFrom, Node nodeTo) {
12761340
exists(UnpackingAssignmentSequenceTarget target |
12771341
nodeFrom = TIterableSequenceNode(target) and
12781342
nodeTo.asCfgNode() = target
@@ -1376,6 +1440,8 @@ module UnpackingAssignment {
13761440

13771441
/** All read steps associated with unpacking assignment. */
13781442
predicate unpackingAssignmentReadStep(Node nodeFrom, Content c, Node nodeTo) {
1443+
unpackingAssignmentForReadStep(nodeFrom, c, nodeTo)
1444+
or
13791445
unpackingAssignmentElementReadStep(nodeFrom, c, nodeTo)
13801446
or
13811447
unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo)
@@ -1387,6 +1453,13 @@ module UnpackingAssignment {
13871453
or
13881454
unpackingAssignmentConvertingStoreStep(nodeFrom, c, nodeTo)
13891455
}
1456+
1457+
/** All flow steps associated with unpacking assignment. */
1458+
predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
1459+
unpackingAssignmentAssignmentFlowStep(nodeFrom, nodeTo)
1460+
or
1461+
unpackingAssignmentTupleFlowStep(nodeFrom, nodeTo)
1462+
}
13901463
}
13911464

13921465
import UnpackingAssignment
@@ -1425,25 +1498,10 @@ predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
14251498
)
14261499
}
14271500

1428-
/** Data flows from a iterated sequence to the variable iterating over the sequence. */
1429-
predicate comprehensionReadStep(CfgNode nodeFrom, Content c, EssaNode nodeTo) {
1430-
// Comprehension
1431-
// `[x+1 for x in l]`
1432-
// nodeFrom is `l`, cfg node
1433-
// nodeTo is `x`, essa var
1434-
// c denotes element of list or set
1435-
exists(Comp comp |
1436-
// outermost for
1437-
nodeFrom.getNode().getNode() = comp.getIterable() and
1438-
nodeTo.getVar().getDefinition().(AssignmentDefinition).getDefiningNode().getNode() =
1439-
comp.getIterationVariable(0).getAStore()
1440-
or
1441-
// an inner for
1442-
exists(int n | n > 0 |
1443-
nodeFrom.getNode().getNode() = comp.getNthInnerLoop(n).getIter() and
1444-
nodeTo.getVar().getDefinition().(AssignmentDefinition).getDefiningNode().getNode() =
1445-
comp.getNthInnerLoop(n).getTarget()
1446-
)
1501+
predicate forReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
1502+
exists(ForTarget target |
1503+
nodeFrom.asExpr() = target.getSource() and
1504+
nodeTo.asVar().(EssaNodeDefinition).getDefiningNode() = target
14471505
) and
14481506
(
14491507
c instanceof ListElementContent

python/ql/test/experimental/dataflow/coverage/dataflow.expected

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,38 @@ edges
285285
| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | test.py:639:12:639:16 | ControlFlowNode for Subscript |
286286
| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | test.py:640:10:640:14 | ControlFlowNode for Subscript |
287287
| test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a |
288-
| test.py:739:16:739:21 | ControlFlowNode for SOURCE | test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() |
288+
| test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:656:16:656:17 | ControlFlowNode for tl [List element, Tuple element at index 0] |
289+
| test.py:655:12:655:17 | ControlFlowNode for SOURCE | test.py:655:12:655:28 | ControlFlowNode for Tuple [Tuple element at index 0] |
290+
| test.py:655:12:655:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] |
291+
| test.py:655:33:655:38 | ControlFlowNode for SOURCE | test.py:655:33:655:49 | ControlFlowNode for Tuple [Tuple element at index 0] |
292+
| test.py:655:33:655:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] |
293+
| test.py:656:9:656:9 | SSA variable x | test.py:657:14:657:14 | ControlFlowNode for x |
294+
| test.py:656:9:656:11 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:656:9:656:9 | SSA variable x |
295+
| test.py:656:9:656:11 | IterableSequence [Tuple element at index 0] | test.py:656:9:656:11 | ControlFlowNode for Tuple [Tuple element at index 0] |
296+
| test.py:656:16:656:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:656:9:656:11 | IterableSequence [Tuple element at index 0] |
297+
| test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:664:17:664:18 | ControlFlowNode for tl [List element, Tuple element at index 0] |
298+
| test.py:663:12:663:17 | ControlFlowNode for SOURCE | test.py:663:12:663:28 | ControlFlowNode for Tuple [Tuple element at index 0] |
299+
| test.py:663:12:663:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] |
300+
| test.py:663:33:663:38 | ControlFlowNode for SOURCE | test.py:663:33:663:49 | ControlFlowNode for Tuple [Tuple element at index 0] |
301+
| test.py:663:33:663:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] |
302+
| test.py:664:9:664:10 | IterableElement | test.py:664:9:664:10 | SSA variable x [List element] |
303+
| test.py:664:9:664:10 | SSA variable x [List element] | test.py:666:14:666:14 | ControlFlowNode for x [List element] |
304+
| test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:664:9:664:10 | IterableElement |
305+
| test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:664:12:664:12 | SSA variable y |
306+
| test.py:664:9:664:12 | IterableSequence [Tuple element at index 0] | test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] |
307+
| test.py:664:12:664:12 | SSA variable y | test.py:667:16:667:16 | ControlFlowNode for y |
308+
| test.py:664:17:664:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:664:9:664:12 | IterableSequence [Tuple element at index 0] |
309+
| test.py:666:14:666:14 | ControlFlowNode for x [List element] | test.py:666:14:666:17 | ControlFlowNode for Subscript |
310+
| test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:673:19:673:20 | ControlFlowNode for tl [List element, Tuple element at index 0] |
311+
| test.py:672:12:672:17 | ControlFlowNode for SOURCE | test.py:672:12:672:28 | ControlFlowNode for Tuple [Tuple element at index 0] |
312+
| test.py:672:12:672:28 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] |
313+
| test.py:672:33:672:38 | ControlFlowNode for SOURCE | test.py:672:33:672:49 | ControlFlowNode for Tuple [Tuple element at index 0] |
314+
| test.py:672:33:672:49 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] |
315+
| test.py:673:9:673:9 | SSA variable x | test.py:674:14:674:14 | ControlFlowNode for x |
316+
| test.py:673:9:673:14 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:673:9:673:9 | SSA variable x |
317+
| test.py:673:9:673:14 | IterableSequence [Tuple element at index 0] | test.py:673:9:673:14 | ControlFlowNode for Tuple [Tuple element at index 0] |
318+
| test.py:673:19:673:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | test.py:673:9:673:14 | IterableSequence [Tuple element at index 0] |
319+
| test.py:749:16:749:21 | ControlFlowNode for SOURCE | test.py:752:10:752:36 | ControlFlowNode for return_from_inner_scope() |
289320
nodes
290321
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
291322
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
@@ -628,8 +659,42 @@ nodes
628659
| test.py:640:10:640:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
629660
| test.py:647:19:647:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
630661
| test.py:648:10:648:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
631-
| test.py:739:16:739:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
632-
| test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() |
662+
| test.py:655:10:655:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] |
663+
| test.py:655:12:655:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
664+
| test.py:655:12:655:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
665+
| test.py:655:33:655:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
666+
| test.py:655:33:655:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
667+
| test.py:656:9:656:9 | SSA variable x | semmle.label | SSA variable x |
668+
| test.py:656:9:656:11 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
669+
| test.py:656:9:656:11 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
670+
| test.py:656:16:656:17 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] |
671+
| test.py:657:14:657:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
672+
| test.py:663:10:663:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] |
673+
| test.py:663:12:663:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
674+
| test.py:663:12:663:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
675+
| test.py:663:33:663:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
676+
| test.py:663:33:663:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
677+
| test.py:664:9:664:10 | IterableElement | semmle.label | IterableElement |
678+
| test.py:664:9:664:10 | SSA variable x [List element] | semmle.label | SSA variable x [List element] |
679+
| test.py:664:9:664:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
680+
| test.py:664:9:664:12 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
681+
| test.py:664:12:664:12 | SSA variable y | semmle.label | SSA variable y |
682+
| test.py:664:17:664:18 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] |
683+
| test.py:666:14:666:14 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] |
684+
| test.py:666:14:666:17 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
685+
| test.py:667:16:667:16 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
686+
| test.py:672:10:672:51 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] |
687+
| test.py:672:12:672:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
688+
| test.py:672:12:672:28 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
689+
| test.py:672:33:672:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
690+
| test.py:672:33:672:49 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
691+
| test.py:673:9:673:9 | SSA variable x | semmle.label | SSA variable x |
692+
| test.py:673:9:673:14 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
693+
| test.py:673:9:673:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] |
694+
| test.py:673:19:673:20 | ControlFlowNode for tl [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for tl [List element, Tuple element at index 0] |
695+
| test.py:674:14:674:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
696+
| test.py:749:16:749:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
697+
| test.py:752:10:752:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() |
633698
#select
634699
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found |
635700
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found |
@@ -724,4 +789,12 @@ nodes
724789
| test.py:639:12:639:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:639:12:639:16 | ControlFlowNode for Subscript | Flow found |
725790
| test.py:640:10:640:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:640:10:640:14 | ControlFlowNode for Subscript | Flow found |
726791
| test.py:648:10:648:10 | ControlFlowNode for a | test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a | Flow found |
727-
| test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | test.py:739:16:739:21 | ControlFlowNode for SOURCE | test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | Flow found |
792+
| test.py:657:14:657:14 | ControlFlowNode for x | test.py:655:12:655:17 | ControlFlowNode for SOURCE | test.py:657:14:657:14 | ControlFlowNode for x | Flow found |
793+
| test.py:657:14:657:14 | ControlFlowNode for x | test.py:655:33:655:38 | ControlFlowNode for SOURCE | test.py:657:14:657:14 | ControlFlowNode for x | Flow found |
794+
| test.py:666:14:666:17 | ControlFlowNode for Subscript | test.py:663:12:663:17 | ControlFlowNode for SOURCE | test.py:666:14:666:17 | ControlFlowNode for Subscript | Flow found |
795+
| test.py:666:14:666:17 | ControlFlowNode for Subscript | test.py:663:33:663:38 | ControlFlowNode for SOURCE | test.py:666:14:666:17 | ControlFlowNode for Subscript | Flow found |
796+
| test.py:667:16:667:16 | ControlFlowNode for y | test.py:663:12:663:17 | ControlFlowNode for SOURCE | test.py:667:16:667:16 | ControlFlowNode for y | Flow found |
797+
| test.py:667:16:667:16 | ControlFlowNode for y | test.py:663:33:663:38 | ControlFlowNode for SOURCE | test.py:667:16:667:16 | ControlFlowNode for y | Flow found |
798+
| test.py:674:14:674:14 | ControlFlowNode for x | test.py:672:12:672:17 | ControlFlowNode for SOURCE | test.py:674:14:674:14 | ControlFlowNode for x | Flow found |
799+
| test.py:674:14:674:14 | ControlFlowNode for x | test.py:672:33:672:38 | ControlFlowNode for SOURCE | test.py:674:14:674:14 | ControlFlowNode for x | Flow found |
800+
| test.py:752:10:752:36 | ControlFlowNode for return_from_inner_scope() | test.py:749:16:749:21 | ControlFlowNode for SOURCE | test.py:752:10:752:36 | ControlFlowNode for return_from_inner_scope() | Flow found |

0 commit comments

Comments
 (0)