mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Rust: Add CFG test for early return in async block
Also made the test comply with `cargo check`.
This commit is contained in:
53
rust/ql/test/library-tests/controlflow-unstable/Cfg.expected
Normal file
53
rust/ql/test/library-tests/controlflow-unstable/Cfg.expected
Normal file
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
query: utils/Cfg.ql
|
||||||
22
rust/ql/test/library-tests/controlflow-unstable/test.rs
Normal file
22
rust/ql/test/library-tests/controlflow-unstable/test.rs
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::convert::Infallible;
|
|
||||||
|
|
||||||
mod calls {
|
mod calls {
|
||||||
|
use crate::test::logical_operators;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn function_call() {
|
fn function_call() {
|
||||||
test_and_operator(true, false, true);
|
logical_operators::test_and_operator(true, false, true);
|
||||||
foo::<u32, u64>(42);
|
method_call();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn method_call() {
|
fn method_call() {
|
||||||
@@ -15,6 +15,14 @@ mod calls {
|
|||||||
|
|
||||||
mod loop_expression {
|
mod loop_expression {
|
||||||
|
|
||||||
|
fn next(n: i64) -> i64 {
|
||||||
|
if n % 2 == 0 {
|
||||||
|
n / 2
|
||||||
|
} else {
|
||||||
|
3 * n + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_break_and_continue(n: i64) -> bool {
|
fn test_break_and_continue(n: i64) -> bool {
|
||||||
let mut i = n;
|
let mut i = n;
|
||||||
loop {
|
loop {
|
||||||
@@ -89,7 +97,7 @@ mod loop_expression {
|
|||||||
fn test_while_let() {
|
fn test_while_let() {
|
||||||
let mut iter = 1..10;
|
let mut iter = 1..10;
|
||||||
while let Some(x) = iter.next() {
|
while let Some(x) = iter.next() {
|
||||||
if (i = 5) {
|
if (x == 5) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,29 +144,11 @@ mod if_expression {
|
|||||||
|
|
||||||
fn test_if_let(a: Option<i64>) -> i64 {
|
fn test_if_let(a: Option<i64>) -> i64 {
|
||||||
if let Some(n) = a {
|
if let Some(n) = a {
|
||||||
n
|
return n;
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_nested_if(a: i64) -> i64 {
|
fn test_nested_if(a: i64) -> i64 {
|
||||||
if (if a < 0 { a < -10 } else { a > 10 }) {
|
if (if a < 0 { a < -10 } else { a > 10 }) {
|
||||||
1
|
1
|
||||||
@@ -191,7 +181,10 @@ mod if_expression {
|
|||||||
|
|
||||||
fn test_if_assignment(a: i64) -> i64 {
|
fn test_if_assignment(a: i64) -> i64 {
|
||||||
let mut x = false;
|
let mut x = false;
|
||||||
if x = true {
|
if {
|
||||||
|
x = true;
|
||||||
|
x
|
||||||
|
} {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
@@ -237,7 +230,7 @@ mod if_expression {
|
|||||||
|
|
||||||
mod logical_operators {
|
mod logical_operators {
|
||||||
|
|
||||||
fn test_and_operator(a: bool, b: bool, c: bool) -> bool {
|
pub fn test_and_operator(a: bool, b: bool, c: bool) -> bool {
|
||||||
let d = a && b && c;
|
let d = a && b && c;
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
@@ -257,7 +250,7 @@ mod logical_operators {
|
|||||||
d
|
d
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_if_and_operator(a: bool, b: i64, c: bool) -> bool {
|
fn test_if_and_operator(a: bool, b: bool, c: bool) -> bool {
|
||||||
if a && b && c {
|
if a && b && c {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -265,7 +258,7 @@ mod logical_operators {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_if_or_operator(a: bool, b: i64, c: bool) -> bool {
|
fn test_if_or_operator(a: bool, b: bool, c: bool) -> bool {
|
||||||
if a || b || c {
|
if a || b || c {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -287,9 +280,10 @@ mod logical_operators {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod question_mark_operator {
|
mod question_mark_operator {
|
||||||
|
use std::num;
|
||||||
|
|
||||||
fn test_question_mark_operator_1(s: &str) -> Option<i32> {
|
fn test_question_mark_operator_1(s: &str) -> Result<u32, std::num::ParseIntError> {
|
||||||
str.parse::<u32>()? + 4
|
Ok(s.parse::<u32>()? + 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_question_mark_operator_2(b: Option<bool>) -> Option<bool> {
|
fn test_question_mark_operator_2(b: Option<bool>) -> Option<bool> {
|
||||||
@@ -301,6 +295,7 @@ mod question_mark_operator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod match_expression {
|
mod match_expression {
|
||||||
|
use std::convert::Infallible;
|
||||||
|
|
||||||
fn test_match(maybe_digit: Option<i64>) -> i64 {
|
fn test_match(maybe_digit: Option<i64>) -> i64 {
|
||||||
match maybe_digit {
|
match maybe_digit {
|
||||||
@@ -321,7 +316,7 @@ mod match_expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_match_and(cond: bool, r: Opton<bool>) -> bool {
|
fn test_match_and(cond: bool, r: Option<bool>) -> bool {
|
||||||
(match r {
|
(match r {
|
||||||
Some(a) => a,
|
Some(a) => a,
|
||||||
_ => false,
|
_ => false,
|
||||||
@@ -338,12 +333,12 @@ mod match_expression {
|
|||||||
|
|
||||||
mod let_statement {
|
mod let_statement {
|
||||||
|
|
||||||
fn test_let_match(a: Option<i64>) {
|
fn test_let_match(a: Option<i64>) -> i64 {
|
||||||
let Some(n) = a else { "Expected some" };
|
let Some(n) = a else { panic!("Expected some") };
|
||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_let_with_return(m: Option<i64>) {
|
fn test_let_with_return(m: Option<i64>) -> bool {
|
||||||
let ret = match m {
|
let ret = match m {
|
||||||
Some(ret) => ret,
|
Some(ret) => ret,
|
||||||
None => return false,
|
None => return false,
|
||||||
@@ -354,7 +349,7 @@ mod let_statement {
|
|||||||
|
|
||||||
mod patterns {
|
mod patterns {
|
||||||
|
|
||||||
fn empty_tuple_pattern(unit: ()) -> void {
|
fn empty_tuple_pattern(unit: ()) -> () {
|
||||||
let () = unit;
|
let () = unit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -363,7 +358,7 @@ mod patterns {
|
|||||||
|
|
||||||
fn empty_struct_pattern(st: MyStruct) -> i64 {
|
fn empty_struct_pattern(st: MyStruct) -> i64 {
|
||||||
match st {
|
match st {
|
||||||
MyStruct {} => 1,
|
MyStruct { .. } => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +367,7 @@ mod patterns {
|
|||||||
..0 => 1,
|
..0 => 1,
|
||||||
1..2 => 2,
|
1..2 => 2,
|
||||||
5.. => 3,
|
5.. => 3,
|
||||||
.. => 4,
|
_ => 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,7 +375,7 @@ mod patterns {
|
|||||||
mod divergence {
|
mod divergence {
|
||||||
fn test_infinite_loop() -> &'static str {
|
fn test_infinite_loop() -> &'static str {
|
||||||
loop {
|
loop {
|
||||||
1
|
()
|
||||||
}
|
}
|
||||||
"never reached"
|
"never reached"
|
||||||
}
|
}
|
||||||
@@ -391,7 +386,7 @@ mod async_await {
|
|||||||
println!("hello, world!");
|
println!("hello, world!");
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn async_block() {
|
async fn async_block(b: bool) {
|
||||||
let say_godbye = async {
|
let say_godbye = async {
|
||||||
println!("godbye, everyone!");
|
println!("godbye, everyone!");
|
||||||
};
|
};
|
||||||
@@ -403,17 +398,24 @@ mod async_await {
|
|||||||
say_how_are_you.await;
|
say_how_are_you.await;
|
||||||
say_godbye.await;
|
say_godbye.await;
|
||||||
noop.await;
|
noop.await;
|
||||||
|
|
||||||
|
let lambda = |foo| async {
|
||||||
|
if b {
|
||||||
|
return async_block(true);
|
||||||
|
};
|
||||||
|
foo
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod const_evaluation {
|
mod const_evaluation {
|
||||||
const PI: i64 = 3.14159;
|
const PI: f64 = 3.14159;
|
||||||
|
|
||||||
const fn add_two(n: i64) -> i64 {
|
const fn add_two(n: i64) -> i64 {
|
||||||
n + 2
|
n + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
const A_NUMBER: i64 = if add_two(2) + 2 == 4 { PI } else { 0 };
|
const A_NUMBER: f64 = if add_two(2) + 2 == 4 { PI } else { 0.0 };
|
||||||
|
|
||||||
fn const_block_assert<T>() -> usize {
|
fn const_block_assert<T>() -> usize {
|
||||||
// If this code ever gets executed, then the assertion has definitely
|
// If this code ever gets executed, then the assertion has definitely
|
||||||
@@ -444,6 +446,16 @@ fn dead_code() -> i64 {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_thing() {}
|
||||||
|
|
||||||
|
fn condition_not_met() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_next_thing() {}
|
||||||
|
|
||||||
|
fn do_last_thing() {}
|
||||||
|
|
||||||
fn labelled_block1() -> i64 {
|
fn labelled_block1() -> i64 {
|
||||||
let result = 'block: {
|
let result = 'block: {
|
||||||
do_thing();
|
do_thing();
|
||||||
@@ -457,19 +469,20 @@ fn labelled_block1() -> i64 {
|
|||||||
do_last_thing();
|
do_last_thing();
|
||||||
3
|
3
|
||||||
};
|
};
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn labelled_block2() -> i64 {
|
fn labelled_block2() {
|
||||||
let result = 'block: {
|
let result = 'block: {
|
||||||
let x: Option<i64> = None;
|
let x: Option<i64> = None;
|
||||||
let Some(y) = x else {
|
let Some(y) = x else {
|
||||||
break 'block 1;
|
break 'block 1;
|
||||||
};
|
};
|
||||||
x
|
0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_nested_function() {
|
fn test_nested_function2() {
|
||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
fn nested(x: &mut i64) {
|
fn nested(x: &mut i64) {
|
||||||
*x += 1;
|
*x += 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user