Skip to content

Commit 9b9986b

Browse files
authored
Merge pull request #1762 from jbj/ast-field-flow-LambdaExpression
C++: Support flow through LambdaExpression
2 parents 0df9a62 + 84adeda commit 9b9986b

File tree

6 files changed

+28
-17
lines changed

6 files changed

+28
-17
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,11 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
452452
// initializer `(x)`.
453453
toExpr.(NewExpr).getInitializer() = fromExpr
454454
or
455+
// A lambda expression (`[captures](params){body}`) is just a thin wrapper
456+
// around the desugared closure creation in the form of a
457+
// `ClassAggregateLiteral` (`{ capture1, ..., captureN }`).
458+
toExpr.(LambdaExpression).getInitializer() = fromExpr
459+
or
455460
toExpr = any(Call call |
456461
exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel, int iIn |
457462
call.getTarget() = f and

cpp/ql/test/library-tests/dataflow/dataflow-tests/lambdas.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@ void test_lambdas()
1111
int w = 0;
1212

1313
auto a = [t, u]() -> int {
14-
sink(t); // flow from source() [NOT DETECTED]
14+
sink(t); // flow from source()
1515
sink(u);
1616
return t;
1717
};
18-
sink(a()); // flow from source() [NOT DETECTED]
18+
sink(a()); // flow from source()
1919

2020
auto b = [&] {
21-
sink(t); // flow from source() [NOT DETECTED]
21+
sink(t); // flow from source()
2222
sink(u);
2323
v = source(); // (v is reference captured)
2424
};
2525
b();
2626
sink(v); // flow from source() [NOT DETECTED]
2727

2828
auto c = [=] {
29-
sink(t); // flow from source() [NOT DETECTED]
29+
sink(t); // flow from source()
3030
sink(u);
3131
};
3232
c();

cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
2+
| file://:0:0:0:0 | t | lambdas.cpp:8:10:8:15 | call to source |
3+
| file://:0:0:0:0 | t | lambdas.cpp:8:10:8:15 | call to source |
4+
| file://:0:0:0:0 | t | lambdas.cpp:8:10:8:15 | call to source |
5+
| lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source |
26
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
37
| lambdas.cpp:41:8:41:8 | a | lambdas.cpp:8:10:8:15 | call to source |
48
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
| lambdas.cpp:8:10:8:15 | file://:0:0:0:0 | AST only |
2+
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
13
| lambdas.cpp:8:10:8:15 | lambdas.cpp:35:8:35:8 | AST only |
24
| lambdas.cpp:8:10:8:15 | lambdas.cpp:41:8:41:8 | AST only |
35
| test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only |

cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@
213213
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
214214
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
215215
| taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
216-
| taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | TAINT |
216+
| taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | |
217217
| taint.cpp:228:12:228:12 | t | taint.cpp:228:11:232:2 | {...} | TAINT |
218218
| taint.cpp:228:15:228:15 | u | taint.cpp:228:11:232:2 | {...} | TAINT |
219219
| taint.cpp:228:17:228:17 | `this` parameter in operator() | file://:0:0:0:0 | this | |
@@ -222,13 +222,13 @@
222222
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
223223
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
224224
| taint.cpp:235:11:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
225-
| taint.cpp:235:11:239:2 | {...} | taint.cpp:235:11:239:2 | [...](...){...} | TAINT |
225+
| taint.cpp:235:11:239:2 | {...} | taint.cpp:235:11:239:2 | [...](...){...} | |
226226
| taint.cpp:235:15:235:15 | `this` parameter in operator() | file://:0:0:0:0 | this | |
227227
| taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | |
228228
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
229229
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
230230
| taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
231-
| taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | TAINT |
231+
| taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | |
232232
| taint.cpp:243:15:243:15 | `this` parameter in operator() | file://:0:0:0:0 | this | |
233233
| taint.cpp:243:15:243:15 | `this` parameter in operator() | file://:0:0:0:0 | this | |
234234
| taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | |

cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,11 @@ void test_swap() {
208208
y = 0;
209209

210210
sink(x); // tainted
211-
sink(y);
211+
sink(y); // clean
212212

213213
std::swap(x, y);
214214

215-
sink(x); // [FALSE POSITIVE]
215+
sink(x); // clean [FALSE POSITIVE]
216216
sink(y); // tainted
217217
}
218218

@@ -226,35 +226,35 @@ void test_lambdas()
226226
int w = 0;
227227

228228
auto a = [t, u]() -> int {
229-
sink(t); // tainted [NOT DETECTED]
230-
sink(u);
229+
sink(t); // tainted
230+
sink(u); // clean [FALSE POSITIVE]
231231
return t;
232232
};
233233
sink(a()); // tainted
234234

235235
auto b = [&] {
236-
sink(t); // tainted [NOT DETECTED]
237-
sink(u);
236+
sink(t); // tainted
237+
sink(u); // clean [FALSE POSITIVE]
238238
v = source(); // (v is reference captured)
239239
};
240240
b();
241241
sink(v); // tainted [NOT DETECTED]
242242

243243
auto c = [=] {
244-
sink(t); // tainted [NOT DETECTED]
245-
sink(u);
244+
sink(t); // tainted
245+
sink(u); // clean [FALSE POSITIVE]
246246
};
247247
c();
248248

249249
auto d = [](int a, int b) {
250250
sink(a); // tainted
251-
sink(b);
251+
sink(b); // clean
252252
};
253253
d(t, u);
254254

255255
auto e = [](int &a, int &b, int &c) {
256256
sink(a); // tainted
257-
sink(b);
257+
sink(b); // clean
258258
c = source();
259259
};
260260
e(t, u, w);

0 commit comments

Comments
 (0)