Python: model conversion during unpacking

This commit is contained in:
Rasmus Lerchedahl Petersen
2021-01-12 22:19:31 +01:00
parent d8d8b45c6a
commit 4ee2f49f38
4 changed files with 389 additions and 85 deletions

View File

@@ -161,6 +161,8 @@ module EssaFlow {
// If expressions
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand()
or
unpackingAssignmentDirectFlowStep(nodeFrom, nodeTo)
or
// Overflow keyword argument
exists(CallNode call, CallableValue callable |
call = callable.getACall() and
@@ -846,6 +848,8 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
or
comprehensionStoreStep(nodeFrom, c, nodeTo)
or
unpackingAssignmentStoreStep(nodeFrom, c, nodeTo)
or
attributeStoreStep(nodeFrom, c, nodeTo)
or
posOverflowStoreStep(nodeFrom, c, nodeTo)
@@ -1010,76 +1014,196 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
)
}
predicate unpackingAssignmentRead(CfgNode nodeFrom, Content c, ControlFlowNode readNode) {
// `a, b = iterable`
// nodeFrom = `iterable`
// readNode = `a`
// c is compatible with type of `a, b` (so tuple if it was `(a, b)`)
exists(Assign assign, SequenceNode target, int index | target.getNode() = assign.getATarget() |
nodeFrom.asExpr() = assign.getValue() and
readNode = target.getElement(index) and
(
target instanceof ListNode and
c instanceof ListElementContent
or
target instanceof TupleNode and
c.(TupleElementContent).getIndex() = index
module unpackinAssignment {
/** Data flows from an iterable to an assigned variable. */
predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
unpackingAssignmentToplevelReadStep(nodeFrom, c, nodeTo)
or
unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo)
or
unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo)
or
unpackingAssignmentConvertingInternalReadStep(nodeFrom, c, nodeTo)
}
predicate unpackingAssignmentStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) {
unpackingAssignmentConvertingStoreStep(nodeFrom, c, nodeTo)
or
unpackingAssignmentConvertingInternalStoreStep(nodeFrom, c, nodeTo)
}
predicate unpackingAssignmentRead(CfgNode nodeFrom, Content c, ControlFlowNode readNode) {
// `a, b = iterable`
// nodeFrom = `a, b`
// readNode = `a`
// c is compatible with type of `a, b` (so tuple if it was `(a, b)`)
exists(Assign assign, SequenceNode target, int index | target.getNode() = assign.getATarget() |
nodeFrom.getNode() = target and
readNode = target.getElement(index) and
(
target instanceof ListNode and
c instanceof ListElementContent
or
target instanceof TupleNode and
c.(TupleElementContent).getIndex() = index
)
)
)
}
predicate unpackingAssignmentInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
// iterable unpacking
// `a, (b, (c, d)) = iterable`
// nodeFrom is `(b, (c, d))`, cfg node
// nodeTo is `b`, essa var
// or `(c, d)`, cfg node
// c is compatible with `b`s (or `(c, d)`s) index
exists(
Assign assign, SequenceNode target, SequenceNode readFrom, int index, ControlFlowNode readTo
|
target.getNode() = assign.getATarget() and
readFrom = target.getAnElement() // use contains to get deeper nesting
|
nodeFrom.getNode() = readFrom and
readTo = readFrom.getElement(index) and
(
readTo instanceof SequenceNode and
nodeTo.asCfgNode() = readTo
or
not readTo instanceof SequenceNode and
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readTo
) and
(
readFrom instanceof ListNode and
c instanceof ListElementContent
or
readFrom instanceof TupleNode and
c.(TupleElementContent).getIndex() = index
)
)
}
/** Data flows from an iterable to an assigned variable. */
predicate unpackingAssignmentToplevelReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
// iterable unpacking
// `a, (b, c) = iterable`
// nodeFrom is `a, (b, c)`, cfg node
// nodeTo is `a`, essa var
// or `(b, c)`, cfg node
// c is compatible with `a`s (or `(b, c)`s) index
exists(ControlFlowNode readNode | unpackingAssignmentRead(nodeFrom, c, readNode) |
(
readNode instanceof SequenceNode and
nodeTo.asCfgNode() = readNode
or
not readNode instanceof SequenceNode and
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readNode
)
)
or
unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo)
}
predicate unpackingAssignmentDirectFlowStep(CfgNode nodeFrom, CfgNode nodeTo) {
// `a, b = iterable`
// nodeFrom = `iterable`
// readNode = `a, b`
exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() |
nodeFrom.asExpr() = assign.getValue() and
nodeTo.getNode() = target
)
}
predicate unpackingAssignmentConvertingReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
// iterable unpacking
// `a, b = iterable`
// nodeFrom is `iterable`
// nodeTo is synthetic IterableElement
// c is whatever element content `iterable` might carry
// we wish to consume c, so that we can later write it back in the type of the lhs.
exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() |
nodeFrom.asExpr() = assign.getValue() and
nodeTo = TIterableElement(target) and
(
c instanceof ListElementContent
or
c instanceof SetElementContent
or
// do not lose precision by routing tuple content through the `IterableElement`
not target instanceof TupleNode and
// `index` refers to `nodeFrom`, but only the ones in `target` are relevant.
exists(int index | exists(target.getElement(index)) |
c.(TupleElementContent).getIndex() = index
)
// leaving out dict content for now
)
)
}
predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) {
// iterable unpacking
// `a, b = iterable`
// nodeFrom is synthetic IterableElement
// nodeTo is `a, b`
// c is consistent with the type of the lhs.
exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() |
nodeFrom = TIterableElement(target) and
nodeTo.getNode() = target and
(
target instanceof ListNode and
c instanceof ListElementContent
or
target instanceof TupleNode and
exists(int index | exists(target.getElement(index)) |
c.(TupleElementContent).getIndex() = index
)
)
)
}
predicate unpackingAssignmentConvertingInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
exists(Assign assign, SequenceNode target, SequenceNode readFrom |
target.getNode() = assign.getATarget() and
readFrom = target.getAnElement() // use contains to get deeper nesting
|
nodeFrom.getNode() = readFrom and
nodeTo = TIterableElement(readFrom) and
(
c instanceof ListElementContent
or
c instanceof SetElementContent
or
// do not lose precision by routing tuple content through the `IterableElement`
not readFrom instanceof TupleNode and
// `index` refers to `nodeFrom`, but only the ones in `target` are relevant.
exists(int index | exists(readFrom.getElement(index)) |
c.(TupleElementContent).getIndex() = index
)
// leaving out dict content for now
)
)
}
predicate unpackingAssignmentConvertingInternalStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) {
exists(Assign assign, SequenceNode target, SequenceNode readFrom |
target.getNode() = assign.getATarget() and
readFrom = target.getAnElement() // use contains to get deeper nesting
|
nodeFrom = TIterableElement(readFrom) and
nodeTo.getNode() = readFrom and
(
readFrom instanceof ListNode and
c instanceof ListElementContent
or
readFrom instanceof TupleNode and
exists(int index | exists(readFrom.getElement(index)) |
c.(TupleElementContent).getIndex() = index
)
)
)
}
}
predicate unpackingAssignmentInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
// iterable unpacking
// `a, (b, (c, d)) = iterable`
// nodeFrom is `(b, (c, d))`, cfg node
// nodeTo is `b`, essa var
// or `(c, d)`, cfg node
// c is compatible with `b`s (or `(c, d)`s) index
exists(
Assign assign, SequenceNode target, SequenceNode readFrom, int index, ControlFlowNode readTo
|
target.getNode() = assign.getATarget() and
readFrom = target.getAnElement() // use contains to get deeper nesting
|
nodeFrom.getNode() = readFrom and
readTo = readFrom.getElement(index) and
(
readTo instanceof SequenceNode and
nodeTo.asCfgNode() = readTo
or
not readTo instanceof SequenceNode and
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readTo
) and
(
readFrom instanceof ListNode and
c instanceof ListElementContent
or
readFrom instanceof TupleNode and
c.(TupleElementContent).getIndex() = index
)
)
}
/** Data flows from an iterable to an assigned variable. */
predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
// iterable unpacking
// `a, (b, c) = iterable`
// nodeFrom is `iterable`, cfg node
// nodeTo is `a`, essa var
// or `(b, c)`, cfg node
// c is compatible with `a`s (or `(b, c)`s) index
exists(ControlFlowNode readNode | unpackingAssignmentRead(nodeFrom, c, readNode) |
(
readNode instanceof SequenceNode and
nodeTo.asCfgNode() = readNode
or
not readNode instanceof SequenceNode and
nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readNode
)
)
or
unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo)
}
import unpackinAssignment
/** Data flows from a sequence to a call to `pop` on the sequence. */
predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {

View File

@@ -60,6 +60,17 @@ newtype TNode =
*/
TKwUnpacked(CallNode call, CallableValue callable, string name) {
call_unpacks(call, _, callable, name, _)
} or
/**
* A synthetic node representing that there may be an iterable element
* for `consumer` to consume.
*/
TIterableElement(SequenceNode consumer) {
exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() |
consumer = target
or
consumer = target.getAnElement() // use containts for deeper nesting
)
}
/** Helper for `Node::getEnclosingCallable`. */
@@ -319,6 +330,20 @@ class KwUnpacked extends Node, TKwUnpacked {
override Location getLocation() { result = call.getLocation() }
}
/**
* A synthetic node representing an iterable element. Use for changing content type
* for instance from a `ListElement` to a `TupleElement`.
*/
class IterableElement extends Node, TIterableElement {
SequenceNode consumer;
IterableElement() { this = TIterableElement(consumer) }
override string toString() { result = "IterableElement" }
override Location getLocation() { result = consumer.getLocation() }
}
/**
* A node that controls whether other nodes are evaluated.
*/

View File

@@ -65,6 +65,9 @@ edges
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE |
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE |
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE |
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:12:555:17 | ControlFlowNode for SOURCE |
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:31:555:36 | ControlFlowNode for SOURCE |
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:41:555:46 | ControlFlowNode for SOURCE |
| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:651:16:651:21 | ControlFlowNode for SOURCE |
| test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test |
| test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE |
@@ -185,24 +188,89 @@ edges
| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a |
| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b |
| test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] |
| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a |
| test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a |
| test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a |
| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:30:529:35 | ControlFlowNode for SOURCE |
| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] |
| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] |
| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
| test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a |
| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a |
| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c |
| test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c |
| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a |
| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] |
| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a |
| test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a |
| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a |
| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] |
| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] |
| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] |
| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] |
| test.py:555:11:555:37 | ControlFlowNode for List [List element] | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] |
| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:11:555:37 | ControlFlowNode for List [List element] |
| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:31:555:36 | ControlFlowNode for SOURCE |
| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:41:555:46 | ControlFlowNode for SOURCE |
| test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:555:11:555:37 | ControlFlowNode for List [List element] |
| test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:555:41:555:46 | ControlFlowNode for SOURCE |
| test.py:555:40:555:47 | ControlFlowNode for List [List element] | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] |
| test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:555:40:555:47 | ControlFlowNode for List [List element] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] |
| test.py:558:6:558:23 | IterableElement [List element] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
| test.py:558:7:558:8 | SSA variable a1 | test.py:559:10:559:11 | ControlFlowNode for a1 |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | test.py:558:7:558:16 | IterableElement |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:7:558:8 | SSA variable a1 |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:11:558:12 | SSA variable a2 |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:558:15:558:16 | SSA variable a3 |
| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] |
| test.py:558:11:558:12 | SSA variable a2 | test.py:560:12:560:13 | ControlFlowNode for a2 |
| test.py:558:15:558:16 | SSA variable a3 | test.py:561:10:561:11 | ControlFlowNode for a3 |
| test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | test.py:558:6:558:23 | IterableElement [List element] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] |
| test.py:566:5:566:24 | IterableElement [List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] |
| test.py:566:7:566:8 | SSA variable a1 | test.py:567:10:567:11 | ControlFlowNode for a1 |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | test.py:566:7:566:16 | IterableElement |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:566:7:566:8 | SSA variable a1 |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:566:11:566:12 | SSA variable a2 |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:566:15:566:16 | SSA variable a3 |
| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] |
| test.py:566:11:566:12 | SSA variable a2 | test.py:568:12:568:13 | ControlFlowNode for a2 |
| test.py:566:15:566:16 | SSA variable a3 | test.py:569:10:569:11 | ControlFlowNode for a3 |
| test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | test.py:566:5:566:24 | IterableElement [List element] |
| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:6:574:17 | IterableElement |
| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:7:574:8 | SSA variable a1 |
| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:11:574:12 | SSA variable a2 |
| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:15:574:16 | SSA variable a3 |
| test.py:574:6:574:17 | IterableElement | test.py:574:6:574:17 | ControlFlowNode for List [List element] |
| test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:574:6:574:17 | ControlFlowNode for List [List element] |
| test.py:574:6:574:23 | IterableElement [List element] | test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
| test.py:574:7:574:8 | SSA variable a1 | test.py:575:10:575:11 | ControlFlowNode for a1 |
| test.py:574:11:574:12 | SSA variable a2 | test.py:576:12:576:13 | ControlFlowNode for a2 |
| test.py:574:15:574:16 | SSA variable a3 | test.py:577:10:577:11 | ControlFlowNode for a3 |
| test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | test.py:574:6:574:23 | IterableElement [List element] |
| test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() |
nodes
| datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel |
@@ -383,7 +451,7 @@ nodes
| test.py:521:10:521:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:522:5:522:5 | SSA variable a | semmle.label | SSA variable a |
| test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] |
| test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
| test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
@@ -391,17 +459,68 @@ nodes
| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:529:30:529:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a |
| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] |
| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:530:12:530:12 | SSA variable c | semmle.label | SSA variable c |
| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] |
| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] |
| test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
| test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c |
| test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a |
| test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] |
| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a |
| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] |
| test.py:555:11:555:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:555:12:555:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:555:31:555:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:555:40:555:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:555:41:555:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] |
| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] |
| test.py:558:6:558:23 | IterableElement [List element] | semmle.label | IterableElement [List element] |
| test.py:558:7:558:8 | SSA variable a1 | semmle.label | SSA variable a1 |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
| test.py:558:7:558:16 | IterableElement | semmle.label | IterableElement |
| test.py:558:11:558:12 | SSA variable a2 | semmle.label | SSA variable a2 |
| test.py:558:15:558:16 | SSA variable a3 | semmle.label | SSA variable a3 |
| test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] |
| test.py:559:10:559:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
| test.py:560:12:560:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 |
| test.py:561:10:561:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] |
| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] |
| test.py:566:5:566:24 | IterableElement [List element] | semmle.label | IterableElement [List element] |
| test.py:566:7:566:8 | SSA variable a1 | semmle.label | SSA variable a1 |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] |
| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] |
| test.py:566:7:566:16 | IterableElement | semmle.label | IterableElement |
| test.py:566:11:566:12 | SSA variable a2 | semmle.label | SSA variable a2 |
| test.py:566:15:566:16 | SSA variable a3 | semmle.label | SSA variable a3 |
| test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] |
| test.py:567:10:567:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
| test.py:568:12:568:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 |
| test.py:569:10:569:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 |
| test.py:574:6:574:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| test.py:574:6:574:17 | IterableElement | semmle.label | IterableElement |
| test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] |
| test.py:574:6:574:23 | IterableElement [List element] | semmle.label | IterableElement [List element] |
| test.py:574:7:574:8 | SSA variable a1 | semmle.label | SSA variable a1 |
| test.py:574:11:574:12 | SSA variable a2 | semmle.label | SSA variable a2 |
| test.py:574:15:574:16 | SSA variable a3 | semmle.label | SSA variable a3 |
| test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] |
| test.py:575:10:575:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 |
| test.py:576:12:576:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 |
| test.py:577:10:577:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 |
| test.py:651:16:651:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() |
#select
@@ -510,5 +629,41 @@ nodes
| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found |
| test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found |
| test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found |
| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found |
| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found |
| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found |
| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found |
| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found |
| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found |
| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found |
| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found |
| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found |
| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found |
| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found |
| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found |
| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found |
| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found |
| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found |
| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found |
| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found |
| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found |
| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found |
| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found |
| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found |
| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found |
| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found |
| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found |
| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found |
| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found |
| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found |
| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found |
| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found |
| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found |
| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found |
| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found |
| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found |
| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found |
| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found |
| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found |
| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found |
| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found |

View File

@@ -556,25 +556,25 @@ def test_unpacking_assignment_conversion():
# tuple
((a1, a2, a3), b, c) = ll
SINK(a1) # Flow not found
SINK(a1)
SINK_F(a2) # We expect an FP as all elements are tainted
SINK(a3) # Flow not found
SINK(a3)
SINK_F(b) # The list itself is not tainted
SINK_F(c)
# mixed
[(a1, a2, a3), b, c] = ll
SINK(a1) # Flow not found
SINK(a1)
SINK_F(a2) # We expect an FP as all elements are tainted
SINK(a3) # Flow not found
SINK(a3)
SINK_F(b) # The list itself is not tainted
SINK_F(c)
# mixed differently
([a1, a2, a3], b, c) = ll
SINK(a1) # Flow not found
SINK(a1)
SINK_F(a2) # We expect an FP as all elements are tainted
SINK(a3) # Flow not found
SINK(a3)
SINK_F(b) # The list itself is not tainted
SINK_F(c)