Skip to content

Commit 8e4e663

Browse files
committed
Rust: Handle question mark operator in CFG
1 parent 2f07f1c commit 8e4e663

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ class SimpleCompletion extends NormalCompletion, TSimpleCompletion {
3636

3737
// `SimpleCompletion` is the "default" completion type, thus it is valid for
3838
// any node where there isn't another more specific completion type.
39-
override predicate isValidFor(AstNode e) { not any(Completion c).isValidForSpecific(e) }
39+
override predicate isValidFor(AstNode e) {
40+
not any(Completion c).isValidForSpecific(e)
41+
or
42+
// A `?` expression can both proceed normally or cause an early return, so
43+
// we explicitly allow the former here.
44+
e instanceof TryExpr
45+
}
4046

4147
override string toString() { result = "simple" }
4248
}
@@ -204,7 +210,9 @@ class ContinueCompletion extends TContinueCompletion, Completion {
204210
class ReturnCompletion extends TReturnCompletion, Completion {
205211
override ReturnSuccessor getAMatchingSuccessorType() { any() }
206212

207-
override predicate isValidForSpecific(AstNode e) { e instanceof ReturnExpr }
213+
override predicate isValidForSpecific(AstNode e) {
214+
e instanceof ReturnExpr or e instanceof TryExpr
215+
}
208216

209217
override string toString() { result = "return" }
210218
}

rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ class ReturnExprTree extends PostOrderTree instanceof ReturnExpr {
586586
}
587587
}
588588

589+
class TryExprTree extends StandardPostOrderTree instanceof TryExpr {
590+
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
591+
}
592+
589593
class TupleExprTree extends StandardPostOrderTree instanceof TupleExpr {
590594
override AstNode getChildNode(int i) { result = super.getField(i) }
591595
}

rust/ql/test/library-tests/controlflow/Cfg.expected

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,34 @@ edges
555555
| test.rs:245:16:247:9 | BlockExpr | test.rs:243:9:247:9 | IfExpr | |
556556
| test.rs:246:13:246:17 | false | test.rs:245:16:247:9 | BlockExpr | |
557557
| test.rs:253:5:255:5 | enter test_question_mark_operator_1 | test.rs:253:38:253:38 | s | |
558+
| test.rs:253:5:255:5 | exit test_question_mark_operator_1 (normal) | test.rs:253:5:255:5 | exit test_question_mark_operator_1 | |
558559
| test.rs:253:38:253:38 | s | test.rs:253:38:253:44 | Param | match |
560+
| test.rs:253:38:253:44 | Param | test.rs:254:9:254:11 | PathExpr | |
561+
| test.rs:253:62:255:5 | BlockExpr | test.rs:253:5:255:5 | exit test_question_mark_operator_1 (normal) | |
562+
| test.rs:254:9:254:11 | PathExpr | test.rs:254:9:254:26 | MethodCallExpr | |
563+
| test.rs:254:9:254:26 | MethodCallExpr | test.rs:254:9:254:27 | TryExpr | |
564+
| test.rs:254:9:254:27 | TryExpr | test.rs:253:5:255:5 | exit test_question_mark_operator_1 (normal) | return |
565+
| test.rs:254:9:254:27 | TryExpr | test.rs:254:31:254:31 | 4 | |
566+
| test.rs:254:9:254:31 | ... + ... | test.rs:253:62:255:5 | BlockExpr | |
567+
| test.rs:254:31:254:31 | 4 | test.rs:254:9:254:31 | ... + ... | |
559568
| test.rs:257:5:262:5 | enter test_question_mark_operator_2 | test.rs:257:38:257:38 | b | |
569+
| test.rs:257:5:262:5 | exit test_question_mark_operator_2 (normal) | test.rs:257:5:262:5 | exit test_question_mark_operator_2 | |
560570
| test.rs:257:38:257:38 | b | test.rs:257:38:257:52 | Param | match |
571+
| test.rs:257:38:257:52 | Param | test.rs:258:15:258:15 | b | |
572+
| test.rs:257:71:262:5 | BlockExpr | test.rs:257:5:262:5 | exit test_question_mark_operator_2 (normal) | |
573+
| test.rs:258:9:261:9 | MatchExpr | test.rs:257:71:262:5 | BlockExpr | |
574+
| test.rs:258:15:258:15 | b | test.rs:258:15:258:16 | TryExpr | |
575+
| test.rs:258:15:258:16 | TryExpr | test.rs:257:5:262:5 | exit test_question_mark_operator_2 (normal) | return |
576+
| test.rs:258:15:258:16 | TryExpr | test.rs:259:13:259:16 | LiteralPat | |
577+
| test.rs:259:13:259:16 | LiteralPat | test.rs:259:21:259:24 | PathExpr | match |
578+
| test.rs:259:13:259:16 | LiteralPat | test.rs:260:13:260:17 | LiteralPat | no-match |
579+
| test.rs:259:21:259:24 | PathExpr | test.rs:259:26:259:30 | false | |
580+
| test.rs:259:21:259:31 | CallExpr | test.rs:258:9:261:9 | MatchExpr | |
581+
| test.rs:259:26:259:30 | false | test.rs:259:21:259:31 | CallExpr | |
582+
| test.rs:260:13:260:17 | LiteralPat | test.rs:260:22:260:25 | PathExpr | match |
583+
| test.rs:260:22:260:25 | PathExpr | test.rs:260:27:260:30 | true | |
584+
| test.rs:260:22:260:31 | CallExpr | test.rs:258:9:261:9 | MatchExpr | |
585+
| test.rs:260:27:260:30 | true | test.rs:260:22:260:31 | CallExpr | |
561586
| test.rs:267:5:273:5 | enter test_match | test.rs:267:19:267:29 | maybe_digit | |
562587
| test.rs:267:5:273:5 | exit test_match (normal) | test.rs:267:5:273:5 | exit test_match | |
563588
| test.rs:267:19:267:29 | maybe_digit | test.rs:267:19:267:42 | Param | match |

0 commit comments

Comments
 (0)