Skip to content

Commit c8bcfb7

Browse files
authored
Merge pull request #11836 from geoffw0/optbinding
Swift: Data flow through optional binding
2 parents 3a4623b + 5e5c4e9 commit c8bcfb7

File tree

8 files changed

+363
-104
lines changed

8 files changed

+363
-104
lines changed

swift/ql/lib/codeql/swift/dataflow/Ssa.qll

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@ module Ssa {
3030
certain = true
3131
)
3232
or
33-
exists(PatternBindingDecl decl, Pattern pattern |
33+
// Any variable initialization through pattern matching. For example each `x*` in:
34+
// ```
35+
// var x1 = v
36+
// let x2 = v
37+
// let (x3, x4) = tuple
38+
// if let x5 = optional { ... }
39+
// guard let x6 = optional else { ... }
40+
// ```
41+
exists(Pattern pattern |
3442
bb.getNode(i).getNode().asAstNode() = pattern and
35-
decl.getAPattern() = pattern and
3643
v.getParentPattern() = pattern and
3744
certain = true
3845
)
@@ -158,6 +165,15 @@ module Ssa {
158165
// TODO: We should probably enumerate more cfg nodes here.
159166
value.(PropertyGetterCfgNode).getRef() = init
160167
)
168+
or
169+
exists(SsaInput::BasicBlock bb, int blockIndex, ConditionElement ce, Expr init |
170+
this.definesAt(_, bb, blockIndex) and
171+
ce.getPattern() = bb.getNode(blockIndex).getNode().asAstNode() and
172+
init = ce.getInitializer() and
173+
strictcount(Ssa::WriteDefinition alt | alt.definesAt(_, bb, blockIndex)) = 1 // exclude cases where there are multiple writes from the same pattern, this is at best taint flow.
174+
|
175+
value.getNode().asAstNode() = init
176+
)
161177
}
162178
}
163179

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

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -100,36 +100,48 @@ edges
100100
| test.swift:225:14:225:21 | call to source() : | test.swift:235:13:235:15 | .source_value |
101101
| test.swift:225:14:225:21 | call to source() : | test.swift:238:13:238:15 | .source_value |
102102
| test.swift:259:12:259:19 | call to source() : | test.swift:263:13:263:28 | call to optionalSource() : |
103+
| test.swift:259:12:259:19 | call to source() : | test.swift:439:13:439:28 | call to optionalSource() : |
103104
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:265:15:265:15 | x |
104105
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:267:15:267:16 | ...! |
105106
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:271:15:271:16 | ...? : |
106107
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:274:15:274:20 | ... ??(_:_:) ... |
107108
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:275:15:275:27 | ... ??(_:_:) ... |
108109
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:279:15:279:31 | ... ? ... : ... |
109110
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:280:15:280:38 | ... ? ... : ... |
111+
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:285:19:285:19 | z |
112+
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:291:16:291:17 | ...? : |
113+
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:300:15:300:15 | z1 |
114+
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:303:15:303:16 | ...! : |
115+
| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:307:19:307:19 | z |
110116
| test.swift:270:15:270:22 | call to source() : | file://:0:0:0:0 | [summary param] this in signum() : |
111117
| test.swift:270:15:270:22 | call to source() : | test.swift:270:15:270:31 | call to signum() |
112118
| test.swift:271:15:271:16 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : |
113119
| test.swift:271:15:271:16 | ...? : | test.swift:271:15:271:25 | call to signum() : |
114120
| test.swift:271:15:271:25 | call to signum() : | test.swift:271:15:271:25 | OptionalEvaluationExpr |
115121
| test.swift:280:31:280:38 | call to source() : | test.swift:280:15:280:38 | ... ? ... : ... |
116122
| test.swift:282:31:282:38 | call to source() : | test.swift:282:15:282:38 | ... ? ... : ... |
117-
| test.swift:302:14:302:26 | (...) [Tuple element at index 1] : | test.swift:306:15:306:15 | t1 [Tuple element at index 1] : |
118-
| test.swift:302:18:302:25 | call to source() : | test.swift:302:14:302:26 | (...) [Tuple element at index 1] : |
119-
| test.swift:306:15:306:15 | t1 [Tuple element at index 1] : | test.swift:306:15:306:18 | .1 |
120-
| test.swift:314:5:314:5 | [post] t1 [Tuple element at index 0] : | test.swift:317:15:317:15 | t1 [Tuple element at index 0] : |
121-
| test.swift:314:12:314:19 | call to source() : | test.swift:314:5:314:5 | [post] t1 [Tuple element at index 0] : |
122-
| test.swift:317:15:317:15 | t1 [Tuple element at index 0] : | test.swift:317:15:317:18 | .0 |
123-
| test.swift:322:14:322:45 | (...) [Tuple element at index 0] : | test.swift:327:15:327:15 | t1 [Tuple element at index 0] : |
124-
| test.swift:322:14:322:45 | (...) [Tuple element at index 0] : | test.swift:331:15:331:15 | t2 [Tuple element at index 0] : |
125-
| test.swift:322:14:322:45 | (...) [Tuple element at index 1] : | test.swift:328:15:328:15 | t1 [Tuple element at index 1] : |
126-
| test.swift:322:14:322:45 | (...) [Tuple element at index 1] : | test.swift:332:15:332:15 | t2 [Tuple element at index 1] : |
127-
| test.swift:322:18:322:25 | call to source() : | test.swift:322:14:322:45 | (...) [Tuple element at index 0] : |
128-
| test.swift:322:31:322:38 | call to source() : | test.swift:322:14:322:45 | (...) [Tuple element at index 1] : |
129-
| test.swift:327:15:327:15 | t1 [Tuple element at index 0] : | test.swift:327:15:327:18 | .0 |
130-
| test.swift:328:15:328:15 | t1 [Tuple element at index 1] : | test.swift:328:15:328:18 | .1 |
131-
| test.swift:331:15:331:15 | t2 [Tuple element at index 0] : | test.swift:331:15:331:18 | .0 |
132-
| test.swift:332:15:332:15 | t2 [Tuple element at index 1] : | test.swift:332:15:332:18 | .1 |
123+
| test.swift:291:16:291:17 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : |
124+
| test.swift:291:16:291:17 | ...? : | test.swift:291:16:291:26 | call to signum() : |
125+
| test.swift:291:16:291:26 | call to signum() : | test.swift:292:19:292:19 | z |
126+
| test.swift:303:15:303:16 | ...! : | file://:0:0:0:0 | [summary param] this in signum() : |
127+
| test.swift:303:15:303:16 | ...! : | test.swift:303:15:303:25 | call to signum() |
128+
| test.swift:331:14:331:26 | (...) [Tuple element at index 1] : | test.swift:335:15:335:15 | t1 [Tuple element at index 1] : |
129+
| test.swift:331:18:331:25 | call to source() : | test.swift:331:14:331:26 | (...) [Tuple element at index 1] : |
130+
| test.swift:335:15:335:15 | t1 [Tuple element at index 1] : | test.swift:335:15:335:18 | .1 |
131+
| test.swift:343:5:343:5 | [post] t1 [Tuple element at index 0] : | test.swift:346:15:346:15 | t1 [Tuple element at index 0] : |
132+
| test.swift:343:12:343:19 | call to source() : | test.swift:343:5:343:5 | [post] t1 [Tuple element at index 0] : |
133+
| test.swift:346:15:346:15 | t1 [Tuple element at index 0] : | test.swift:346:15:346:18 | .0 |
134+
| test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | test.swift:356:15:356:15 | t1 [Tuple element at index 0] : |
135+
| test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | test.swift:360:15:360:15 | t2 [Tuple element at index 0] : |
136+
| test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | test.swift:357:15:357:15 | t1 [Tuple element at index 1] : |
137+
| test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | test.swift:361:15:361:15 | t2 [Tuple element at index 1] : |
138+
| test.swift:351:18:351:25 | call to source() : | test.swift:351:14:351:45 | (...) [Tuple element at index 0] : |
139+
| test.swift:351:31:351:38 | call to source() : | test.swift:351:14:351:45 | (...) [Tuple element at index 1] : |
140+
| test.swift:356:15:356:15 | t1 [Tuple element at index 0] : | test.swift:356:15:356:18 | .0 |
141+
| test.swift:357:15:357:15 | t1 [Tuple element at index 1] : | test.swift:357:15:357:18 | .1 |
142+
| test.swift:360:15:360:15 | t2 [Tuple element at index 0] : | test.swift:360:15:360:18 | .0 |
143+
| test.swift:361:15:361:15 | t2 [Tuple element at index 1] : | test.swift:361:15:361:18 | .1 |
144+
| test.swift:439:13:439:28 | call to optionalSource() : | test.swift:442:19:442:19 | a |
133145
nodes
134146
| file://:0:0:0:0 | .a [x] : | semmle.label | .a [x] : |
135147
| file://:0:0:0:0 | .x : | semmle.label | .x : |
@@ -258,26 +270,36 @@ nodes
258270
| test.swift:280:31:280:38 | call to source() : | semmle.label | call to source() : |
259271
| test.swift:282:15:282:38 | ... ? ... : ... | semmle.label | ... ? ... : ... |
260272
| test.swift:282:31:282:38 | call to source() : | semmle.label | call to source() : |
261-
| test.swift:302:14:302:26 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : |
262-
| test.swift:302:18:302:25 | call to source() : | semmle.label | call to source() : |
263-
| test.swift:306:15:306:15 | t1 [Tuple element at index 1] : | semmle.label | t1 [Tuple element at index 1] : |
264-
| test.swift:306:15:306:18 | .1 | semmle.label | .1 |
265-
| test.swift:314:5:314:5 | [post] t1 [Tuple element at index 0] : | semmle.label | [post] t1 [Tuple element at index 0] : |
266-
| test.swift:314:12:314:19 | call to source() : | semmle.label | call to source() : |
267-
| test.swift:317:15:317:15 | t1 [Tuple element at index 0] : | semmle.label | t1 [Tuple element at index 0] : |
268-
| test.swift:317:15:317:18 | .0 | semmle.label | .0 |
269-
| test.swift:322:14:322:45 | (...) [Tuple element at index 0] : | semmle.label | (...) [Tuple element at index 0] : |
270-
| test.swift:322:14:322:45 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : |
271-
| test.swift:322:18:322:25 | call to source() : | semmle.label | call to source() : |
272-
| test.swift:322:31:322:38 | call to source() : | semmle.label | call to source() : |
273-
| test.swift:327:15:327:15 | t1 [Tuple element at index 0] : | semmle.label | t1 [Tuple element at index 0] : |
274-
| test.swift:327:15:327:18 | .0 | semmle.label | .0 |
275-
| test.swift:328:15:328:15 | t1 [Tuple element at index 1] : | semmle.label | t1 [Tuple element at index 1] : |
276-
| test.swift:328:15:328:18 | .1 | semmle.label | .1 |
277-
| test.swift:331:15:331:15 | t2 [Tuple element at index 0] : | semmle.label | t2 [Tuple element at index 0] : |
278-
| test.swift:331:15:331:18 | .0 | semmle.label | .0 |
279-
| test.swift:332:15:332:15 | t2 [Tuple element at index 1] : | semmle.label | t2 [Tuple element at index 1] : |
280-
| test.swift:332:15:332:18 | .1 | semmle.label | .1 |
273+
| test.swift:285:19:285:19 | z | semmle.label | z |
274+
| test.swift:291:16:291:17 | ...? : | semmle.label | ...? : |
275+
| test.swift:291:16:291:26 | call to signum() : | semmle.label | call to signum() : |
276+
| test.swift:292:19:292:19 | z | semmle.label | z |
277+
| test.swift:300:15:300:15 | z1 | semmle.label | z1 |
278+
| test.swift:303:15:303:16 | ...! : | semmle.label | ...! : |
279+
| test.swift:303:15:303:25 | call to signum() | semmle.label | call to signum() |
280+
| test.swift:307:19:307:19 | z | semmle.label | z |
281+
| test.swift:331:14:331:26 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : |
282+
| test.swift:331:18:331:25 | call to source() : | semmle.label | call to source() : |
283+
| test.swift:335:15:335:15 | t1 [Tuple element at index 1] : | semmle.label | t1 [Tuple element at index 1] : |
284+
| test.swift:335:15:335:18 | .1 | semmle.label | .1 |
285+
| test.swift:343:5:343:5 | [post] t1 [Tuple element at index 0] : | semmle.label | [post] t1 [Tuple element at index 0] : |
286+
| test.swift:343:12:343:19 | call to source() : | semmle.label | call to source() : |
287+
| test.swift:346:15:346:15 | t1 [Tuple element at index 0] : | semmle.label | t1 [Tuple element at index 0] : |
288+
| test.swift:346:15:346:18 | .0 | semmle.label | .0 |
289+
| test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | semmle.label | (...) [Tuple element at index 0] : |
290+
| test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : |
291+
| test.swift:351:18:351:25 | call to source() : | semmle.label | call to source() : |
292+
| test.swift:351:31:351:38 | call to source() : | semmle.label | call to source() : |
293+
| test.swift:356:15:356:15 | t1 [Tuple element at index 0] : | semmle.label | t1 [Tuple element at index 0] : |
294+
| test.swift:356:15:356:18 | .0 | semmle.label | .0 |
295+
| test.swift:357:15:357:15 | t1 [Tuple element at index 1] : | semmle.label | t1 [Tuple element at index 1] : |
296+
| test.swift:357:15:357:18 | .1 | semmle.label | .1 |
297+
| test.swift:360:15:360:15 | t2 [Tuple element at index 0] : | semmle.label | t2 [Tuple element at index 0] : |
298+
| test.swift:360:15:360:18 | .0 | semmle.label | .0 |
299+
| test.swift:361:15:361:15 | t2 [Tuple element at index 1] : | semmle.label | t2 [Tuple element at index 1] : |
300+
| test.swift:361:15:361:18 | .1 | semmle.label | .1 |
301+
| test.swift:439:13:439:28 | call to optionalSource() : | semmle.label | call to optionalSource() : |
302+
| test.swift:442:19:442:19 | a | semmle.label | a |
281303
subpaths
282304
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:31:75:32 | [post] &... : |
283305
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | arg : | test.swift:110:12:110:12 | arg : | test.swift:114:12:114:22 | call to ... : |
@@ -306,6 +328,8 @@ subpaths
306328
| test.swift:219:13:219:15 | .a [x] : | test.swift:163:7:163:7 | self [x] : | file://:0:0:0:0 | .x : | test.swift:219:13:219:17 | .x |
307329
| test.swift:270:15:270:22 | call to source() : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:270:15:270:31 | call to signum() |
308330
| test.swift:271:15:271:16 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:271:15:271:25 | call to signum() : |
331+
| test.swift:291:16:291:17 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:291:16:291:26 | call to signum() : |
332+
| test.swift:303:15:303:16 | ...! : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:303:15:303:25 | call to signum() |
309333
#select
310334
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 | result |
311335
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 | result |
@@ -345,9 +369,15 @@ subpaths
345369
| test.swift:280:15:280:38 | ... ? ... : ... | test.swift:259:12:259:19 | call to source() : | test.swift:280:15:280:38 | ... ? ... : ... | result |
346370
| test.swift:280:15:280:38 | ... ? ... : ... | test.swift:280:31:280:38 | call to source() : | test.swift:280:15:280:38 | ... ? ... : ... | result |
347371
| test.swift:282:15:282:38 | ... ? ... : ... | test.swift:282:31:282:38 | call to source() : | test.swift:282:15:282:38 | ... ? ... : ... | result |
348-
| test.swift:306:15:306:18 | .1 | test.swift:302:18:302:25 | call to source() : | test.swift:306:15:306:18 | .1 | result |
349-
| test.swift:317:15:317:18 | .0 | test.swift:314:12:314:19 | call to source() : | test.swift:317:15:317:18 | .0 | result |
350-
| test.swift:327:15:327:18 | .0 | test.swift:322:18:322:25 | call to source() : | test.swift:327:15:327:18 | .0 | result |
351-
| test.swift:328:15:328:18 | .1 | test.swift:322:31:322:38 | call to source() : | test.swift:328:15:328:18 | .1 | result |
352-
| test.swift:331:15:331:18 | .0 | test.swift:322:18:322:25 | call to source() : | test.swift:331:15:331:18 | .0 | result |
353-
| test.swift:332:15:332:18 | .1 | test.swift:322:31:322:38 | call to source() : | test.swift:332:15:332:18 | .1 | result |
372+
| test.swift:285:19:285:19 | z | test.swift:259:12:259:19 | call to source() : | test.swift:285:19:285:19 | z | result |
373+
| test.swift:292:19:292:19 | z | test.swift:259:12:259:19 | call to source() : | test.swift:292:19:292:19 | z | result |
374+
| test.swift:300:15:300:15 | z1 | test.swift:259:12:259:19 | call to source() : | test.swift:300:15:300:15 | z1 | result |
375+
| test.swift:303:15:303:25 | call to signum() | test.swift:259:12:259:19 | call to source() : | test.swift:303:15:303:25 | call to signum() | result |
376+
| test.swift:307:19:307:19 | z | test.swift:259:12:259:19 | call to source() : | test.swift:307:19:307:19 | z | result |
377+
| test.swift:335:15:335:18 | .1 | test.swift:331:18:331:25 | call to source() : | test.swift:335:15:335:18 | .1 | result |
378+
| test.swift:346:15:346:18 | .0 | test.swift:343:12:343:19 | call to source() : | test.swift:346:15:346:18 | .0 | result |
379+
| test.swift:356:15:356:18 | .0 | test.swift:351:18:351:25 | call to source() : | test.swift:356:15:356:18 | .0 | result |
380+
| test.swift:357:15:357:18 | .1 | test.swift:351:31:351:38 | call to source() : | test.swift:357:15:357:18 | .1 | result |
381+
| test.swift:360:15:360:18 | .0 | test.swift:351:18:351:25 | call to source() : | test.swift:360:15:360:18 | .0 | result |
382+
| test.swift:361:15:361:18 | .1 | test.swift:351:31:351:38 | call to source() : | test.swift:361:15:361:18 | .1 | result |
383+
| test.swift:442:19:442:19 | a | test.swift:259:12:259:19 | call to source() : | test.swift:442:19:442:19 | a | result |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class TestConfiguration extends DataFlow::Configuration {
1010
TestConfiguration() { this = "TestConfiguration" }
1111

1212
override predicate isSource(DataFlow::Node src) {
13-
src.asExpr().(CallExpr).getStaticTarget().getName() = "source()"
13+
src.asExpr().(CallExpr).getStaticTarget().getName().matches("source%()")
1414
}
1515

1616
override predicate isSink(DataFlow::Node sink) {

0 commit comments

Comments
 (0)