diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll index 95c72ef7e14..ef1aff9ad1d 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll @@ -220,15 +220,32 @@ predicate jumpStep(Node pred, Node succ) { // Field flow //-------- /** - * Holds if data can flow from `node1` to `node2` via an assignment to + * Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to * content `c`. */ -predicate storeStep(Node node1, Content c, Node node2) { none() } +predicate storeStep(Node nodeFrom, Content c, Node nodeTo) { + // Definition + // `x = (..., 42, ...)` + // or + // `x = [..., 42, ...]` + // nodeFrom is `f(42)`, cfg node + // nodeTo is `x`, essa var + exists(SequenceNode s | + nodeFrom.(CfgNode).getNode() = s.getAnElement() and + nodeTo.(EssaNode).getVar().getDefinition().(AssignmentDefinition).getValue() = s + ) +} /** - * Holds if data can flow from `node1` to `node2` via a read of content `c`. + * Holds if data can flow from `nodeFrom` to `nodeTo` via a read of content `c`. */ -predicate readStep(Node node1, Content c, Node node2) { none() } +predicate readStep(Node nodeFrom, Content c, Node nodeTo) { + // Subscription + // `l[3]` + // nodeFrom is `l` + // nodeTo is `l[3]` + nodeFrom.(CfgNode).getNode() = nodeTo.(CfgNode).getNode().(SubscriptNode).getObject() +} /** * Holds if values stored inside content `c` are cleared at node `n`. For example, diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 041cbdfd8dd..0b2a081d75c 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,13 +1,25 @@ edges +| test.py:17:5:17:5 | SSA variable x [Content] | test.py:18:9:18:9 | ControlFlowNode for x [Content] | +| test.py:17:13:17:18 | ControlFlowNode for SOURCE | test.py:17:5:17:5 | SSA variable x [Content] | +| test.py:18:9:18:9 | ControlFlowNode for x [Content] | test.py:18:9:18:12 | ControlFlowNode for Subscript | +| test.py:18:9:18:12 | ControlFlowNode for Subscript | test.py:19:10:19:10 | ControlFlowNode for y | | test.py:23:9:23:14 | ControlFlowNode for SOURCE | test.py:24:10:24:10 | ControlFlowNode for x | | test.py:28:9:28:16 | ControlFlowNode for Str | test.py:29:10:29:10 | ControlFlowNode for x | | test.py:32:9:32:17 | ControlFlowNode for Str | test.py:33:10:33:10 | ControlFlowNode for x | | test.py:36:9:36:10 | ControlFlowNode for IntegerLiteral | test.py:37:10:37:10 | ControlFlowNode for x | | test.py:40:9:40:12 | ControlFlowNode for FloatLiteral | test.py:41:10:41:10 | ControlFlowNode for x | | test.py:49:10:49:15 | ControlFlowNode for SOURCE | test.py:50:10:50:10 | ControlFlowNode for x | +| test.py:54:5:54:5 | SSA variable x [Content] | test.py:55:10:55:10 | ControlFlowNode for x [Content] | +| test.py:54:10:54:15 | ControlFlowNode for SOURCE | test.py:54:5:54:5 | SSA variable x [Content] | +| test.py:55:10:55:10 | ControlFlowNode for x [Content] | test.py:55:10:55:13 | ControlFlowNode for Subscript | | test.py:226:15:226:20 | ControlFlowNode for SOURCE | test.py:226:10:226:21 | ControlFlowNode for f() | | test.py:282:12:282:17 | ControlFlowNode for SOURCE | test.py:282:10:282:18 | ControlFlowNode for f() | nodes +| test.py:17:5:17:5 | SSA variable x [Content] | semmle.label | SSA variable x [Content] | +| test.py:17:13:17:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:18:9:18:9 | ControlFlowNode for x [Content] | semmle.label | ControlFlowNode for x [Content] | +| test.py:18:9:18:12 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:19:10:19:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | | test.py:23:9:23:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:24:10:24:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | | test.py:28:9:28:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | @@ -20,16 +32,22 @@ nodes | test.py:41:10:41:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | | test.py:49:10:49:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:50:10:50:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:54:5:54:5 | SSA variable x [Content] | semmle.label | SSA variable x [Content] | +| test.py:54:10:54:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:55:10:55:10 | ControlFlowNode for x [Content] | semmle.label | ControlFlowNode for x [Content] | +| test.py:55:10:55:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:226:10:226:21 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | | test.py:226:15:226:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:282:10:282:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | | test.py:282:12:282:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | #select +| test.py:19:10:19:10 | ControlFlowNode for y | test.py:17:13:17:18 | ControlFlowNode for SOURCE | test.py:19:10:19:10 | ControlFlowNode for y | | | test.py:24:10:24:10 | ControlFlowNode for x | test.py:23:9:23:14 | ControlFlowNode for SOURCE | test.py:24:10:24:10 | ControlFlowNode for x | | | test.py:29:10:29:10 | ControlFlowNode for x | test.py:28:9:28:16 | ControlFlowNode for Str | test.py:29:10:29:10 | ControlFlowNode for x | | | test.py:33:10:33:10 | ControlFlowNode for x | test.py:32:9:32:17 | ControlFlowNode for Str | test.py:33:10:33:10 | ControlFlowNode for x | | | test.py:37:10:37:10 | ControlFlowNode for x | test.py:36:9:36:10 | ControlFlowNode for IntegerLiteral | test.py:37:10:37:10 | ControlFlowNode for x | | | test.py:41:10:41:10 | ControlFlowNode for x | test.py:40:9:40:12 | ControlFlowNode for FloatLiteral | test.py:41:10:41:10 | ControlFlowNode for x | | | test.py:50:10:50:10 | ControlFlowNode for x | test.py:49:10:49:15 | ControlFlowNode for SOURCE | test.py:50:10:50:10 | ControlFlowNode for x | | +| test.py:55:10:55:13 | ControlFlowNode for Subscript | test.py:54:10:54:15 | ControlFlowNode for SOURCE | test.py:55:10:55:13 | ControlFlowNode for Subscript | | | test.py:226:10:226:21 | ControlFlowNode for f() | test.py:226:15:226:20 | ControlFlowNode for SOURCE | test.py:226:10:226:21 | ControlFlowNode for f() | | | test.py:282:10:282:18 | ControlFlowNode for f() | test.py:282:12:282:17 | ControlFlowNode for SOURCE | test.py:282:10:282:18 | ControlFlowNode for f() | |