Skip to content

Commit b8d60cb

Browse files
committed
Rust: Implement predicates for lambdas/closures in the data flow library
1 parent ad74805 commit b8d60cb

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -744,14 +744,28 @@ module RustDataFlow implements InputSig<Location> {
744744
SsaFlow::localMustFlowStep(_, node1, node2)
745745
}
746746

747-
class LambdaCallKind = Void;
747+
class LambdaCallKind = Unit;
748748

749-
// class LambdaCallKind;
750749
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
751-
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() }
750+
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
751+
exists(Expr cl | cl = creation.asExpr().getExpr() and cl = c.asCfgScope() |
752+
cl instanceof ClosureExpr or cl instanceof AsyncBlockExpr
753+
) and
754+
exists(kind)
755+
}
752756

753-
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
754-
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() }
757+
/**
758+
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the
759+
* invoked expression.
760+
*/
761+
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
762+
receiver.asExpr() = call.asCallExprCfgNode().getFunction() and
763+
// All calls to complex expressions and local variable accesses are lambda call.
764+
exists(Expr f | f = receiver.asExpr().getExpr() |
765+
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
766+
) and
767+
exists(kind)
768+
}
755769

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

rust/ql/test/library-tests/dataflow/local/inline-flow.expected

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ edges
2323
| main.rs:179:36:179:36 | n | main.rs:179:48:179:48 | n | provenance | |
2424
| main.rs:183:10:183:39 | ...::C {...} [C] | main.rs:183:37:183:37 | n | provenance | |
2525
| main.rs:183:37:183:37 | n | main.rs:183:83:183:83 | n | provenance | |
26+
| main.rs:240:20:240:52 | if cond {...} else {...} | main.rs:241:10:241:16 | f(...) | provenance | |
27+
| main.rs:240:30:240:39 | source(...) | main.rs:240:20:240:52 | if cond {...} else {...} | provenance | |
28+
| main.rs:245:20:245:23 | ... | main.rs:247:18:247:21 | data | provenance | |
29+
| main.rs:251:13:251:22 | source(...) | main.rs:252:13:252:13 | a | provenance | |
30+
| main.rs:252:13:252:13 | a | main.rs:245:20:245:23 | ... | provenance | |
31+
| main.rs:256:20:256:23 | ... | main.rs:257:9:261:9 | if cond {...} else {...} | provenance | |
32+
| main.rs:262:13:262:22 | source(...) | main.rs:263:21:263:21 | a | provenance | |
33+
| main.rs:263:13:263:22 | f(...) | main.rs:264:10:264:10 | b | provenance | |
34+
| main.rs:263:21:263:21 | a | main.rs:256:20:256:23 | ... | provenance | |
35+
| main.rs:263:21:263:21 | a | main.rs:263:13:263:22 | f(...) | provenance | |
2636
nodes
2737
| main.rs:15:10:15:18 | source(...) | semmle.label | source(...) |
2838
| main.rs:19:13:19:21 | source(...) | semmle.label | source(...) |
@@ -56,7 +66,21 @@ nodes
5666
| main.rs:183:10:183:39 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
5767
| main.rs:183:37:183:37 | n | semmle.label | n |
5868
| main.rs:183:83:183:83 | n | semmle.label | n |
69+
| main.rs:240:20:240:52 | if cond {...} else {...} | semmle.label | if cond {...} else {...} |
70+
| main.rs:240:30:240:39 | source(...) | semmle.label | source(...) |
71+
| main.rs:241:10:241:16 | f(...) | semmle.label | f(...) |
72+
| main.rs:245:20:245:23 | ... | semmle.label | ... |
73+
| main.rs:247:18:247:21 | data | semmle.label | data |
74+
| main.rs:251:13:251:22 | source(...) | semmle.label | source(...) |
75+
| main.rs:252:13:252:13 | a | semmle.label | a |
76+
| main.rs:256:20:256:23 | ... | semmle.label | ... |
77+
| main.rs:257:9:261:9 | if cond {...} else {...} | semmle.label | if cond {...} else {...} |
78+
| main.rs:262:13:262:22 | source(...) | semmle.label | source(...) |
79+
| main.rs:263:13:263:22 | f(...) | semmle.label | f(...) |
80+
| main.rs:263:21:263:21 | a | semmle.label | a |
81+
| main.rs:264:10:264:10 | b | semmle.label | b |
5982
subpaths
83+
| main.rs:263:21:263:21 | a | main.rs:256:20:256:23 | ... | main.rs:257:9:261:9 | if cond {...} else {...} | main.rs:263:13:263:22 | f(...) |
6084
testFailures
6185
#select
6286
| main.rs:15:10:15:18 | source(...) | main.rs:15:10:15:18 | source(...) | main.rs:15:10:15:18 | source(...) | $@ | main.rs:15:10:15:18 | source(...) | source(...) |
@@ -70,3 +94,6 @@ testFailures
7094
| main.rs:142:57:142:57 | n | main.rs:135:29:135:38 | source(...) | main.rs:142:57:142:57 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) |
7195
| main.rs:179:48:179:48 | n | main.rs:175:18:175:27 | source(...) | main.rs:179:48:179:48 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) |
7296
| main.rs:183:83:183:83 | n | main.rs:175:18:175:27 | source(...) | main.rs:183:83:183:83 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) |
97+
| main.rs:241:10:241:16 | f(...) | main.rs:240:30:240:39 | source(...) | main.rs:241:10:241:16 | f(...) | $@ | main.rs:240:30:240:39 | source(...) | source(...) |
98+
| main.rs:247:18:247:21 | data | main.rs:251:13:251:22 | source(...) | main.rs:247:18:247:21 | data | $@ | main.rs:251:13:251:22 | source(...) | source(...) |
99+
| main.rs:264:10:264:10 | b | main.rs:262:13:262:22 | source(...) | main.rs:264:10:264:10 | b | $@ | main.rs:262:13:262:22 | source(...) | source(...) |

rust/ql/test/library-tests/dataflow/local/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,13 @@ fn block_expression3(b: bool) -> i64 {
238238

239239
fn closure_flow_out() {
240240
let f = |cond| if cond { source(92) } else { 0 };
241-
sink(f(true)); // $ MISSING: hasValueFlow=92
241+
sink(f(true)); // $ hasValueFlow=92
242242
}
243243

244244
fn closure_flow_in() {
245245
let f = |cond, data|
246246
if cond {
247-
sink(data); // $ MISSING: hasValueFlow=87
247+
sink(data); // $ hasValueFlow=87
248248
} else {
249249
sink(0)
250250
};
@@ -261,7 +261,7 @@ fn closure_flow_through() {
261261
};
262262
let a = source(43);
263263
let b = f(true, a);
264-
sink(b); // $ MISSING: hasValueFlow=43
264+
sink(b); // $ hasValueFlow=43
265265
}
266266

267267
fn main() {

0 commit comments

Comments
 (0)