Skip to content

Commit 9b58784

Browse files
authored
Merge pull request #9669 from rdmarsh2/rdmarsh2/swift/dataflow-lambda-flow
Swift: implement LambdaCall in dataflow library
2 parents 298f4ab + 42929a7 commit 9b58784

File tree

4 files changed

+196
-4
lines changed

4 files changed

+196
-4
lines changed

swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private module ParameterNodes {
165165
override string toStringImpl() { result = param.toString() }
166166

167167
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
168-
exists(FuncDecl f, int index |
168+
exists(Callable f, int index |
169169
c = TDataFlowFunc(f) and
170170
f.getParam(index) = param and
171171
pos = TPositionalParameter(index)
@@ -383,13 +383,25 @@ class Unit extends TUnit {
383383
*/
384384
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() }
385385

386-
newtype LambdaCallKind = TODO_TLambdaCallKind()
386+
newtype LambdaCallKind = TLambdaCallKind()
387387

388388
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
389-
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() }
389+
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
390+
kind = TLambdaCallKind() and
391+
(
392+
// Closures
393+
c.getUnderlyingCallable() = creation.asExpr()
394+
or
395+
// Reference to a function declaration
396+
creation.asExpr().(DeclRefExpr).getDecl() = c.getUnderlyingCallable()
397+
)
398+
}
390399

391400
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
392-
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() }
401+
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
402+
kind = TLambdaCallKind() and
403+
receiver.asExpr() = call.asCall().getExpr().(ApplyExpr).getFunction()
404+
}
393405

394406
/** Extra data-flow steps needed for lambda flow analysis. */
395407
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }

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

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,42 @@ edges
2929
| test.swift:89:15:89:22 | call to source() : | test.swift:84:1:91:1 | arg[return] : |
3030
| test.swift:97:9:97:41 | arg : | test.swift:98:19:98:19 | x |
3131
| test.swift:104:9:104:54 | arg : | test.swift:105:19:105:19 | x |
32+
| test.swift:109:9:109:14 | WriteDef : | test.swift:110:12:110:12 | arg : |
33+
| test.swift:109:9:109:14 | arg : | test.swift:110:12:110:12 | arg : |
34+
| test.swift:113:14:113:19 | WriteDef : | test.swift:114:19:114:19 | arg : |
35+
| test.swift:113:14:113:19 | WriteDef : | test.swift:114:19:114:19 | arg : |
36+
| test.swift:113:14:113:19 | arg : | test.swift:114:19:114:19 | arg : |
37+
| test.swift:113:14:113:19 | arg : | test.swift:114:19:114:19 | arg : |
38+
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | WriteDef : |
39+
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | arg : |
40+
| test.swift:114:19:114:19 | arg : | test.swift:114:12:114:22 | call to ... : |
41+
| test.swift:114:19:114:19 | arg : | test.swift:114:12:114:22 | call to ... : |
42+
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | WriteDef : |
43+
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | i : |
44+
| test.swift:118:18:118:25 | call to source() : | test.swift:119:31:119:31 | x : |
45+
| test.swift:119:18:119:44 | call to forward(arg:lambda:) : | test.swift:120:15:120:15 | y |
46+
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | WriteDef : |
47+
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | arg : |
48+
| test.swift:119:31:119:31 | x : | test.swift:119:18:119:44 | call to forward(arg:lambda:) : |
49+
| test.swift:122:18:125:6 | call to forward(arg:lambda:) : | test.swift:126:15:126:15 | z |
50+
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | WriteDef : |
51+
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | arg : |
52+
| test.swift:122:31:122:38 | call to source() : | test.swift:122:18:125:6 | call to forward(arg:lambda:) : |
53+
| test.swift:123:10:123:13 | WriteDef : | test.swift:124:16:124:16 | i : |
54+
| test.swift:123:10:123:13 | i : | test.swift:124:16:124:16 | i : |
55+
| test.swift:142:10:142:13 | WriteDef : | test.swift:143:16:143:16 | i : |
56+
| test.swift:142:10:142:13 | i : | test.swift:143:16:143:16 | i : |
57+
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | WriteDef : |
58+
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | i : |
59+
| test.swift:145:23:145:30 | call to source() : | test.swift:145:15:145:31 | call to ... |
60+
| test.swift:149:16:149:23 | call to source() : | test.swift:151:15:151:28 | call to ... |
61+
| test.swift:149:16:149:23 | call to source() : | test.swift:159:16:159:29 | call to ... : |
62+
| test.swift:154:10:154:13 | WriteDef : | test.swift:155:19:155:19 | i |
63+
| test.swift:154:10:154:13 | i : | test.swift:155:19:155:19 | i |
64+
| test.swift:157:16:157:23 | call to source() : | test.swift:154:10:154:13 | WriteDef : |
65+
| test.swift:157:16:157:23 | call to source() : | test.swift:154:10:154:13 | i : |
66+
| test.swift:159:16:159:29 | call to ... : | test.swift:154:10:154:13 | WriteDef : |
67+
| test.swift:159:16:159:29 | call to ... : | test.swift:154:10:154:13 | i : |
3268
nodes
3369
| test.swift:6:19:6:26 | call to source() : | semmle.label | call to source() : |
3470
| test.swift:7:15:7:15 | t1 | semmle.label | t1 |
@@ -72,9 +108,65 @@ nodes
72108
| test.swift:98:19:98:19 | x | semmle.label | x |
73109
| test.swift:104:9:104:54 | arg : | semmle.label | arg : |
74110
| test.swift:105:19:105:19 | x | semmle.label | x |
111+
| test.swift:109:9:109:14 | WriteDef : | semmle.label | WriteDef : |
112+
| test.swift:109:9:109:14 | WriteDef : | semmle.label | arg : |
113+
| test.swift:109:9:109:14 | arg : | semmle.label | WriteDef : |
114+
| test.swift:109:9:109:14 | arg : | semmle.label | arg : |
115+
| test.swift:110:12:110:12 | arg : | semmle.label | arg : |
116+
| test.swift:113:14:113:19 | WriteDef : | semmle.label | WriteDef : |
117+
| test.swift:113:14:113:19 | WriteDef : | semmle.label | WriteDef : |
118+
| test.swift:113:14:113:19 | WriteDef : | semmle.label | arg : |
119+
| test.swift:113:14:113:19 | WriteDef : | semmle.label | arg : |
120+
| test.swift:113:14:113:19 | arg : | semmle.label | WriteDef : |
121+
| test.swift:113:14:113:19 | arg : | semmle.label | WriteDef : |
122+
| test.swift:113:14:113:19 | arg : | semmle.label | arg : |
123+
| test.swift:113:14:113:19 | arg : | semmle.label | arg : |
124+
| test.swift:114:12:114:22 | call to ... : | semmle.label | call to ... : |
125+
| test.swift:114:12:114:22 | call to ... : | semmle.label | call to ... : |
126+
| test.swift:114:19:114:19 | arg : | semmle.label | arg : |
127+
| test.swift:114:19:114:19 | arg : | semmle.label | arg : |
128+
| test.swift:118:18:118:25 | call to source() : | semmle.label | call to source() : |
129+
| test.swift:119:18:119:44 | call to forward(arg:lambda:) : | semmle.label | call to forward(arg:lambda:) : |
130+
| test.swift:119:31:119:31 | x : | semmle.label | x : |
131+
| test.swift:120:15:120:15 | y | semmle.label | y |
132+
| test.swift:122:18:125:6 | call to forward(arg:lambda:) : | semmle.label | call to forward(arg:lambda:) : |
133+
| test.swift:122:31:122:38 | call to source() : | semmle.label | call to source() : |
134+
| test.swift:123:10:123:13 | WriteDef : | semmle.label | WriteDef : |
135+
| test.swift:123:10:123:13 | WriteDef : | semmle.label | i : |
136+
| test.swift:123:10:123:13 | i : | semmle.label | WriteDef : |
137+
| test.swift:123:10:123:13 | i : | semmle.label | i : |
138+
| test.swift:124:16:124:16 | i : | semmle.label | i : |
139+
| test.swift:126:15:126:15 | z | semmle.label | z |
140+
| test.swift:138:19:138:26 | call to source() | semmle.label | call to source() |
141+
| test.swift:142:10:142:13 | WriteDef : | semmle.label | WriteDef : |
142+
| test.swift:142:10:142:13 | WriteDef : | semmle.label | i : |
143+
| test.swift:142:10:142:13 | i : | semmle.label | WriteDef : |
144+
| test.swift:142:10:142:13 | i : | semmle.label | i : |
145+
| test.swift:143:16:143:16 | i : | semmle.label | i : |
146+
| test.swift:145:15:145:31 | call to ... | semmle.label | call to ... |
147+
| test.swift:145:23:145:30 | call to source() : | semmle.label | call to source() : |
148+
| test.swift:149:16:149:23 | call to source() : | semmle.label | call to source() : |
149+
| test.swift:151:15:151:28 | call to ... | semmle.label | call to ... |
150+
| test.swift:154:10:154:13 | WriteDef : | semmle.label | WriteDef : |
151+
| test.swift:154:10:154:13 | WriteDef : | semmle.label | i : |
152+
| test.swift:154:10:154:13 | i : | semmle.label | WriteDef : |
153+
| test.swift:154:10:154:13 | i : | semmle.label | i : |
154+
| test.swift:155:19:155:19 | i | semmle.label | i |
155+
| test.swift:157:16:157:23 | call to source() : | semmle.label | call to source() : |
156+
| test.swift:159:16:159:29 | call to ... : | semmle.label | call to ... : |
75157
subpaths
76158
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | WriteDef : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:5:75:33 | arg2 : |
77159
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:5:75:33 | arg2 : |
160+
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | WriteDef : | test.swift:110:12:110:12 | arg : | test.swift:114:12:114:22 | call to ... : |
161+
| 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 ... : |
162+
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | WriteDef : | test.swift:124:16:124:16 | i : | test.swift:114:12:114:22 | call to ... : |
163+
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | i : | test.swift:124:16:124:16 | i : | test.swift:114:12:114:22 | call to ... : |
164+
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | WriteDef : | test.swift:114:12:114:22 | call to ... : | test.swift:119:18:119:44 | call to forward(arg:lambda:) : |
165+
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | arg : | test.swift:114:12:114:22 | call to ... : | test.swift:119:18:119:44 | call to forward(arg:lambda:) : |
166+
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | WriteDef : | test.swift:114:12:114:22 | call to ... : | test.swift:122:18:125:6 | call to forward(arg:lambda:) : |
167+
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | arg : | test.swift:114:12:114:22 | call to ... : | test.swift:122:18:125:6 | call to forward(arg:lambda:) : |
168+
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | WriteDef : | test.swift:143:16:143:16 | i : | test.swift:145:15:145:31 | call to ... |
169+
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | i : | test.swift:143:16:143:16 | i : | test.swift:145:15:145:31 | call to ... |
78170
#select
79171
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 | result |
80172
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 | result |
@@ -88,3 +180,10 @@ subpaths
88180
| test.swift:98:19:98:19 | x | test.swift:81:11:81:18 | call to source() : | test.swift:98:19:98:19 | x | result |
89181
| test.swift:105:19:105:19 | x | test.swift:86:15:86:22 | call to source() : | test.swift:105:19:105:19 | x | result |
90182
| test.swift:105:19:105:19 | x | test.swift:89:15:89:22 | call to source() : | test.swift:105:19:105:19 | x | result |
183+
| test.swift:120:15:120:15 | y | test.swift:118:18:118:25 | call to source() : | test.swift:120:15:120:15 | y | result |
184+
| test.swift:126:15:126:15 | z | test.swift:122:31:122:38 | call to source() : | test.swift:126:15:126:15 | z | result |
185+
| test.swift:138:19:138:26 | call to source() | test.swift:138:19:138:26 | call to source() | test.swift:138:19:138:26 | call to source() | result |
186+
| test.swift:145:15:145:31 | call to ... | test.swift:145:23:145:30 | call to source() : | test.swift:145:15:145:31 | call to ... | result |
187+
| test.swift:151:15:151:28 | call to ... | test.swift:149:16:149:23 | call to source() : | test.swift:151:15:151:28 | call to ... | result |
188+
| test.swift:155:19:155:19 | i | test.swift:149:16:149:23 | call to source() : | test.swift:155:19:155:19 | i | result |
189+
| test.swift:155:19:155:19 | i | test.swift:157:16:157:23 | call to source() : | test.swift:155:19:155:19 | i | result |

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,31 @@
7474
| test.swift:104:9:104:54 | WriteDef | test.swift:105:19:105:19 | x |
7575
| test.swift:104:9:104:54 | arg | test.swift:104:9:104:54 | WriteDef |
7676
| test.swift:104:41:104:41 | x | test.swift:104:40:104:41 | &... |
77+
| test.swift:109:9:109:14 | WriteDef | test.swift:110:12:110:12 | arg |
78+
| test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg |
79+
| test.swift:113:14:113:19 | WriteDef | test.swift:114:19:114:19 | arg |
80+
| test.swift:113:14:113:19 | arg | test.swift:114:19:114:19 | arg |
81+
| test.swift:113:24:113:41 | WriteDef | test.swift:114:12:114:12 | lambda |
82+
| test.swift:113:24:113:41 | lambda | test.swift:114:12:114:12 | lambda |
83+
| test.swift:118:9:118:12 | WriteDef | test.swift:119:31:119:31 | x |
84+
| test.swift:118:18:118:25 | call to source() | test.swift:118:9:118:12 | WriteDef |
85+
| test.swift:119:9:119:12 | WriteDef | test.swift:120:15:120:15 | y |
86+
| test.swift:119:18:119:44 | call to forward(arg:lambda:) | test.swift:119:9:119:12 | WriteDef |
87+
| test.swift:122:9:122:12 | WriteDef | test.swift:126:15:126:15 | z |
88+
| test.swift:122:18:125:6 | call to forward(arg:lambda:) | test.swift:122:9:122:12 | WriteDef |
89+
| test.swift:123:10:123:13 | WriteDef | test.swift:124:16:124:16 | i |
90+
| test.swift:123:10:123:13 | i | test.swift:124:16:124:16 | i |
91+
| test.swift:128:9:128:16 | WriteDef | test.swift:132:15:132:15 | clean |
92+
| test.swift:128:22:131:6 | call to forward(arg:lambda:) | test.swift:128:9:128:16 | WriteDef |
93+
| test.swift:141:9:141:9 | WriteDef | test.swift:145:15:145:15 | lambda2 |
94+
| test.swift:141:19:144:5 | { ... } | test.swift:141:9:141:9 | WriteDef |
95+
| test.swift:142:10:142:13 | WriteDef | test.swift:143:16:143:16 | i |
96+
| test.swift:142:10:142:13 | i | test.swift:143:16:143:16 | i |
97+
| test.swift:147:9:147:9 | WriteDef | test.swift:151:15:151:15 | lambdaSource |
98+
| test.swift:147:24:150:5 | { ... } | test.swift:147:9:147:9 | WriteDef |
99+
| test.swift:151:15:151:15 | lambdaSource | test.swift:159:16:159:16 | lambdaSource |
100+
| test.swift:153:9:153:9 | WriteDef | test.swift:157:5:157:5 | lambdaSink |
101+
| test.swift:153:22:156:5 | { ... } | test.swift:153:9:153:9 | WriteDef |
102+
| test.swift:154:10:154:13 | WriteDef | test.swift:155:19:155:19 | i |
103+
| test.swift:154:10:154:13 | i | test.swift:155:19:155:19 | i |
104+
| test.swift:157:5:157:5 | lambdaSink | test.swift:159:5:159:5 | lambdaSink |

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,56 @@ func inoutUser2(bool: Bool) {
105105
sink(arg: x) // tainted by two sources
106106
}
107107
}
108+
109+
func id(arg: Int) -> Int {
110+
return arg
111+
}
112+
113+
func forward(arg: Int, lambda: (Int) -> Int) -> Int {
114+
return lambda(arg)
115+
}
116+
117+
func forwarder() {
118+
var x: Int = source()
119+
var y: Int = forward(arg: x, lambda: id)
120+
sink(arg: y)
121+
122+
var z: Int = forward(arg: source(), lambda: {
123+
(i: Int) -> Int in
124+
return i
125+
})
126+
sink(arg: z)
127+
128+
var clean: Int = forward(arg: source(), lambda: {
129+
(i: Int) -> Int in
130+
return 0
131+
})
132+
sink(arg: clean)
133+
}
134+
135+
func lambdaFlows() {
136+
var lambda1 = {
137+
() -> Void in
138+
sink(arg: source())
139+
}
140+
141+
var lambda2 = {
142+
(i: Int) -> Int in
143+
return i
144+
}
145+
sink(arg: lambda2(source()))
146+
147+
var lambdaSource = {
148+
() -> Int in
149+
return source()
150+
}
151+
sink(arg: lambdaSource())
152+
153+
var lambdaSink = {
154+
(i: Int) -> Void in
155+
sink(arg: i)
156+
}
157+
lambdaSink(source())
158+
159+
lambdaSink(lambdaSource())
160+
}

0 commit comments

Comments
 (0)