Skip to content

Commit aaa3b1b

Browse files
committed
Rust: Add a couple of new test cases.
1 parent a25ae39 commit aaa3b1b

File tree

5 files changed

+119
-65
lines changed

5 files changed

+119
-65
lines changed

rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#select
22
| main.rs:6:25:6:30 | &regex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | &regex | This regular expression is constructed from a $@. | main.rs:4:20:4:32 | ...::var | user-provided value |
3+
| main.rs:21:25:21:30 | &regex | main.rs:19:23:19:35 | ...::var | main.rs:21:25:21:30 | &regex | This regular expression is constructed from a $@. | main.rs:19:23:19:35 | ...::var | user-provided value |
34
edges
45
| main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | |
56
| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:1 |
@@ -8,14 +9,28 @@ edges
89
| main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | |
910
| main.rs:5:25:5:44 | ...::format(...) | main.rs:5:25:5:44 | { ... } | provenance | |
1011
| main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | |
11-
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:3 |
12-
| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:4 |
12+
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:4 |
13+
| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:5 |
1314
| main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | &regex | provenance | |
15+
| main.rs:19:9:19:19 | user_number | main.rs:20:25:20:47 | MacroExpr | provenance | |
16+
| main.rs:19:23:19:35 | ...::var | main.rs:19:23:19:43 | ...::var(...) [Ok] | provenance | Src:MaD:1 |
17+
| main.rs:19:23:19:43 | ...::var(...) [Ok] | main.rs:19:23:19:70 | ... .unwrap_or(...) | provenance | MaD:2 |
18+
| main.rs:19:23:19:70 | ... .unwrap_or(...) | main.rs:19:23:19:85 | ... .parse() [Ok] | provenance | MaD:3 |
19+
| main.rs:19:23:19:70 | ... .unwrap_or(...) | main.rs:19:23:19:85 | ... .parse() [Ok] | provenance | MaD:3 |
20+
| main.rs:19:23:19:85 | ... .parse() [Ok] | main.rs:19:23:19:98 | ... .unwrap_or(...) | provenance | MaD:2 |
21+
| main.rs:19:23:19:98 | ... .unwrap_or(...) | main.rs:19:9:19:19 | user_number | provenance | |
22+
| main.rs:20:9:20:13 | regex | main.rs:21:26:21:30 | regex | provenance | |
23+
| main.rs:20:25:20:47 | ...::format(...) | main.rs:20:25:20:47 | { ... } | provenance | |
24+
| main.rs:20:25:20:47 | ...::must_use(...) | main.rs:20:9:20:13 | regex | provenance | |
25+
| main.rs:20:25:20:47 | MacroExpr | main.rs:20:25:20:47 | ...::format(...) | provenance | MaD:4 |
26+
| main.rs:20:25:20:47 | { ... } | main.rs:20:25:20:47 | ...::must_use(...) | provenance | MaD:5 |
27+
| main.rs:21:26:21:30 | regex | main.rs:21:25:21:30 | &regex | provenance | |
1428
models
1529
| 1 | Source: std::env::var; ReturnValue.Field[core::result::Result::Ok(0)]; environment |
1630
| 2 | Summary: <core::result::Result>::unwrap_or; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
17-
| 3 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
18-
| 4 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
31+
| 3 | Summary: <core::str>::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
32+
| 4 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
33+
| 5 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
1934
nodes
2035
| main.rs:4:9:4:16 | username | semmle.label | username |
2136
| main.rs:4:20:4:32 | ...::var | semmle.label | ...::var |
@@ -28,4 +43,17 @@ nodes
2843
| main.rs:5:25:5:44 | { ... } | semmle.label | { ... } |
2944
| main.rs:6:25:6:30 | &regex | semmle.label | &regex |
3045
| main.rs:6:26:6:30 | regex | semmle.label | regex |
46+
| main.rs:19:9:19:19 | user_number | semmle.label | user_number |
47+
| main.rs:19:23:19:35 | ...::var | semmle.label | ...::var |
48+
| main.rs:19:23:19:43 | ...::var(...) [Ok] | semmle.label | ...::var(...) [Ok] |
49+
| main.rs:19:23:19:70 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
50+
| main.rs:19:23:19:85 | ... .parse() [Ok] | semmle.label | ... .parse() [Ok] |
51+
| main.rs:19:23:19:98 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
52+
| main.rs:20:9:20:13 | regex | semmle.label | regex |
53+
| main.rs:20:25:20:47 | ...::format(...) | semmle.label | ...::format(...) |
54+
| main.rs:20:25:20:47 | ...::must_use(...) | semmle.label | ...::must_use(...) |
55+
| main.rs:20:25:20:47 | MacroExpr | semmle.label | MacroExpr |
56+
| main.rs:20:25:20:47 | { ... } | semmle.label | { ... } |
57+
| main.rs:21:25:21:30 | &regex | semmle.label | &regex |
58+
| main.rs:21:26:21:30 | regex | semmle.label | regex |
3159
subpaths
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
| main.rs:6:25:6:30 | &regex |
22
| main.rs:14:25:14:30 | &regex |
3+
| main.rs:21:25:21:30 | &regex |

rust/ql/test/query-tests/security/CWE-020/main.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@ fn simple_bad(hay: &str) -> Option<bool> {
77
Some(re.is_match(hay))
88
}
99

10-
fn simple_good(hay: &str) -> Option<bool> {
10+
fn simple_good_escaped(hay: &str) -> Option<bool> {
1111
let username = std::env::var("USER").unwrap_or("".to_string());
1212
let escaped = regex::escape(&username);
1313
let regex = format!("foo{}bar", escaped);
1414
let re = Regex::new(&regex).unwrap();
1515
Some(re.is_match(hay))
1616
}
1717

18+
fn simple_good_numeric(hay: &str) -> Option<bool> {
19+
let user_number = std::env::var("USER").unwrap_or("0".to_string()).parse::<u64>().unwrap_or(0); // $ Source=env
20+
let regex = format!("foo{}bar", user_number);
21+
let re = Regex::new(&regex).unwrap(); // $ SPURIOUS: Alert[rust/regex-injection]=env
22+
Some(re.is_match(hay))
23+
}
24+
1825
fn not_a_sink_literal() -> Option<bool> {
1926
let username = std::env::var("USER").unwrap_or("".to_string());
2027
let re = Regex::new("literal string").unwrap();
@@ -30,7 +37,8 @@ fn not_a_sink_raw_literal() -> Option<bool> {
3037
fn main() {
3138
let hay = "a string";
3239
simple_bad(hay);
33-
simple_good(hay);
40+
simple_good_escaped(hay);
41+
simple_good_numeric(hay);
3442
not_a_sink_literal();
3543
not_a_sink_raw_literal();
3644
}

0 commit comments

Comments
 (0)