Skip to content

Commit 9bd5694

Browse files
committed
Python: Add tests of path-graph for dataflow/taint-tracking
Although this is actually using taint-tracking (so we can use the += statement), I would personally forget to check under the dataflow/tainttracking folder to look for such a test, so I'm opting to keep it under the dataflow/ folder.
1 parent 01ff690 commit 9bd5694

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
failures
2+
testFailures
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @kind path-problem
3+
*/
4+
5+
import python
6+
import semmle.python.dataflow.new.DataFlow
7+
import semmle.python.dataflow.new.TaintTracking
8+
import experimental.dataflow.testConfig
9+
import TestUtilities.InlineExpectationsTest
10+
11+
module TestTaintFlow = TaintTracking::Global<TestConfig>;
12+
13+
module PathNodeTest implements TestSig {
14+
string getARelevantTag() { result = "path-node" }
15+
16+
predicate hasActualResult(Location location, string element, string tag, string value) {
17+
exists(TestTaintFlow::PathNode pn |
18+
location = pn.getNode().getLocation() and
19+
tag = "path-node" and
20+
value = "" and
21+
element = pn.toString()
22+
)
23+
}
24+
}
25+
26+
import MakeTest<PathNodeTest>
27+
// running the query to inspect the results can be quite nice!
28+
// just uncomment these lines!
29+
// import TestTaintFlow::PathGraph
30+
// from TestTaintFlow::PathNode source, TestTaintFlow::PathNode sink
31+
// where TestTaintFlow::flowPath(source, sink)
32+
// select sink.getNode(), source, sink,
33+
// sink.getNode().getEnclosingCallable().toString() + ": --> " +
34+
// sink.getNode().getLocation().getStartLine().toString()
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
def assign():
2+
x = SOURCE # $ path-node
3+
4+
y = x
5+
6+
SINK(y) # $ path-node
7+
8+
9+
def aug_assign():
10+
x = SOURCE # $ path-node
11+
z = ""
12+
13+
z += x
14+
15+
SINK(z) # $ path-node
16+
17+
18+
def dont_use_rhs(cond):
19+
# liked noted in the original Ruby PR: https://github.com/github/codeql/pull/12566
20+
x = SOURCE # $ path-node
21+
22+
if cond:
23+
y = x
24+
25+
SINK(x) # $ path-node
26+
27+
28+
def flow_through_function():
29+
def identify(x): # $ path-node
30+
return x # $ path-node
31+
32+
x = SOURCE # $ path-node
33+
34+
y = identify(x) # $ path-node
35+
36+
SINK(y) # $ path-node
37+
38+
39+
def attribute():
40+
class X: pass
41+
x = X()
42+
x.attr = SOURCE # $ path-node
43+
44+
y = x
45+
46+
SINK(y.attr) # $ path-node
47+
48+
49+
def list_loop():
50+
x = SOURCE # $ path-node
51+
l = list()
52+
53+
l.append(x) # $ path-node
54+
55+
for y in l: # $ path-node
56+
57+
SINK(y) # $ path-node
58+
59+
60+
def list_index():
61+
x = SOURCE # $ path-node
62+
l = list()
63+
64+
l.append(x) # $ path-node
65+
66+
z = l[0] # $ path-node
67+
68+
SINK(z) # $ path-node
69+
70+
71+
def test_tuple():
72+
x = SOURCE # $ path-node
73+
74+
y = ((x, 1), 2) # $ path-node
75+
76+
(z, _), _ = y # $ path-node
77+
78+
SINK(z) # $ path-node
79+
80+
81+
def test_with():
82+
x = SOURCE # $ path-node
83+
84+
with x as y:
85+
86+
SINK(y) # $ path-node
87+
88+
89+
def test_match():
90+
x = SOURCE # $ path-node
91+
92+
match x:
93+
94+
case y:
95+
96+
SINK(y) # $ path-node

0 commit comments

Comments
 (0)