Skip to content

Commit 18ed9ed

Browse files
authored
Merge pull request #10145 from MathiasVP/swift-inline-expect-for-dataflow
Swift: Use `InlineExpectationsTest` for dataflow tests
2 parents f0e5ef6 + 6e148a4 commit 18ed9ed

File tree

6 files changed

+197
-37
lines changed

6 files changed

+197
-37
lines changed

swift/ql/test/library-tests/dataflow/dataflow/DataFlow.ql

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,10 @@
33
*/
44

55
import swift
6-
import codeql.swift.dataflow.DataFlow
6+
import codeql.swift.dataflow.DataFlow::DataFlow
7+
import FlowConfig
78
import DataFlow::PathGraph
89

9-
class TestConfiguration extends DataFlow::Configuration {
10-
TestConfiguration() { this = "TestConfiguration" }
11-
12-
override predicate isSource(DataFlow::Node src) {
13-
src.asExpr().(CallExpr).getStaticTarget().getName() = "source()"
14-
}
15-
16-
override predicate isSink(DataFlow::Node sink) {
17-
exists(CallExpr sinkCall |
18-
sinkCall.getStaticTarget().getName() = "sink(arg:)" and
19-
sinkCall.getAnArgument().getExpr() = sink.asExpr()
20-
)
21-
}
22-
23-
override int explorationLimit() { result = 100 }
24-
}
25-
2610
from DataFlow::PathNode src, DataFlow::PathNode sink, TestConfiguration test
2711
where test.hasFlowPath(src, sink)
2812
select sink, src, sink, "result"

swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.expected

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import swift
2+
import DataFlow
3+
import FlowConfig
4+
import TestUtilities.InlineExpectationsTest
5+
6+
class TaintTest extends InlineExpectationsTest {
7+
TaintTest() { this = "DataFlowTest" }
8+
9+
override string getARelevantTag() { result = "flow" }
10+
11+
override predicate hasActualResult(Location location, string element, string tag, string value) {
12+
exists(TestConfiguration config, Node source, Node sink, Expr sinkExpr |
13+
config.hasFlow(source, sink) and
14+
sinkExpr = sink.asExpr() and
15+
location = sinkExpr.getLocation() and
16+
element = sinkExpr.toString() and
17+
tag = "flow" and
18+
value = source.asExpr().getLocation().getStartLine().toString()
19+
)
20+
}
21+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @kind path-problem
3+
*/
4+
5+
import swift
6+
import codeql.swift.dataflow.DataFlow
7+
8+
class TestConfiguration extends DataFlow::Configuration {
9+
TestConfiguration() { this = "TestConfiguration" }
10+
11+
override predicate isSource(DataFlow::Node src) {
12+
src.asExpr().(CallExpr).getStaticTarget().getName() = "source()"
13+
}
14+
15+
override predicate isSink(DataFlow::Node sink) {
16+
exists(CallExpr sinkCall |
17+
sinkCall.getStaticTarget().getName() = "sink(arg:)" and
18+
sinkCall.getAnArgument().getExpr() = sink.asExpr()
19+
)
20+
}
21+
22+
override int explorationLimit() { result = 100 }
23+
}

swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
| file://:0:0:0:0 | .a | file://:0:0:0:0 | &... |
2+
| file://:0:0:0:0 | .source_value | file://:0:0:0:0 | &... |
3+
| file://:0:0:0:0 | .wrappedValue | file://:0:0:0:0 | &... |
4+
| file://:0:0:0:0 | .x | file://:0:0:0:0 | &... |
5+
| file://:0:0:0:0 | self | file://:0:0:0:0 | &... |
6+
| file://:0:0:0:0 | self | file://:0:0:0:0 | &... |
17
| test.swift:6:9:6:13 | WriteDef | test.swift:7:15:7:15 | t1 |
28
| test.swift:6:19:6:26 | call to source() | test.swift:6:9:6:13 | WriteDef |
39
| test.swift:7:15:7:15 | t1 | test.swift:8:10:8:10 | t1 |
@@ -102,3 +108,35 @@
102108
| test.swift:154:10:154:13 | WriteDef | test.swift:155:19:155:19 | i |
103109
| test.swift:154:10:154:13 | i | test.swift:155:19:155:19 | i |
104110
| test.swift:157:5:157:5 | lambdaSink | test.swift:159:5:159:5 | lambdaSink |
111+
| test.swift:163:7:163:7 | WriteDef | file://:0:0:0:0 | value |
112+
| test.swift:163:7:163:7 | value | file://:0:0:0:0 | value |
113+
| test.swift:169:12:169:22 | WriteDef | test.swift:170:9:170:9 | value |
114+
| test.swift:169:12:169:22 | value | test.swift:170:9:170:9 | value |
115+
| test.swift:179:7:179:7 | WriteDef | test.swift:180:3:180:3 | a |
116+
| test.swift:179:11:179:13 | call to init | test.swift:179:7:179:7 | WriteDef |
117+
| test.swift:180:3:180:3 | a | test.swift:181:13:181:13 | a |
118+
| test.swift:185:7:185:7 | WriteDef | file://:0:0:0:0 | value |
119+
| test.swift:185:7:185:7 | value | file://:0:0:0:0 | value |
120+
| test.swift:193:7:193:7 | WriteDef | test.swift:194:3:194:3 | b |
121+
| test.swift:193:11:193:13 | call to init | test.swift:193:7:193:7 | WriteDef |
122+
| test.swift:194:3:194:3 | b | test.swift:195:13:195:13 | b |
123+
| test.swift:199:7:199:7 | WriteDef | test.swift:200:3:200:3 | a |
124+
| test.swift:199:11:199:13 | call to init | test.swift:199:7:199:7 | WriteDef |
125+
| test.swift:200:3:200:3 | a | test.swift:201:13:201:13 | a |
126+
| test.swift:205:7:205:7 | WriteDef | test.swift:206:3:206:3 | a |
127+
| test.swift:205:11:205:13 | call to init | test.swift:205:7:205:7 | WriteDef |
128+
| test.swift:206:3:206:3 | a | test.swift:207:13:207:13 | a |
129+
| test.swift:211:7:211:7 | WriteDef | test.swift:212:3:212:3 | a |
130+
| test.swift:211:11:211:13 | call to init | test.swift:211:7:211:7 | WriteDef |
131+
| test.swift:212:3:212:3 | a | test.swift:213:13:213:13 | a |
132+
| test.swift:217:7:217:7 | WriteDef | test.swift:218:3:218:3 | b |
133+
| test.swift:217:11:217:13 | call to init | test.swift:217:7:217:7 | WriteDef |
134+
| test.swift:218:3:218:3 | b | test.swift:219:13:219:13 | b |
135+
| test.swift:234:7:234:7 | WriteDef | test.swift:235:13:235:13 | a |
136+
| test.swift:234:11:234:31 | call to init | test.swift:234:7:234:7 | WriteDef |
137+
| test.swift:235:13:235:13 | a | test.swift:237:3:237:3 | a |
138+
| test.swift:237:3:237:3 | a | test.swift:238:13:238:13 | a |
139+
| test.swift:242:9:242:9 | WriteDef | file://:0:0:0:0 | value |
140+
| test.swift:242:9:242:9 | value | file://:0:0:0:0 | value |
141+
| test.swift:252:23:252:23 | WriteDef | file://:0:0:0:0 | value |
142+
| test.swift:252:23:252:23 | value | file://:0:0:0:0 | value |

swift/ql/test/library-tests/dataflow/dataflow/test.swift

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ func sink(arg: Int) {}
44
func intraprocedural_with_local_flow() -> Void {
55
var t2: Int
66
var t1: Int = source()
7-
sink(arg: t1)
7+
sink(arg: t1) // $ flow=6
88
t2 = t1
9-
sink(arg: t1)
10-
sink(arg: t2)
9+
sink(arg: t1) // $ flow=6
10+
sink(arg: t2) // $ flow=6
1111
if(t1 != 0) {
1212
t2 = 0
1313
sink(arg: t2)
1414
}
15-
sink(arg: t2)
15+
sink(arg: t2) // $ MISSING: flow=6
1616

1717
t1 = 0;
1818
while(false) {
@@ -27,16 +27,16 @@ func caller_source() -> Void {
2727
}
2828

2929
func callee_sink(x: Int, y: Int) -> Void {
30-
sink(arg: x)
31-
sink(arg: y)
30+
sink(arg: x) // $ flow=25
31+
sink(arg: y) // $ flow=26
3232
}
3333

3434
func callee_source() -> Int {
3535
return source()
3636
}
3737

3838
func caller_sink() -> Void {
39-
sink(arg: callee_source())
39+
sink(arg: callee_source()) // $ flow=35
4040
}
4141

4242
func branching(b: Bool) -> Void {
@@ -47,7 +47,7 @@ func branching(b: Bool) -> Void {
4747
} else {
4848
t = 1;
4949
}
50-
sink(arg: t)
50+
sink(arg: t) // $ flow=43
5151
}
5252

5353
func inoutSource(arg: inout Int) -> Void {
@@ -59,7 +59,7 @@ func inoutUser() {
5959
var x: Int = 0
6060
sink(arg: x)
6161
inoutSource(arg: &x)
62-
sink(arg: x)
62+
sink(arg: x) // $ flow=54
6363
}
6464

6565
func inoutSwap(arg1: inout Int, arg2: inout Int) -> Void {
@@ -73,8 +73,8 @@ func swapUser() {
7373
var x: Int = source()
7474
var y: Int = 0
7575
inoutSwap(arg1: &x, arg2: &y)
76-
sink(arg: x)
77-
sink(arg: y)
76+
sink(arg: x) // clean
77+
sink(arg: y) // $ flow=73
7878
}
7979

8080
func inoutSourceWithoutReturn(arg: inout Int) {
@@ -95,14 +95,14 @@ func inoutUser2(bool: Bool) {
9595
var x: Int = 0
9696
sink(arg: x) // clean
9797
inoutSourceWithoutReturn(arg: &x)
98-
sink(arg: x) // tainted
98+
sink(arg: x) // $ flow=81
9999
}
100100

101101
do {
102102
var x: Int = 0
103103
sink(arg: x) // clean
104104
inoutSourceMultipleReturn(arg: &x, bool: bool)
105-
sink(arg: x) // tainted by two sources
105+
sink(arg: x) // $ flow=86 flow=89
106106
}
107107
}
108108

@@ -117,13 +117,13 @@ func forward(arg: Int, lambda: (Int) -> Int) -> Int {
117117
func forwarder() {
118118
var x: Int = source()
119119
var y: Int = forward(arg: x, lambda: id)
120-
sink(arg: y)
120+
sink(arg: y) // $ flow=118
121121

122122
var z: Int = forward(arg: source(), lambda: {
123123
(i: Int) -> Int in
124124
return i
125125
})
126-
sink(arg: z)
126+
sink(arg: z) // $ flow=122
127127

128128
var clean: Int = forward(arg: source(), lambda: {
129129
(i: Int) -> Int in
@@ -135,26 +135,120 @@ func forwarder() {
135135
func lambdaFlows() {
136136
var lambda1 = {
137137
() -> Void in
138-
sink(arg: source())
138+
sink(arg: source()) // $ flow=138
139139
}
140140

141141
var lambda2 = {
142142
(i: Int) -> Int in
143143
return i
144144
}
145-
sink(arg: lambda2(source()))
145+
sink(arg: lambda2(source())) // $ flow=145
146146

147147
var lambdaSource = {
148148
() -> Int in
149149
return source()
150150
}
151-
sink(arg: lambdaSource())
151+
sink(arg: lambdaSource()) // $ flow=149
152152

153153
var lambdaSink = {
154154
(i: Int) -> Void in
155-
sink(arg: i)
155+
sink(arg: i) // $ flow=157 flow=149
156156
}
157157
lambdaSink(source())
158158

159159
lambdaSink(lambdaSource())
160+
}
161+
162+
class A {
163+
var x : Int
164+
165+
init() {
166+
x = 0
167+
}
168+
169+
func set(_ value : Int) {
170+
x = value
171+
}
172+
173+
func get() -> Int {
174+
return x
175+
}
176+
}
177+
178+
func simple_field_flow() {
179+
var a = A()
180+
a.x = source()
181+
sink(arg: a.x) // $ MISSING: flow=180
182+
}
183+
184+
class B {
185+
var a : A
186+
187+
init() {
188+
a = A()
189+
}
190+
}
191+
192+
func reverse_read() {
193+
var b = B()
194+
b.a.x = source()
195+
sink(arg: b.a.x) // $ MISSING: flow=194
196+
}
197+
198+
func test_setter() {
199+
var a = A()
200+
a.set(source())
201+
sink(arg: a.x) // $ MISSING: flow=200
202+
}
203+
204+
func test_getter() {
205+
var a = A()
206+
a.x = source()
207+
sink(arg: a.get()) // $ MISSING: flow=206
208+
}
209+
210+
func test_setter_getter() {
211+
var a = A()
212+
a.set(source())
213+
sink(arg: a.get()) // $ MISSING: flow=212
214+
}
215+
216+
func flow_through(b : B) {
217+
var b = B()
218+
b.a.set(source())
219+
sink(arg: b.a.x) // $ MISSING: flow=218
220+
}
221+
222+
class HasComputedProperty {
223+
var source_value : Int {
224+
get {
225+
return source()
226+
}
227+
set {
228+
229+
}
230+
}
231+
}
232+
233+
func test_computed_property() {
234+
var a = HasComputedProperty()
235+
sink(arg: a.source_value) // $ MISSING: flow=225
236+
237+
a.source_value = 0
238+
sink(arg: a.source_value) // $ MISSING: flow=225
239+
}
240+
241+
@propertyWrapper struct DidSetSource {
242+
var wrappedValue: Int {
243+
didSet { wrappedValue = source() }
244+
}
245+
246+
init(wrappedValue: Int) {
247+
self.wrappedValue = 0
248+
}
249+
}
250+
251+
func test_property_wrapper() {
252+
@DidSetSource var x = 42
253+
sink(arg: x) // $ MISSING: flow=243
160254
}

0 commit comments

Comments
 (0)