Skip to content

Commit

Permalink
Merge pull request #18024 from hvitved/rust/cfg/async-block-return
Browse files Browse the repository at this point in the history
Rust: Handle early returns in `async` blocks in CFG
  • Loading branch information
hvitved authored Nov 19, 2024
2 parents 95a8881 + bb8d0b4 commit 7a06574
Show file tree
Hide file tree
Showing 7 changed files with 1,180 additions and 1,063 deletions.
3 changes: 3 additions & 0 deletions rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ final class AsyncBlockScope extends CfgScopeImpl, AsyncBlockExpr instanceof Expr

override predicate scopeLast(AstNode last, Completion c) {
last(super.getLastChildElement(), last, c)
or
last(super.getChildNode(_), last, c) and
not c instanceof NormalCompletion
}
}

Expand Down
53 changes: 53 additions & 0 deletions rust/ql/test/library-tests/controlflow-unstable/Cfg.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
edges
| test.rs:5:5:11:5 | enter test_and_if_let | test.rs:5:24:5:24 | a | |
| test.rs:5:5:11:5 | exit test_and_if_let (normal) | test.rs:5:5:11:5 | exit test_and_if_let | |
| test.rs:5:24:5:24 | a | test.rs:5:24:5:30 | Param | match |
| test.rs:5:24:5:30 | Param | test.rs:5:33:5:33 | b | |
| test.rs:5:33:5:33 | b | test.rs:5:33:5:47 | Param | match |
| test.rs:5:33:5:47 | Param | test.rs:5:50:5:50 | c | |
| test.rs:5:50:5:50 | c | test.rs:5:50:5:56 | Param | match |
| test.rs:5:50:5:56 | Param | test.rs:6:12:6:12 | a | |
| test.rs:5:67:11:5 | BlockExpr | test.rs:5:5:11:5 | exit test_and_if_let (normal) | |
| test.rs:6:9:10:9 | IfExpr | test.rs:5:67:11:5 | BlockExpr | |
| test.rs:6:12:6:12 | a | test.rs:6:12:6:31 | [boolean(false)] ... && ... | false |
| test.rs:6:12:6:12 | a | test.rs:6:17:6:31 | LetExpr | true |
| test.rs:6:12:6:31 | [boolean(false)] ... && ... | test.rs:9:13:9:17 | false | false |
| test.rs:6:12:6:31 | [boolean(true)] ... && ... | test.rs:7:13:7:13 | d | true |
| test.rs:6:17:6:31 | LetExpr | test.rs:6:31:6:31 | b | |
| test.rs:6:21:6:27 | TupleStructPat | test.rs:6:12:6:31 | [boolean(false)] ... && ... | no-match |
| test.rs:6:21:6:27 | TupleStructPat | test.rs:6:26:6:26 | d | match |
| test.rs:6:26:6:26 | d | test.rs:6:12:6:31 | [boolean(true)] ... && ... | match |
| test.rs:6:31:6:31 | b | test.rs:6:21:6:27 | TupleStructPat | |
| test.rs:6:33:8:9 | BlockExpr | test.rs:6:9:10:9 | IfExpr | |
| test.rs:7:13:7:13 | d | test.rs:6:33:8:9 | BlockExpr | |
| test.rs:8:16:10:9 | BlockExpr | test.rs:6:9:10:9 | IfExpr | |
| test.rs:9:13:9:17 | false | test.rs:8:16:10:9 | BlockExpr | |
| test.rs:13:5:21:5 | enter test_and_if_let2 | test.rs:13:25:13:25 | a | |
| test.rs:13:5:21:5 | exit test_and_if_let2 (normal) | test.rs:13:5:21:5 | exit test_and_if_let2 | |
| test.rs:13:25:13:25 | a | test.rs:13:25:13:31 | Param | match |
| test.rs:13:25:13:31 | Param | test.rs:13:34:13:34 | b | |
| test.rs:13:34:13:34 | b | test.rs:13:34:13:39 | Param | match |
| test.rs:13:34:13:39 | Param | test.rs:13:42:13:42 | c | |
| test.rs:13:42:13:42 | c | test.rs:13:42:13:48 | Param | match |
| test.rs:13:42:13:48 | Param | test.rs:14:12:14:12 | a | |
| test.rs:13:59:21:5 | BlockExpr | test.rs:13:5:21:5 | exit test_and_if_let2 (normal) | |
| test.rs:14:9:20:9 | IfExpr | test.rs:13:59:21:5 | BlockExpr | |
| test.rs:14:12:14:12 | a | test.rs:14:12:14:25 | [boolean(false)] ... && ... | false |
| test.rs:14:12:14:12 | a | test.rs:14:17:14:25 | LetExpr | true |
| test.rs:14:12:14:25 | [boolean(false)] ... && ... | test.rs:14:12:15:16 | [boolean(false)] ... && ... | false |
| test.rs:14:12:14:25 | [boolean(true)] ... && ... | test.rs:15:16:15:16 | c | true |
| test.rs:14:12:15:16 | [boolean(false)] ... && ... | test.rs:19:13:19:17 | false | false |
| test.rs:14:12:15:16 | [boolean(true)] ... && ... | test.rs:17:13:17:13 | d | true |
| test.rs:14:17:14:25 | LetExpr | test.rs:14:25:14:25 | b | |
| test.rs:14:21:14:21 | d | test.rs:14:12:14:25 | [boolean(true)] ... && ... | match |
| test.rs:14:25:14:25 | b | test.rs:14:21:14:21 | d | |
| test.rs:15:16:15:16 | c | test.rs:14:12:15:16 | [boolean(false)] ... && ... | false |
| test.rs:15:16:15:16 | c | test.rs:14:12:15:16 | [boolean(true)] ... && ... | true |
| test.rs:16:9:18:9 | BlockExpr | test.rs:14:9:20:9 | IfExpr | |
| test.rs:17:13:17:13 | d | test.rs:17:17:17:17 | 0 | |
| test.rs:17:13:17:17 | ... > ... | test.rs:16:9:18:9 | BlockExpr | |
| test.rs:17:17:17:17 | 0 | test.rs:17:13:17:17 | ... > ... | |
| test.rs:18:16:20:9 | BlockExpr | test.rs:14:9:20:9 | IfExpr | |
| test.rs:19:13:19:17 | false | test.rs:18:16:20:9 | BlockExpr | |
breakTarget
continueTarget
1 change: 1 addition & 0 deletions rust/ql/test/library-tests/controlflow-unstable/Cfg.qlref
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
query: utils/Cfg.ql
22 changes: 22 additions & 0 deletions rust/ql/test/library-tests/controlflow-unstable/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// TODO: Move these tests into `controlflow` when they become stable features

mod if_expression {

fn test_and_if_let(a: bool, b: Option<bool>, c: bool) -> bool {
if a && let Some(d) = b {
d
} else {
false
}
}

fn test_and_if_let2(a: bool, b: i64, c: bool) -> bool {
if a && let d = b
&& c
{
d > 0
} else {
false
}
}
}
Loading

0 comments on commit 7a06574

Please sign in to comment.