Skip to content

Commit e468d49

Browse files
committed
Python: routing tests 3-7 and some annotations
1 parent 4fe2576 commit e468d49

File tree

3 files changed

+189
-8
lines changed

3 files changed

+189
-8
lines changed

python/ql/test/experimental/dataflow/coverage/argumentPassing.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ def argument_passing(
7474
):
7575
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:89 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:94 -> ControlFlowNode for a"
7676
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:94 -> ControlFlowNode for b" MISSING:arg2="ControlFlowNode for arg2, l:89 -> ControlFlowNode for b"
77-
SINK3(c)
78-
SINK4(d)
79-
SINK5(e)
80-
SINK6(f)
77+
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:94 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:89 -> ControlFlowNode for c"
78+
SINK4(d) #$ MISSING: arg4="ControlFlowNode for arg4, l:89 -> ControlFlowNode for d"
79+
SINK5(e) #$ MISSING: arg5="ControlFlowNode for arg5, l:89 -> ControlFlowNode for e"
80+
SINK6(f) #$ MISSING: arg6="ControlFlowNode for arg6, l:89 -> ControlFlowNode for f"
8181
try:
82-
SINK7(g["g"])
82+
SINK7(g["g"]) #$ arg7="ControlFlowNode for arg7, l:89 -> ControlFlowNode for Subscript"
8383
except:
8484
print("OK")
8585

@@ -109,7 +109,7 @@ def test_pos_only():
109109
def with_multiple_kw_args(a, b, c):
110110
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:117 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:118 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:119 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:120 -> ControlFlowNode for a"
111111
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:117 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:120 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:118 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:119 -> ControlFlowNode for b"
112-
SINK3(c)
112+
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:117 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:119 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:120 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:118 -> ControlFlowNode for c"
113113

114114

115115
@expects(9)
@@ -123,7 +123,7 @@ def test_multiple_kw_args():
123123
def with_default_arguments(a=arg1, b=arg2, c=arg3):
124124
SINK1(a) #$ arg1="ControlFlowNode for arg1, l:132 -> ControlFlowNode for a" MISSING:arg1="ControlFlowNode for arg1, l:123 -> ControlFlowNode for a"
125125
SINK2(b) #$ arg2="ControlFlowNode for arg2, l:133 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:123 -> ControlFlowNode for b"
126-
SINK3(c)
126+
SINK3(c) #$ arg3="ControlFlowNode for arg3, l:134 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:123 -> ControlFlowNode for c"
127127

128128

129129
@expects(12)
@@ -152,7 +152,7 @@ def grab_bar_baz(bar, **kwargs):
152152

153153

154154
def grab_baz(baz):
155-
SINK3(baz)
155+
SINK3(baz) #$ arg3="ControlFlowNode for arg3, l:160 -> ControlFlowNode for baz"
156156

157157

158158
@expects(4)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
| classes.py:556:15:556:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" |
22
| classes.py:557:15:557:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" |
3+
| classes.py:571:15:571:19 | ControlFlowNode for value | Unexpected result: arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value" |
34
| classes.py:572:15:572:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" |
45
| classes.py:573:15:573:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" |
56
| classes.py:587:15:587:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" |

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

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,183 @@ class Argument2RoutingConfig extends DataFlow::Configuration {
8181
*/
8282
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
8383
}
84+
85+
class Argument3RoutingTest extends FlowTest {
86+
Argument3RoutingTest() { this = "Argument3RoutingTest" }
87+
88+
override string flowTag() { result = "arg3" }
89+
90+
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
91+
exists(Argument3RoutingConfig cfg | cfg.hasFlow(source, sink))
92+
}
93+
}
94+
95+
/**
96+
* A configuration to check routing of arguments through magic methods.
97+
*/
98+
class Argument3RoutingConfig extends DataFlow::Configuration {
99+
Argument3RoutingConfig() { this = "Argument3RoutingConfig" }
100+
101+
override predicate isSource(DataFlow::Node node) {
102+
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg3"
103+
}
104+
105+
override predicate isSink(DataFlow::Node node) {
106+
exists(CallNode call |
107+
call.getFunction().(NameNode).getId() = "SINK3" and
108+
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
109+
)
110+
}
111+
112+
/**
113+
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
114+
* Use-use flow lets the argument to the first call reach the sink inside the second call,
115+
* making it seem like we handle all cases even if we only handle the last one.
116+
* We make the test honest by preventing flow into source nodes.
117+
*/
118+
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
119+
}
120+
121+
class Argument4RoutingTest extends FlowTest {
122+
Argument4RoutingTest() { this = "Argument4RoutingTest" }
123+
124+
override string flowTag() { result = "arg4" }
125+
126+
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
127+
exists(Argument4RoutingConfig cfg | cfg.hasFlow(source, sink))
128+
}
129+
}
130+
131+
/**
132+
* A configuration to check routing of arguments through magic methods.
133+
*/
134+
class Argument4RoutingConfig extends DataFlow::Configuration {
135+
Argument4RoutingConfig() { this = "Argument4RoutingConfig" }
136+
137+
override predicate isSource(DataFlow::Node node) {
138+
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg4"
139+
}
140+
141+
override predicate isSink(DataFlow::Node node) {
142+
exists(CallNode call |
143+
call.getFunction().(NameNode).getId() = "SINK4" and
144+
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
145+
)
146+
}
147+
148+
/**
149+
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
150+
* Use-use flow lets the argument to the first call reach the sink inside the second call,
151+
* making it seem like we handle all cases even if we only handle the last one.
152+
* We make the test honest by preventing flow into source nodes.
153+
*/
154+
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
155+
}
156+
157+
class Argument5RoutingTest extends FlowTest {
158+
Argument5RoutingTest() { this = "Argument5RoutingTest" }
159+
160+
override string flowTag() { result = "arg5" }
161+
162+
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
163+
exists(Argument5RoutingConfig cfg | cfg.hasFlow(source, sink))
164+
}
165+
}
166+
167+
/**
168+
* A configuration to check routing of arguments through magic methods.
169+
*/
170+
class Argument5RoutingConfig extends DataFlow::Configuration {
171+
Argument5RoutingConfig() { this = "Argument5RoutingConfig" }
172+
173+
override predicate isSource(DataFlow::Node node) {
174+
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg5"
175+
}
176+
177+
override predicate isSink(DataFlow::Node node) {
178+
exists(CallNode call |
179+
call.getFunction().(NameNode).getId() = "SINK5" and
180+
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
181+
)
182+
}
183+
184+
/**
185+
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
186+
* Use-use flow lets the argument to the first call reach the sink inside the second call,
187+
* making it seem like we handle all cases even if we only handle the last one.
188+
* We make the test honest by preventing flow into source nodes.
189+
*/
190+
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
191+
}
192+
193+
class Argument6RoutingTest extends FlowTest {
194+
Argument6RoutingTest() { this = "Argument6RoutingTest" }
195+
196+
override string flowTag() { result = "arg6" }
197+
198+
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
199+
exists(Argument6RoutingConfig cfg | cfg.hasFlow(source, sink))
200+
}
201+
}
202+
203+
/**
204+
* A configuration to check routing of arguments through magic methods.
205+
*/
206+
class Argument6RoutingConfig extends DataFlow::Configuration {
207+
Argument6RoutingConfig() { this = "Argument6RoutingConfig" }
208+
209+
override predicate isSource(DataFlow::Node node) {
210+
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg6"
211+
}
212+
213+
override predicate isSink(DataFlow::Node node) {
214+
exists(CallNode call |
215+
call.getFunction().(NameNode).getId() = "SINK6" and
216+
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
217+
)
218+
}
219+
220+
/**
221+
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
222+
* Use-use flow lets the argument to the first call reach the sink inside the second call,
223+
* making it seem like we handle all cases even if we only handle the last one.
224+
* We make the test honest by preventing flow into source nodes.
225+
*/
226+
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
227+
}
228+
229+
class Argument7RoutingTest extends FlowTest {
230+
Argument7RoutingTest() { this = "Argument7RoutingTest" }
231+
232+
override string flowTag() { result = "arg7" }
233+
234+
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
235+
exists(Argument7RoutingConfig cfg | cfg.hasFlow(source, sink))
236+
}
237+
}
238+
239+
/**
240+
* A configuration to check routing of arguments through magic methods.
241+
*/
242+
class Argument7RoutingConfig extends DataFlow::Configuration {
243+
Argument7RoutingConfig() { this = "Argument7RoutingConfig" }
244+
245+
override predicate isSource(DataFlow::Node node) {
246+
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg7"
247+
}
248+
249+
override predicate isSink(DataFlow::Node node) {
250+
exists(CallNode call |
251+
call.getFunction().(NameNode).getId() = "SINK7" and
252+
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
253+
)
254+
}
255+
256+
/**
257+
* We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`.
258+
* Use-use flow lets the argument to the first call reach the sink inside the second call,
259+
* making it seem like we handle all cases even if we only handle the last one.
260+
* We make the test honest by preventing flow into source nodes.
261+
*/
262+
override predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
263+
}

0 commit comments

Comments
 (0)