Skip to content

Commit 9a821bf

Browse files
authored
Merge pull request #4 from yoff/RasmusWL-python-more-complete-dataflow-tests
Python: Annotate test file
2 parents 654c4f3 + aad51af commit 9a821bf

File tree

4 files changed

+59
-53
lines changed

4 files changed

+59
-53
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.py:126:13:126:25 | ControlFlowNode for CUSTOM_SOURCE | test.py:130:21:130:21 | ControlFlowNode for t |
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* This query is meant to catch the flows from `CUSTOM_SOURCE` to `CUSTOM_SINK`.
3+
*
4+
* This should be compared to
5+
* python/ql/test/library-tests/taint/dataflow/Dataflow.ql
6+
* A first goal is to have identical results; after that we
7+
* hope to remove the false positive.
8+
*/
9+
10+
import experimental.dataflow.DataFlow
11+
12+
class CustomTestConfiguration extends DataFlow::Configuration {
13+
CustomTestConfiguration() { this = "CustomTestConfiguration" }
14+
15+
override predicate isSource(DataFlow::Node node) {
16+
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "CUSTOM_SOURCE"
17+
}
18+
19+
override predicate isSink(DataFlow::Node node) {
20+
exists(CallNode call |
21+
call.getFunction().(NameNode).getId() in ["CUSTOM_SINK", "CUSTOM_SINK_F"] and
22+
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
23+
)
24+
}
25+
}
26+
27+
from DataFlow::Node source, DataFlow::Node sink
28+
where exists(CustomTestConfiguration cfg | cfg.hasFlow(source, sink))
29+
select source, sink

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,10 @@
1010
| test.py:76:9:76:14 | ControlFlowNode for SOURCE | test.py:78:10:78:10 | ControlFlowNode for t |
1111
| test.py:128:13:128:18 | ControlFlowNode for SOURCE | test.py:132:14:132:14 | ControlFlowNode for t |
1212
| test.py:159:10:159:15 | ControlFlowNode for SOURCE | test.py:160:14:160:14 | ControlFlowNode for t |
13-
| test.py:163:9:163:14 | ControlFlowNode for SOURCE | test.py:165:10:165:10 | ControlFlowNode for s |
13+
| test.py:163:9:163:14 | ControlFlowNode for SOURCE | test.py:165:12:165:12 | ControlFlowNode for s |
1414
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:180:14:180:14 | ControlFlowNode for t |
15-
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:182:14:182:14 | ControlFlowNode for t |
16-
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:184:14:184:14 | ControlFlowNode for t |
15+
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:182:16:182:16 | ControlFlowNode for t |
16+
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:184:16:184:16 | ControlFlowNode for t |
1717
| test.py:178:9:178:14 | ControlFlowNode for SOURCE | test.py:186:14:186:14 | ControlFlowNode for t |
1818
| test.py:195:9:195:14 | ControlFlowNode for SOURCE | test.py:197:14:197:14 | ControlFlowNode for t |
1919
| test.py:195:9:195:14 | ControlFlowNode for SOURCE | test.py:199:14:199:14 | ControlFlowNode for t |
20-
| test.py:217:15:217:20 | ControlFlowNode for SOURCE | test.py:219:14:219:20 | ControlFlowNode for tainted |
21-
| test.py:217:15:217:20 | ControlFlowNode for SOURCE | test.py:220:10:220:16 | ControlFlowNode for tainted |
22-
| test.py:223:15:223:20 | ControlFlowNode for SOURCE | test.py:226:10:226:16 | ControlFlowNode for tainted |
23-
| test.py:229:15:229:20 | ControlFlowNode for SOURCE | test.py:231:14:231:20 | ControlFlowNode for tainted |
24-
| test.py:229:15:229:20 | ControlFlowNode for SOURCE | test.py:233:14:233:20 | ControlFlowNode for tainted |

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

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test6(cond):
3030
else:
3131
t = SOURCE
3232
if cond:
33-
SINK(t)
33+
SINK_F(t)
3434

3535
def test7(cond):
3636
if cond:
@@ -40,8 +40,8 @@ def test7(cond):
4040
if cond:
4141
SINK(t)
4242

43-
def source2(arg):
44-
return source(arg)
43+
def source2():
44+
return source()
4545

4646
def sink2(arg):
4747
sink(arg)
@@ -50,7 +50,7 @@ def sink3(cond, arg):
5050
if cond:
5151
sink(arg)
5252

53-
def test8(cond):
53+
def test8(cond): # This test currently adds nothing, as we only track SOURCE -> SINK, and previous tests already add flow from line 10 to line 13
5454
t = source2()
5555
sink2(t)
5656

@@ -80,21 +80,21 @@ def test11():
8080
def test12():
8181
t = "safe"
8282
t = hub(t)
83-
SINK(t)
83+
SINK_F(t)
8484

8585
import module
8686

8787
def test13():
8888
t = module.dangerous
89-
SINK(t)
89+
SINK(t) # Flow not found
9090

9191
def test14():
9292
t = module.safe
93-
SINK(t)
93+
SINK_F(t)
9494

9595
def test15():
9696
t = module.safe2
97-
SINK(t)
97+
SINK_F(t)
9898

9999
def test16():
100100
t = module.dangerous_func()
@@ -108,13 +108,13 @@ def x_sink(arg):
108108
def test17():
109109
t = C()
110110
t.x = module.dangerous
111-
SINK(t.x)
111+
SINK(t.x) # Flow not found
112112

113113
def test18():
114114
t = C()
115115
t.x = module.dangerous
116116
t = hub(t)
117-
x_sink(t)
117+
x_sink(t) # Flow not found
118118

119119
def test19():
120120
t = CUSTOM_SOURCE
@@ -137,40 +137,40 @@ def test21(cond):
137137
else:
138138
t = SOURCE
139139
if not cond:
140-
CUSTOM_SINK(t)
140+
CUSTOM_SINK_F(t)
141141
else:
142-
SINK(t)
142+
SINK_F(t)
143143

144144
def test22(cond):
145145
if cond:
146146
t = CUSTOM_SOURCE
147147
else:
148148
t = SOURCE
149-
t = TAINT_FROM_ARG(t)
149+
t = TAINT_FROM_ARG(t) # Blocks data flow
150150
if cond:
151151
CUSTOM_SINK(t)
152152
else:
153153
SINK(t)
154154

155155
from module import dangerous as unsafe
156-
SINK(unsafe)
156+
SINK(unsafe) # Flow not found
157157

158158
def test23():
159159
with SOURCE as t:
160160
SINK(t)
161161

162162
def test24():
163163
s = SOURCE
164-
SANITIZE(s)
165-
SINK(s)
164+
SANITIZE(s) # Does not block data flow
165+
SINK_F(s)
166166

167167
def test_update_extend(x, y):
168168
l = [SOURCE]
169169
d = {"key" : SOURCE}
170170
x.extend(l)
171171
y.update(d)
172-
SINK(x[0])
173-
SINK(y["key"])
172+
SINK(x[0]) # Flow not found
173+
SINK(y["key"]) # Flow not found
174174
l2 = list(l)
175175
d2 = dict(d)
176176

@@ -179,9 +179,9 @@ def test_truth():
179179
if t:
180180
SINK(t)
181181
else:
182-
SINK(t)
182+
SINK_F(t) # False positive
183183
if not t:
184-
SINK(t)
184+
SINK_F(t) # False positive
185185
else:
186186
SINK(t)
187187

@@ -194,15 +194,15 @@ def test_early_exit():
194194
def flow_through_type_test_if_no_class():
195195
t = SOURCE
196196
if isinstance(t, str):
197-
SINK(t)
197+
SINK(t) # Flows's both here..
198198
else:
199-
SINK(t)
199+
SINK(t) # ..and here
200200

201201
def flow_in_iteration():
202-
t = ITERABLE_SOURCE
202+
t = [SOURCE]
203203
for i in t:
204-
i
205-
return i
204+
SINK(i) # Flow not found
205+
SINK(i) # Flow not found
206206

207207
def flow_in_generator():
208208
seq = [SOURCE]
@@ -211,23 +211,4 @@ def flow_in_generator():
211211

212212
def flow_from_generator():
213213
for x in flow_in_generator():
214-
SINK(x)
215-
216-
def const_eq_clears_taint():
217-
tainted = SOURCE
218-
if tainted == "safe":
219-
SINK(tainted) # safe
220-
SINK(tainted) # unsafe
221-
222-
def const_eq_clears_taint2():
223-
tainted = SOURCE
224-
if tainted != "safe":
225-
return
226-
SINK(tainted) # safe
227-
228-
def non_const_eq_preserves_taint(x):
229-
tainted = SOURCE
230-
if tainted == tainted:
231-
SINK(tainted) # unsafe
232-
if tainted == x:
233-
SINK(tainted) # unsafe
214+
SINK(x) # Flow not found

0 commit comments

Comments
 (0)