Skip to content

Commit 5973fe8

Browse files
committed
Python: scaffold for testing data flow coverage
1 parent c70cf6d commit 5973fe8

8 files changed

Lines changed: 69 additions & 17 deletions

File tree

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

Whitespace-only changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import experimental.dataflow.testConfig
2+
3+
from
4+
DataFlow::Node source,
5+
DataFlow::Node sink
6+
where
7+
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
8+
select
9+
source, sink
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| test.py:13:5:13:5 | SSA variable x | test.py:12:1:12:33 | Exit node for Function test_tuple_with_local_flow |
2+
| test.py:13:5:13:5 | SSA variable x | test.py:14:9:14:9 | ControlFlowNode for x |
3+
| test.py:13:10:13:18 | ControlFlowNode for Tuple | test.py:13:5:13:5 | SSA variable x |
4+
| test.py:14:5:14:5 | SSA variable y | test.py:15:5:15:11 | SSA variable y |
5+
| test.py:14:5:14:5 | SSA variable y | test.py:15:10:15:10 | ControlFlowNode for y |
6+
| test.py:14:9:14:12 | ControlFlowNode for Subscript | test.py:14:5:14:5 | SSA variable y |
7+
| test.py:15:5:15:11 | SSA variable y | test.py:12:1:12:33 | Exit node for Function test_tuple_with_local_flow |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import python
2+
import experimental.dataflow.DataFlow
3+
4+
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
5+
where
6+
DataFlow::localFlowStep(nodeFrom, nodeTo) and
7+
nodeFrom.getEnclosingCallable().getName().matches("%\\_with\\_local\\_flow")
8+
select nodeFrom, nodeTo
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This should cover all the syntactical constructs that we hope to support
2+
# Intended sources should be the variable `SOUCE` and intended sinks should be
3+
# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll).
4+
#
5+
# Functions whose name ends with "_with_local_flow" will also be tested for local flow.
6+
7+
# Uncomment these to test the test code
8+
# SOURCE = 42
9+
# def SINK(x):
10+
# return 42
11+
12+
def test_tuple_with_local_flow():
13+
x = (3, SOURCE)
14+
y = x[1]
15+
SINK(y)

python/ql/test/experimental/dataflow/regression/config.qll

Lines changed: 0 additions & 16 deletions
This file was deleted.

python/ql/test/experimental/dataflow/regression/dataflow.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* hope to remove the false positive.
66
*/
77

8-
import config
8+
import experimental.dataflow.testConfig
99

1010
from
1111
DataFlow::Node source,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Configuration to test selected data flow
3+
* Sources in the source code are denoted by the special name `SOURCE`,
4+
* and sinks are denoted by arguments to the special function `SINK`.
5+
* For example, given the test code
6+
* ```python
7+
* def test():
8+
* s = SOURCE
9+
* SINK(s)
10+
* ```
11+
* `SOURCE` will be a source and the second occurance of `s` will be a sink.
12+
*/
13+
14+
import experimental.dataflow.DataFlow
15+
16+
class TestConfiguration extends DataFlow::Configuration {
17+
TestConfiguration() { this = "TestConfiguration" }
18+
19+
override predicate isSource(DataFlow::Node node) {
20+
node.asCfgNode().(NameNode).getId() = "SOURCE"
21+
}
22+
23+
override predicate isSink(DataFlow::Node node) {
24+
exists(CallNode call |
25+
call.getFunction().(NameNode).getId() = "SINK" and
26+
node.asCfgNode() = call.getAnArg()
27+
)
28+
}
29+
}

0 commit comments

Comments
 (0)