From 6966c96e7a4250ef0910485d9c852d6a036d50c4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:56:24 +0000 Subject: [PATCH 01/18] Rust: Add a test case for parse on a command line arg. --- .../dataflow/sources/TaintSources.expected | 25 ++++++++++--------- .../library-tests/dataflow/sources/test.rs | 2 ++ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 02acbd5bbeb4..4387ca65bd05 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -7,15 +7,16 @@ | test.rs:29:29:29:42 | ...::args | Flow source 'CommandLineArgs' of type commandargs. | | test.rs:32:16:32:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs. | | test.rs:33:16:33:32 | ...::args_os | Flow source 'CommandLineArgs' of type commandargs. | -| test.rs:40:16:40:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs. | -| test.rs:44:16:44:32 | ...::args_os | Flow source 'CommandLineArgs' of type commandargs. | -| test.rs:50:15:50:35 | ...::current_dir | Flow source 'CommandLineArgs' of type commandargs. | -| test.rs:51:15:51:35 | ...::current_exe | Flow source 'CommandLineArgs' of type commandargs. | -| test.rs:52:16:52:33 | ...::home_dir | Flow source 'CommandLineArgs' of type commandargs. | -| test.rs:60:26:60:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:63:26:63:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:66:26:66:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:69:26:69:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:72:26:72:37 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:75:26:75:37 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:78:24:78:35 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:34:16:34:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:42:16:42:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:46:16:46:32 | ...::args_os | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:52:15:52:35 | ...::current_dir | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:53:15:53:35 | ...::current_exe | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:54:16:54:33 | ...::home_dir | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:62:26:62:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:65:26:65:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:68:26:68:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:71:26:71:47 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:74:26:74:37 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:77:26:77:37 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:80:24:80:35 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index e867c2961d67..23fc35849d37 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -31,11 +31,13 @@ fn test_env_args() { let arg1 = &args[1]; let arg2 = std::env::args().nth(2).unwrap(); // $ Alert[rust/summary/taint-sources] let arg3 = std::env::args_os().nth(3).unwrap(); // $ Alert[rust/summary/taint-sources] + let arg4 = std::env::args().nth(4).unwrap().parse::().unwrap(); // $ Alert[rust/summary/taint-sources] sink(my_path); // $ MISSING: hasTaintFlow sink(arg1); // $ MISSING: hasTaintFlow sink(arg2); // $ MISSING: hasTaintFlow sink(arg3); // $ MISSING: hasTaintFlow + sink(arg4); // $ MISSING: hasTaintFlow for arg in std::env::args() { // $ Alert[rust/summary/taint-sources] sink(arg); // $ hasTaintFlow From c597818c4b68a0c7c9484848d3b2bf125f38abac Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 6 Feb 2025 10:29:02 +0000 Subject: [PATCH 02/18] Rust: Add a flow test for to_string() and parse(). --- .../dataflow/local/DataFlowStep.expected | 29 +++++++++++++++++-- .../dataflow/local/inline-flow.expected | 6 ++++ .../test/library-tests/dataflow/local/main.rs | 17 +++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index b4980fcc80ee..1c50275ea499 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -495,8 +495,31 @@ localStep | main.rs:428:9:428:9 | s | main.rs:428:9:428:9 | [SSA] s | | | main.rs:428:13:428:27 | MacroExpr | main.rs:428:9:428:9 | s | | | main.rs:428:25:428:26 | source(...) | main.rs:428:13:428:27 | MacroExpr | | -| main.rs:454:13:454:33 | result_questionmark(...) | main.rs:454:9:454:9 | _ | | -| main.rs:466:36:466:41 | ...::new(...) | main.rs:466:36:466:41 | MacroExpr | | +| main.rs:432:16:432:16 | [SSA] s | main.rs:433:20:433:20 | s | | +| main.rs:432:16:432:16 | s | main.rs:432:16:432:16 | [SSA] s | | +| main.rs:432:16:432:24 | ...: String | main.rs:432:16:432:16 | s | | +| main.rs:433:14:433:20 | FormatArgsExpr | main.rs:433:14:433:20 | MacroExpr | | +| main.rs:433:14:433:20 | MacroExpr | main.rs:433:5:433:21 | ...::_print | MaD:1 | +| main.rs:437:9:437:9 | [SSA] a | main.rs:438:13:438:13 | a | | +| main.rs:437:9:437:9 | a | main.rs:437:9:437:9 | [SSA] a | | +| main.rs:437:13:437:22 | source(...) | main.rs:437:9:437:9 | a | | +| main.rs:438:9:438:9 | [SSA] b | main.rs:439:13:439:13 | b | | +| main.rs:438:9:438:9 | b | main.rs:438:9:438:9 | [SSA] b | | +| main.rs:438:13:438:13 | [post] a | main.rs:442:10:442:10 | a | | +| main.rs:438:13:438:13 | a | main.rs:442:10:442:10 | a | | +| main.rs:438:13:438:25 | a.to_string(...) | main.rs:438:9:438:9 | b | | +| main.rs:439:9:439:9 | [SSA] c | main.rs:444:10:444:10 | c | | +| main.rs:439:9:439:9 | c | main.rs:439:9:439:9 | [SSA] c | | +| main.rs:439:13:439:13 | [post] b | main.rs:440:19:440:19 | b | | +| main.rs:439:13:439:13 | b | main.rs:440:19:440:19 | b | | +| main.rs:439:13:439:37 | ... .unwrap(...) | main.rs:439:9:439:9 | c | | +| main.rs:440:9:440:9 | [SSA] d | main.rs:445:10:445:10 | d | | +| main.rs:440:9:440:9 | d | main.rs:440:9:440:9 | [SSA] d | | +| main.rs:440:19:440:19 | [post] b | main.rs:443:17:443:17 | b | | +| main.rs:440:19:440:19 | b | main.rs:443:17:443:17 | b | | +| main.rs:440:19:440:36 | ... .unwrap(...) | main.rs:440:9:440:9 | d | | +| main.rs:470:13:470:33 | result_questionmark(...) | main.rs:470:9:470:9 | _ | | +| main.rs:482:36:482:41 | ...::new(...) | main.rs:482:36:482:41 | MacroExpr | | models | 1 | Sink: lang:std; crate::io::stdio::_print; log-injection; Argument[0] | | 2 | Summary: lang:core; ::expect; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value | @@ -601,7 +624,7 @@ storeStep | main.rs:399:30:399:30 | 3 | element | main.rs:399:23:399:31 | [...] | | main.rs:402:18:402:27 | source(...) | element | main.rs:402:5:402:11 | [post] mut_arr | | main.rs:414:41:414:67 | default_name | captured default_name | main.rs:414:41:414:67 | \|...\| ... | -| main.rs:436:27:436:27 | 0 | Some | main.rs:436:22:436:28 | Some(...) | +| main.rs:452:27:452:27 | 0 | Some | main.rs:452:22:452:28 | Some(...) | readStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index ded41054c751..4f2978a2da1d 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -179,6 +179,8 @@ edges | main.rs:405:10:405:16 | mut_arr [element] | main.rs:405:10:405:19 | mut_arr[0] | provenance | | | main.rs:428:9:428:9 | s | main.rs:429:10:429:10 | s | provenance | | | main.rs:428:25:428:26 | source(...) | main.rs:428:9:428:9 | s | provenance | | +| main.rs:437:9:437:9 | a | main.rs:442:10:442:10 | a | provenance | | +| main.rs:437:13:437:22 | source(...) | main.rs:437:9:437:9 | a | provenance | | nodes | main.rs:15:10:15:18 | source(...) | semmle.label | source(...) | | main.rs:19:9:19:9 | s | semmle.label | s | @@ -386,6 +388,9 @@ nodes | main.rs:428:9:428:9 | s | semmle.label | s | | main.rs:428:25:428:26 | source(...) | semmle.label | source(...) | | main.rs:429:10:429:10 | s | semmle.label | s | +| main.rs:437:9:437:9 | a | semmle.label | a | +| main.rs:437:13:437:22 | source(...) | semmle.label | source(...) | +| main.rs:442:10:442:10 | a | semmle.label | a | subpaths testFailures #select @@ -430,3 +435,4 @@ testFailures | main.rs:404:10:404:10 | d | main.rs:402:18:402:27 | source(...) | main.rs:404:10:404:10 | d | $@ | main.rs:402:18:402:27 | source(...) | source(...) | | main.rs:405:10:405:19 | mut_arr[0] | main.rs:402:18:402:27 | source(...) | main.rs:405:10:405:19 | mut_arr[0] | $@ | main.rs:402:18:402:27 | source(...) | source(...) | | main.rs:429:10:429:10 | s | main.rs:428:25:428:26 | source(...) | main.rs:429:10:429:10 | s | $@ | main.rs:428:25:428:26 | source(...) | source(...) | +| main.rs:442:10:442:10 | a | main.rs:437:13:437:22 | source(...) | main.rs:442:10:442:10 | a | $@ | main.rs:437:13:437:22 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index 0aae7d866847..444897b422f1 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -429,6 +429,22 @@ fn macro_invocation() { sink(s); // $ hasValueFlow=37 } +fn sink_string(s: String) { + println!("{}", s); +} + +fn parse() { + let a = source(90); + let b = a.to_string(); + let c = b.parse::().unwrap(); + let d : i64 = b.parse().unwrap(); + + sink(a); // $ hasValueFlow=90 + sink_string(b); // $ MISSING: hasTaintFlow=90 + sink(c); // $ MISSING: hasTaintFlow=90 + sink(d); // $ MISSING: hasTaintFlow=90 +} + fn main() { direct(); variable_usage(); @@ -465,4 +481,5 @@ fn main() { array_assignment(); captured_variable_and_continue(vec![]); macro_invocation(); + parse(); } From 1ff7a521d549f1b6f1e70a5f80a0b7b27c0d0343 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 6 Feb 2025 10:46:28 +0000 Subject: [PATCH 03/18] Rust: Add a flow test for some iterator methods. --- .../dataflow/local/DataFlowStep.expected | 51 +++++++++++++++++-- .../dataflow/local/inline-flow.expected | 17 +++++++ .../test/library-tests/dataflow/local/main.rs | 27 ++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 1c50275ea499..6c040a3f7440 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -518,8 +518,39 @@ localStep | main.rs:440:19:440:19 | [post] b | main.rs:443:17:443:17 | b | | | main.rs:440:19:440:19 | b | main.rs:443:17:443:17 | b | | | main.rs:440:19:440:36 | ... .unwrap(...) | main.rs:440:9:440:9 | d | | -| main.rs:470:13:470:33 | result_questionmark(...) | main.rs:470:9:470:9 | _ | | -| main.rs:482:36:482:41 | ...::new(...) | main.rs:482:36:482:41 | MacroExpr | | +| main.rs:449:9:449:10 | [SSA] vs | main.rs:451:10:451:11 | vs | | +| main.rs:449:9:449:10 | vs | main.rs:449:9:449:10 | [SSA] vs | | +| main.rs:449:14:449:34 | [...] | main.rs:449:9:449:10 | vs | | +| main.rs:451:10:451:11 | [post] vs | main.rs:452:11:452:12 | vs | | +| main.rs:451:10:451:11 | vs | main.rs:452:11:452:12 | vs | | +| main.rs:452:11:452:12 | [post] vs | main.rs:453:11:453:12 | vs | | +| main.rs:452:11:452:12 | vs | main.rs:453:11:453:12 | vs | | +| main.rs:453:11:453:12 | [post] vs | main.rs:455:14:455:15 | vs | | +| main.rs:453:11:453:12 | vs | main.rs:455:14:455:15 | vs | | +| main.rs:455:9:455:9 | [SSA] v | main.rs:456:14:456:14 | v | | +| main.rs:455:9:455:9 | v | main.rs:455:9:455:9 | [SSA] v | | +| main.rs:455:14:455:15 | vs | main.rs:458:15:458:16 | vs | | +| main.rs:458:10:458:10 | [SSA] v | main.rs:459:14:459:14 | v | | +| main.rs:458:10:458:10 | v | main.rs:458:10:458:10 | [SSA] v | | +| main.rs:458:15:458:16 | [post] vs | main.rs:462:27:462:28 | vs | | +| main.rs:458:15:458:16 | vs | main.rs:462:27:462:28 | vs | | +| main.rs:462:9:462:11 | [SSA] vs2 | main.rs:463:15:463:17 | vs2 | | +| main.rs:462:9:462:11 | vs2 | main.rs:462:9:462:11 | [SSA] vs2 | | +| main.rs:462:27:462:28 | [post] vs | main.rs:467:5:467:6 | vs | | +| main.rs:462:27:462:28 | vs | main.rs:467:5:467:6 | vs | | +| main.rs:462:27:462:45 | ... .collect(...) | main.rs:462:9:462:11 | vs2 | | +| main.rs:463:10:463:10 | [SSA] v | main.rs:464:14:464:14 | v | | +| main.rs:463:10:463:10 | v | main.rs:463:10:463:10 | [SSA] v | | +| main.rs:467:5:467:6 | [post] vs | main.rs:469:14:469:15 | vs | | +| main.rs:467:5:467:6 | vs | main.rs:469:14:469:15 | vs | | +| main.rs:467:20:467:20 | ... | main.rs:467:20:467:20 | x | | +| main.rs:467:20:467:20 | [SSA] x | main.rs:467:29:467:29 | x | | +| main.rs:467:20:467:20 | x | main.rs:467:20:467:20 | [SSA] x | | +| main.rs:469:5:471:5 | for ... in ... { ... } | main.rs:448:16:472:1 | { ... } | | +| main.rs:469:9:469:9 | [SSA] v | main.rs:470:14:470:14 | v | | +| main.rs:469:9:469:9 | v | main.rs:469:9:469:9 | [SSA] v | | +| main.rs:496:13:496:33 | result_questionmark(...) | main.rs:496:9:496:9 | _ | | +| main.rs:508:36:508:41 | ...::new(...) | main.rs:508:36:508:41 | MacroExpr | | models | 1 | Sink: lang:std; crate::io::stdio::_print; log-injection; Argument[0] | | 2 | Summary: lang:core; ::expect; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value | @@ -624,7 +655,11 @@ storeStep | main.rs:399:30:399:30 | 3 | element | main.rs:399:23:399:31 | [...] | | main.rs:402:18:402:27 | source(...) | element | main.rs:402:5:402:11 | [post] mut_arr | | main.rs:414:41:414:67 | default_name | captured default_name | main.rs:414:41:414:67 | \|...\| ... | -| main.rs:452:27:452:27 | 0 | Some | main.rs:452:22:452:28 | Some(...) | +| main.rs:449:15:449:24 | source(...) | element | main.rs:449:14:449:34 | [...] | +| main.rs:449:27:449:27 | 2 | element | main.rs:449:14:449:34 | [...] | +| main.rs:449:30:449:30 | 3 | element | main.rs:449:14:449:34 | [...] | +| main.rs:449:33:449:33 | 4 | element | main.rs:449:14:449:34 | [...] | +| main.rs:478:27:478:27 | 0 | Some | main.rs:478:22:478:28 | Some(...) | readStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | @@ -722,3 +757,13 @@ readStep | main.rs:412:25:412:29 | names | element | main.rs:412:9:412:20 | TuplePat | | main.rs:414:41:414:67 | [post] \|...\| ... | captured default_name | main.rs:414:41:414:67 | [post] default_name | | main.rs:414:44:414:55 | this | captured default_name | main.rs:414:44:414:55 | default_name | +| main.rs:451:10:451:11 | vs | element | main.rs:451:10:451:14 | vs[0] | +| main.rs:452:11:452:35 | ... .unwrap(...) | &ref | main.rs:452:10:452:35 | * ... | +| main.rs:453:11:453:35 | ... .unwrap(...) | &ref | main.rs:453:10:453:35 | * ... | +| main.rs:455:14:455:15 | vs | element | main.rs:455:9:455:9 | v | +| main.rs:458:9:458:10 | &... | &ref | main.rs:458:10:458:10 | v | +| main.rs:458:15:458:23 | vs.iter(...) | element | main.rs:458:9:458:10 | &... | +| main.rs:463:9:463:10 | &... | &ref | main.rs:463:10:463:10 | v | +| main.rs:463:15:463:17 | vs2 | element | main.rs:463:9:463:10 | &... | +| main.rs:467:29:467:29 | x | &ref | main.rs:467:28:467:29 | * ... | +| main.rs:469:14:469:27 | vs.into_iter(...) | element | main.rs:469:9:469:9 | v | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index 4f2978a2da1d..cec3c9c8293f 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -181,6 +181,13 @@ edges | main.rs:428:25:428:26 | source(...) | main.rs:428:9:428:9 | s | provenance | | | main.rs:437:9:437:9 | a | main.rs:442:10:442:10 | a | provenance | | | main.rs:437:13:437:22 | source(...) | main.rs:437:9:437:9 | a | provenance | | +| main.rs:449:9:449:10 | vs [element] | main.rs:451:10:451:11 | vs [element] | provenance | | +| main.rs:449:9:449:10 | vs [element] | main.rs:455:14:455:15 | vs [element] | provenance | | +| main.rs:449:14:449:34 | [...] [element] | main.rs:449:9:449:10 | vs [element] | provenance | | +| main.rs:449:15:449:24 | source(...) | main.rs:449:14:449:34 | [...] [element] | provenance | | +| main.rs:451:10:451:11 | vs [element] | main.rs:451:10:451:14 | vs[0] | provenance | | +| main.rs:455:9:455:9 | v | main.rs:456:14:456:14 | v | provenance | | +| main.rs:455:14:455:15 | vs [element] | main.rs:455:9:455:9 | v | provenance | | nodes | main.rs:15:10:15:18 | source(...) | semmle.label | source(...) | | main.rs:19:9:19:9 | s | semmle.label | s | @@ -391,6 +398,14 @@ nodes | main.rs:437:9:437:9 | a | semmle.label | a | | main.rs:437:13:437:22 | source(...) | semmle.label | source(...) | | main.rs:442:10:442:10 | a | semmle.label | a | +| main.rs:449:9:449:10 | vs [element] | semmle.label | vs [element] | +| main.rs:449:14:449:34 | [...] [element] | semmle.label | [...] [element] | +| main.rs:449:15:449:24 | source(...) | semmle.label | source(...) | +| main.rs:451:10:451:11 | vs [element] | semmle.label | vs [element] | +| main.rs:451:10:451:14 | vs[0] | semmle.label | vs[0] | +| main.rs:455:9:455:9 | v | semmle.label | v | +| main.rs:455:14:455:15 | vs [element] | semmle.label | vs [element] | +| main.rs:456:14:456:14 | v | semmle.label | v | subpaths testFailures #select @@ -436,3 +451,5 @@ testFailures | main.rs:405:10:405:19 | mut_arr[0] | main.rs:402:18:402:27 | source(...) | main.rs:405:10:405:19 | mut_arr[0] | $@ | main.rs:402:18:402:27 | source(...) | source(...) | | main.rs:429:10:429:10 | s | main.rs:428:25:428:26 | source(...) | main.rs:429:10:429:10 | s | $@ | main.rs:428:25:428:26 | source(...) | source(...) | | main.rs:442:10:442:10 | a | main.rs:437:13:437:22 | source(...) | main.rs:442:10:442:10 | a | $@ | main.rs:437:13:437:22 | source(...) | source(...) | +| main.rs:451:10:451:14 | vs[0] | main.rs:449:15:449:24 | source(...) | main.rs:451:10:451:14 | vs[0] | $@ | main.rs:449:15:449:24 | source(...) | source(...) | +| main.rs:456:14:456:14 | v | main.rs:449:15:449:24 | source(...) | main.rs:456:14:456:14 | v | $@ | main.rs:449:15:449:24 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index 444897b422f1..efae917dde4e 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -445,6 +445,32 @@ fn parse() { sink(d); // $ MISSING: hasTaintFlow=90 } +fn iterators() { + let vs = [source(91), 2, 3, 4]; + + sink(vs[0]); // $ hasValueFlow=91 + sink(*vs.iter().next().unwrap()); // $ MISSING: hasValueFlow=91 + sink(*vs.iter().nth(0).unwrap()); // $ MISSING: hasValueFlow=91 + + for v in vs { + sink(v); // $ hasValueFlow=91 + } + for &v in vs.iter() { + sink(v); // $ MISSING: hasValueFlow=91 + } + + let vs2 : Vec<&i64> = vs.iter().collect(); + for &v in vs2 { + sink(v); // $ MISSING: hasValueFlow=91 + } + + vs.iter().map(|x| sink(*x)); // $ MISSING: hasValueFlow=91 + + for v in vs.into_iter() { + sink(v); // $ MISSING: hasValueFlow=91 + } +} + fn main() { direct(); variable_usage(); @@ -482,4 +508,5 @@ fn main() { captured_variable_and_continue(vec![]); macro_invocation(); parse(); + iterators(); } From d0f5aad085dafe7ab5178d7ad0ff39dda209f2c8 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:24:05 +0000 Subject: [PATCH 04/18] Rust: Model to_string. --- rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml | 1 + rust/ql/test/library-tests/dataflow/local/main.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml index a0639a662d19..0e9290d88211 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml @@ -31,3 +31,4 @@ extensions: # String - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index efae917dde4e..e6bce460fc82 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -440,7 +440,7 @@ fn parse() { let d : i64 = b.parse().unwrap(); sink(a); // $ hasValueFlow=90 - sink_string(b); // $ MISSING: hasTaintFlow=90 + sink_string(b); // $ hasTaintFlow=90 sink(c); // $ MISSING: hasTaintFlow=90 sink(d); // $ MISSING: hasTaintFlow=90 } From a8a051234e522786c8440039930bb3e7529b4ce4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:49:23 +0000 Subject: [PATCH 05/18] Rust: Model parse. --- rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml | 2 ++ .../test/library-tests/dataflow/local/DataFlowStep.expected | 1 + rust/ql/test/library-tests/dataflow/local/main.rs | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml index 0e9290d88211..637e4c3af3a4 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml @@ -28,6 +28,8 @@ extensions: - ["lang:core", "::unwrap_err_unchecked", "Argument[self].Variant[crate::result::Result::Err(0)]", "ReturnValue", "value", "manual"] - ["lang:core", "::expect", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"] - ["lang:core", "::expect_err", "Argument[self].Variant[crate::result::Result::Err(0)]", "ReturnValue", "value", "manual"] + # Str + - ["lang:core", "::parse", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"] # String - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 6c040a3f7440..06f47b46d792 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -574,6 +574,7 @@ models | 20 | Summary: lang:core; ::unwrap_unchecked; Argument[self].Variant[crate::result::Result::Ok(0)]; ReturnValue; value | | 21 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | storeStep +| file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in lang:core::_::::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::parse | | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index e6bce460fc82..c8308933e2dc 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -441,8 +441,8 @@ fn parse() { sink(a); // $ hasValueFlow=90 sink_string(b); // $ hasTaintFlow=90 - sink(c); // $ MISSING: hasTaintFlow=90 - sink(d); // $ MISSING: hasTaintFlow=90 + sink(c); // $ hasTaintFlow=90 + sink(d); // $ hasTaintFlow=90 } fn iterators() { From bce47350621a4762ececa58fad558641e23bac65 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:29:26 +0000 Subject: [PATCH 06/18] Rust: Additional test case suggested by copilot. --- .../dataflow/local/DataFlowStep.expected | 24 ++++++++++++------- .../test/library-tests/dataflow/local/main.rs | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 06f47b46d792..3fbb1252c630 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -541,16 +541,21 @@ localStep | main.rs:462:27:462:45 | ... .collect(...) | main.rs:462:9:462:11 | vs2 | | | main.rs:463:10:463:10 | [SSA] v | main.rs:464:14:464:14 | v | | | main.rs:463:10:463:10 | v | main.rs:463:10:463:10 | [SSA] v | | -| main.rs:467:5:467:6 | [post] vs | main.rs:469:14:469:15 | vs | | -| main.rs:467:5:467:6 | vs | main.rs:469:14:469:15 | vs | | +| main.rs:467:5:467:6 | [post] vs | main.rs:468:5:468:6 | vs | | +| main.rs:467:5:467:6 | vs | main.rs:468:5:468:6 | vs | | | main.rs:467:20:467:20 | ... | main.rs:467:20:467:20 | x | | | main.rs:467:20:467:20 | [SSA] x | main.rs:467:29:467:29 | x | | | main.rs:467:20:467:20 | x | main.rs:467:20:467:20 | [SSA] x | | -| main.rs:469:5:471:5 | for ... in ... { ... } | main.rs:448:16:472:1 | { ... } | | -| main.rs:469:9:469:9 | [SSA] v | main.rs:470:14:470:14 | v | | -| main.rs:469:9:469:9 | v | main.rs:469:9:469:9 | [SSA] v | | -| main.rs:496:13:496:33 | result_questionmark(...) | main.rs:496:9:496:9 | _ | | -| main.rs:508:36:508:41 | ...::new(...) | main.rs:508:36:508:41 | MacroExpr | | +| main.rs:468:5:468:6 | [post] vs | main.rs:470:14:470:15 | vs | | +| main.rs:468:5:468:6 | vs | main.rs:470:14:470:15 | vs | | +| main.rs:468:25:468:25 | ... | main.rs:468:25:468:25 | x | | +| main.rs:468:25:468:25 | [SSA] x | main.rs:468:34:468:34 | x | | +| main.rs:468:25:468:25 | x | main.rs:468:25:468:25 | [SSA] x | | +| main.rs:470:5:472:5 | for ... in ... { ... } | main.rs:448:16:473:1 | { ... } | | +| main.rs:470:9:470:9 | [SSA] v | main.rs:471:14:471:14 | v | | +| main.rs:470:9:470:9 | v | main.rs:470:9:470:9 | [SSA] v | | +| main.rs:497:13:497:33 | result_questionmark(...) | main.rs:497:9:497:9 | _ | | +| main.rs:509:36:509:41 | ...::new(...) | main.rs:509:36:509:41 | MacroExpr | | models | 1 | Sink: lang:std; crate::io::stdio::_print; log-injection; Argument[0] | | 2 | Summary: lang:core; ::expect; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value | @@ -660,7 +665,7 @@ storeStep | main.rs:449:27:449:27 | 2 | element | main.rs:449:14:449:34 | [...] | | main.rs:449:30:449:30 | 3 | element | main.rs:449:14:449:34 | [...] | | main.rs:449:33:449:33 | 4 | element | main.rs:449:14:449:34 | [...] | -| main.rs:478:27:478:27 | 0 | Some | main.rs:478:22:478:28 | Some(...) | +| main.rs:479:27:479:27 | 0 | Some | main.rs:479:22:479:28 | Some(...) | readStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | @@ -767,4 +772,5 @@ readStep | main.rs:463:9:463:10 | &... | &ref | main.rs:463:10:463:10 | v | | main.rs:463:15:463:17 | vs2 | element | main.rs:463:9:463:10 | &... | | main.rs:467:29:467:29 | x | &ref | main.rs:467:28:467:29 | * ... | -| main.rs:469:14:469:27 | vs.into_iter(...) | element | main.rs:469:9:469:9 | v | +| main.rs:468:34:468:34 | x | &ref | main.rs:468:33:468:34 | * ... | +| main.rs:470:14:470:27 | vs.into_iter(...) | element | main.rs:470:9:470:9 | v | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index c8308933e2dc..811b214ad740 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -465,6 +465,7 @@ fn iterators() { } vs.iter().map(|x| sink(*x)); // $ MISSING: hasValueFlow=91 + vs.iter().for_each(|x| sink(*x)); // $ MISSING: hasValueFlow=91 for v in vs.into_iter() { sink(v); // $ MISSING: hasValueFlow=91 From 78e3c89c68172a14f50b8e06e3019a1b8fc5712e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:33:37 +0000 Subject: [PATCH 07/18] Rust: Accept changes to integration tests. --- rust/ql/integration-tests/hello-project/summary.expected | 2 +- .../ql/integration-tests/hello-workspace/summary.cargo.expected | 2 +- .../hello-workspace/summary.rust-project.expected | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/integration-tests/hello-project/summary.expected b/rust/ql/integration-tests/hello-project/summary.expected index 343b06a93b4c..9a1f25d2b830 100644 --- a/rust/ql/integration-tests/hello-project/summary.expected +++ b/rust/ql/integration-tests/hello-project/summary.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 3 | +| Taint edges - number of edges | 4 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | diff --git a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected index 24a7bbf392fe..9ab7d2a15d91 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 3 | +| Taint edges - number of edges | 4 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | diff --git a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected index 24a7bbf392fe..9ab7d2a15d91 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 3 | +| Taint edges - number of edges | 4 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | From f5b9691e7dcf394b582b7a6a33ac8894927a5520 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:14:53 +0000 Subject: [PATCH 08/18] Rust: Accept fixed result. --- rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected | 1 - rust/ql/test/library-tests/dataflow/sources/test.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected b/rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected index cbd0762436cd..e69de29bb2d1 100644 --- a/rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected +++ b/rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected @@ -1 +0,0 @@ -| test.rs:40:10:40:13 | arg4 | Fixed missing result: hasTaintFlow | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 9d808419cb86..2d986de53346 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -37,7 +37,7 @@ fn test_env_args() { sink(arg1); // $ hasTaintFlow sink(arg2); // $ hasTaintFlow sink(arg3); // $ hasTaintFlow - sink(arg4); // $ MISSING: hasTaintFlow + sink(arg4); // $ hasTaintFlow for arg in std::env::args() { // $ Alert[rust/summary/taint-sources] sink(arg); // $ hasTaintFlow From 4f734292514bbfc8c8218ac619765b673c4f21ec Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Feb 2025 17:38:51 +0000 Subject: [PATCH 09/18] Rust: Accept test changes after merging latest main. --- .../dataflow/taint/TaintFlowStep.expected | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected index c9c6b67d5caf..29facae458a9 100644 --- a/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected @@ -1,16 +1,18 @@ additionalTaintStep -| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::fmt::format | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::crate::fmt::format | MaD:3 | -| file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_bytes | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_bytes | MaD:1 | -| file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_str | MaD:2 | +| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::fmt::format | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::crate::fmt::format | MaD:4 | +| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<_ as crate::string::ToString>::to_string | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<_ as crate::string::ToString>::to_string | MaD:1 | +| file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_bytes | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_bytes | MaD:2 | +| file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_str | MaD:3 | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::parse | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in lang:core::_::::parse | MaD:5 | | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::collect | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | | | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::nth | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::nth | | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:4 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:5 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:6 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:7 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)].Variant[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | MaD:8 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:9 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:10 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:6 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:7 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:8 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:9 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)].Variant[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | MaD:10 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:11 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Variant[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:12 | | main.rs:4:5:4:8 | 1000 | main.rs:4:5:4:12 | ... + ... | | | main.rs:4:12:4:12 | i | main.rs:4:5:4:12 | ... + ... | | | main.rs:8:20:8:20 | s | main.rs:8:14:8:20 | FormatArgsExpr | | @@ -28,13 +30,15 @@ additionalTaintStep | main.rs:64:24:64:27 | s[1] | main.rs:64:18:64:27 | FormatArgsExpr | | | main.rs:69:9:69:12 | arr2 | main.rs:69:9:69:15 | arr2[1] | | models -| 1 | Summary: lang:alloc; ::as_bytes; Argument[self]; ReturnValue; taint | -| 2 | Summary: lang:alloc; ::as_str; Argument[self]; ReturnValue; taint | -| 3 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint | -| 4 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | -| 5 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | -| 6 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | -| 7 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | -| 8 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::chunk; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)].Variant[crate::option::Option::Some(0)]; taint | -| 9 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | -| 10 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 1 | Summary: lang:alloc; <_ as crate::string::ToString>::to_string; Argument[self]; ReturnValue; taint | +| 2 | Summary: lang:alloc; ::as_bytes; Argument[self]; ReturnValue; taint | +| 3 | Summary: lang:alloc; ::as_str; Argument[self]; ReturnValue; taint | +| 4 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint | +| 5 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 6 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 7 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 8 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 9 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 10 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::chunk; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)].Variant[crate::option::Option::Some(0)]; taint | +| 11 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 12 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | From f5ab6a6cd68af70d3c3eae6536288a720cd93763 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 11 Feb 2025 17:39:03 +0000 Subject: [PATCH 10/18] Rust: Accept integration test changes. --- .../ql/integration-tests/hello-workspace/summary.cargo.expected | 2 +- .../hello-workspace/summary.rust-project.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected index 9ab7d2a15d91..e5671bbd2d60 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 4 | +| Taint edges - number of edges | 5 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | diff --git a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected index 9ab7d2a15d91..e5671bbd2d60 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 4 | +| Taint edges - number of edges | 5 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | From e9b8ec9324b56bbfe13d1f3f38fcfdcbcd2c9f3a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:18:48 +0000 Subject: [PATCH 11/18] Rust: Accept integration test changes (again). --- rust/ql/integration-tests/hello-project/summary.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/integration-tests/hello-project/summary.expected b/rust/ql/integration-tests/hello-project/summary.expected index 9a1f25d2b830..0eeeeffbffdb 100644 --- a/rust/ql/integration-tests/hello-project/summary.expected +++ b/rust/ql/integration-tests/hello-project/summary.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 4 | +| Taint edges - number of edges | 5 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | From c07a57bf6b8506ad37bc8e8b1d72fcaba6d207b1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:31:10 +0000 Subject: [PATCH 12/18] Rust: Accept spurious test results (we need a barrier for numeric types of this query at some point; it's good that flow reaches it now). --- .../security/CWE-089/SqlInjection.expected | 39 +++++++++++++++++-- .../test/query-tests/security/CWE-089/sqlx.rs | 4 +- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected index c106f22e7ca7..2c32d3649b37 100644 --- a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected @@ -1,21 +1,37 @@ #select +| sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | edges +| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:49:25:49:37 | remote_string | provenance | | | sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:56:34:56:89 | MacroExpr | provenance | | | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | provenance | Src:MaD:1 | | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | sqlx.rs:48:25:48:78 | ... .unwrap(...) | provenance | MaD:4 | -| sqlx.rs:48:25:48:78 | ... .unwrap(...) | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | provenance | MaD:7 | +| sqlx.rs:48:25:48:78 | ... .unwrap(...) | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | provenance | MaD:8 | | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | sqlx.rs:48:25:48:118 | ... .unwrap_or(...) | provenance | MaD:5 | | sqlx.rs:48:25:48:118 | ... .unwrap_or(...) | sqlx.rs:48:9:48:21 | remote_string | provenance | | +| sqlx.rs:49:9:49:21 | remote_number | sqlx.rs:52:32:52:87 | MacroExpr | provenance | | +| sqlx.rs:49:25:49:37 | remote_string | sqlx.rs:49:25:49:52 | remote_string.parse(...) [Ok] | provenance | MaD:6 | +| sqlx.rs:49:25:49:52 | remote_string.parse(...) [Ok] | sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | provenance | MaD:5 | +| sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | sqlx.rs:49:9:49:21 | remote_number | provenance | | +| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:62:26:62:37 | safe_query_3 | provenance | | +| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:73:25:73:36 | safe_query_3 | provenance | | +| sqlx.rs:52:24:52:88 | res | sqlx.rs:52:32:52:87 | { ... } | provenance | | +| sqlx.rs:52:32:52:87 | ...::format(...) | sqlx.rs:52:24:52:88 | res | provenance | | +| sqlx.rs:52:32:52:87 | ...::must_use(...) | sqlx.rs:52:9:52:20 | safe_query_3 | provenance | | +| sqlx.rs:52:32:52:87 | MacroExpr | sqlx.rs:52:32:52:87 | ...::format(...) | provenance | MaD:3 | +| sqlx.rs:52:32:52:87 | { ... } | sqlx.rs:52:32:52:87 | ...::must_use(...) | provenance | MaD:7 | | sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:67:30:67:43 | unsafe_query_4 | provenance | | | sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:78:29:78:42 | unsafe_query_4 | provenance | | | sqlx.rs:56:26:56:90 | res | sqlx.rs:56:34:56:89 | { ... } | provenance | | | sqlx.rs:56:34:56:89 | ...::format(...) | sqlx.rs:56:26:56:90 | res | provenance | | | sqlx.rs:56:34:56:89 | ...::must_use(...) | sqlx.rs:56:9:56:22 | unsafe_query_4 | provenance | | | sqlx.rs:56:34:56:89 | MacroExpr | sqlx.rs:56:34:56:89 | ...::format(...) | provenance | MaD:3 | -| sqlx.rs:56:34:56:89 | { ... } | sqlx.rs:56:34:56:89 | ...::must_use(...) | provenance | MaD:6 | +| sqlx.rs:56:34:56:89 | { ... } | sqlx.rs:56:34:56:89 | ...::must_use(...) | provenance | MaD:7 | +| sqlx.rs:62:26:62:37 | safe_query_3 | sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | provenance | MaD:2 | | sqlx.rs:67:30:67:43 | unsafe_query_4 | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | provenance | MaD:2 | +| sqlx.rs:73:25:73:36 | safe_query_3 | sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | provenance | MaD:2 | | sqlx.rs:78:29:78:42 | unsafe_query_4 | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | provenance | MaD:2 | models | 1 | Source: repo:https://github.com/seanmonstar/reqwest:reqwest; crate::blocking::get; remote; ReturnValue.Variant[crate::result::Result::Ok(0)] | @@ -23,8 +39,9 @@ models | 3 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint | | 4 | Summary: lang:core; ::unwrap; Argument[self].Variant[crate::result::Result::Ok(0)]; ReturnValue; value | | 5 | Summary: lang:core; ::unwrap_or; Argument[self].Variant[crate::result::Result::Ok(0)]; ReturnValue; value | -| 6 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | -| 7 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 6 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | +| 7 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | +| 8 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Variant[crate::result::Result::Ok(0)]; taint | nodes | sqlx.rs:48:9:48:21 | remote_string | semmle.label | remote_string | | sqlx.rs:48:25:48:46 | ...::get | semmle.label | ...::get | @@ -32,14 +49,28 @@ nodes | sqlx.rs:48:25:48:78 | ... .unwrap(...) | semmle.label | ... .unwrap(...) | | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | semmle.label | ... .text(...) [Ok] | | sqlx.rs:48:25:48:118 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) | +| sqlx.rs:49:9:49:21 | remote_number | semmle.label | remote_number | +| sqlx.rs:49:25:49:37 | remote_string | semmle.label | remote_string | +| sqlx.rs:49:25:49:52 | remote_string.parse(...) [Ok] | semmle.label | remote_string.parse(...) [Ok] | +| sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) | +| sqlx.rs:52:9:52:20 | safe_query_3 | semmle.label | safe_query_3 | +| sqlx.rs:52:24:52:88 | res | semmle.label | res | +| sqlx.rs:52:32:52:87 | ...::format(...) | semmle.label | ...::format(...) | +| sqlx.rs:52:32:52:87 | ...::must_use(...) | semmle.label | ...::must_use(...) | +| sqlx.rs:52:32:52:87 | MacroExpr | semmle.label | MacroExpr | +| sqlx.rs:52:32:52:87 | { ... } | semmle.label | { ... } | | sqlx.rs:56:9:56:22 | unsafe_query_4 | semmle.label | unsafe_query_4 | | sqlx.rs:56:26:56:90 | res | semmle.label | res | | sqlx.rs:56:34:56:89 | ...::format(...) | semmle.label | ...::format(...) | | sqlx.rs:56:34:56:89 | ...::must_use(...) | semmle.label | ...::must_use(...) | | sqlx.rs:56:34:56:89 | MacroExpr | semmle.label | MacroExpr | | sqlx.rs:56:34:56:89 | { ... } | semmle.label | { ... } | +| sqlx.rs:62:26:62:37 | safe_query_3 | semmle.label | safe_query_3 | +| sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | semmle.label | safe_query_3.as_str(...) | | sqlx.rs:67:30:67:43 | unsafe_query_4 | semmle.label | unsafe_query_4 | | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | semmle.label | unsafe_query_4.as_str(...) | +| sqlx.rs:73:25:73:36 | safe_query_3 | semmle.label | safe_query_3 | +| sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | semmle.label | safe_query_3.as_str(...) | | sqlx.rs:78:29:78:42 | unsafe_query_4 | semmle.label | unsafe_query_4 | | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | semmle.label | unsafe_query_4.as_str(...) | subpaths diff --git a/rust/ql/test/query-tests/security/CWE-089/sqlx.rs b/rust/ql/test/query-tests/security/CWE-089/sqlx.rs index 24d3e585e95b..f819ea3a781e 100644 --- a/rust/ql/test/query-tests/security/CWE-089/sqlx.rs +++ b/rust/ql/test/query-tests/security/CWE-089/sqlx.rs @@ -59,7 +59,7 @@ async fn test_sqlx_mysql(url: &str, enable_remote: bool) -> Result<(), sqlx::Err // direct execution let _ = conn.execute(safe_query_1.as_str()).await?; // $ sql-sink let _ = conn.execute(safe_query_2.as_str()).await?; // $ sql-sink - let _ = conn.execute(safe_query_3.as_str()).await?; // $ sql-sink + let _ = conn.execute(safe_query_3.as_str()).await?; // $ sql-sink SPURIOUS: Alert[rust/sql-injection]=remote1 let _ = conn.execute(unsafe_query_1.as_str()).await?; // $ sql-sink MISSING: Alert[rust/sql-injection]=args1 if enable_remote { let _ = conn.execute(unsafe_query_2.as_str()).await?; // $ sql-sink MISSING: Alert[rust/sql-injection]=remote1 @@ -70,7 +70,7 @@ async fn test_sqlx_mysql(url: &str, enable_remote: bool) -> Result<(), sqlx::Err // prepared queries let _ = sqlx::query(safe_query_1.as_str()).execute(&pool).await?; // $ sql-sink let _ = sqlx::query(safe_query_2.as_str()).execute(&pool).await?; // $ sql-sink - let _ = sqlx::query(safe_query_3.as_str()).execute(&pool).await?; // $ sql-sink + let _ = sqlx::query(safe_query_3.as_str()).execute(&pool).await?; // $ sql-sink SPURIOUS: Alert[rust/sql-injection]=remote1 let _ = sqlx::query(unsafe_query_1.as_str()).execute(&pool).await?; // $ sql-sink MISSING: Alert[rust/sql-injection][rust/sql-injection]=args1 if enable_remote { let _ = sqlx::query(unsafe_query_2.as_str()).execute(&pool).await?; // $ sql-sink MISSING: Alert[rust/sql-injection]=remote1 From 6c314739f6f416911ee52998c9ec607a7e6e8632 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:33:21 +0000 Subject: [PATCH 13/18] Rust: Accept changes to the summary stats query .expected. --- rust/ql/test/query-tests/diagnostics/SummaryStats.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected index c3f922c52f72..f572b5b4afcc 100644 --- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected +++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 8 | | Macro calls - total | 9 | | Macro calls - unresolved | 1 | -| Taint edges - number of edges | 4 | +| Taint edges - number of edges | 5 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | From 79525fa4edd5c0b1e7aaad7e0e9e36ee587f4717 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:18:53 +0000 Subject: [PATCH 14/18] Rust: Variant -> Field. --- .../frameworks/stdlib/lang-core.model.yml | 2 +- .../dataflow/local/DataFlowStep.expected | 1 + .../dataflow/local/inline-flow.expected | 2 - .../security/CWE-089/SqlInjection.expected | 42 +++++++++++++++---- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml index ae525ac10c80..a5506c06e7e2 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml @@ -25,7 +25,7 @@ extensions: - ["lang:core", "::expect", "Argument[self].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"] - ["lang:core", "::expect_err", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue", "value", "manual"] # Str - - ["lang:core", "::parse", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:core", "::parse", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] # String - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 9c4e9d87e865..d59ecd44e932 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -790,6 +790,7 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::ok_or | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::ok_or_else | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or_else | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::transpose | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::parse | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index 8ec64e5323c1..ed25680e4fac 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -443,8 +443,6 @@ nodes | main.rs:500:11:500:15 | c_ref [&ref] | semmle.label | c_ref [&ref] | subpaths testFailures -| main.rs:460:14:460:33 | //... | Missing result: hasTaintFlow=90 | -| main.rs:461:14:461:33 | //... | Missing result: hasTaintFlow=90 | #select | main.rs:18:10:18:18 | source(...) | main.rs:18:10:18:18 | source(...) | main.rs:18:10:18:18 | source(...) | $@ | main.rs:18:10:18:18 | source(...) | source(...) | | main.rs:23:10:23:10 | s | main.rs:22:13:22:21 | source(...) | main.rs:23:10:23:10 | s | $@ | main.rs:22:13:22:21 | source(...) | source(...) | diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected index e4916d33ecbb..2462328c24cc 100644 --- a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected @@ -1,21 +1,37 @@ #select +| sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | edges +| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:49:25:49:37 | remote_string | provenance | | | sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:56:34:56:89 | MacroExpr | provenance | | | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | provenance | Src:MaD:1 | | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | sqlx.rs:48:25:48:78 | ... .unwrap(...) | provenance | MaD:4 | -| sqlx.rs:48:25:48:78 | ... .unwrap(...) | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | provenance | MaD:7 | +| sqlx.rs:48:25:48:78 | ... .unwrap(...) | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | provenance | MaD:8 | | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | sqlx.rs:48:25:48:118 | ... .unwrap_or(...) | provenance | MaD:5 | | sqlx.rs:48:25:48:118 | ... .unwrap_or(...) | sqlx.rs:48:9:48:21 | remote_string | provenance | | +| sqlx.rs:49:9:49:21 | remote_number | sqlx.rs:52:32:52:87 | MacroExpr | provenance | | +| sqlx.rs:49:25:49:37 | remote_string | sqlx.rs:49:25:49:52 | remote_string.parse(...) [Ok] | provenance | MaD:6 | +| sqlx.rs:49:25:49:52 | remote_string.parse(...) [Ok] | sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | provenance | MaD:5 | +| sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | sqlx.rs:49:9:49:21 | remote_number | provenance | | +| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:62:26:62:37 | safe_query_3 | provenance | | +| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:73:25:73:36 | safe_query_3 | provenance | | +| sqlx.rs:52:24:52:88 | res | sqlx.rs:52:32:52:87 | { ... } | provenance | | +| sqlx.rs:52:32:52:87 | ...::format(...) | sqlx.rs:52:24:52:88 | res | provenance | | +| sqlx.rs:52:32:52:87 | ...::must_use(...) | sqlx.rs:52:9:52:20 | safe_query_3 | provenance | | +| sqlx.rs:52:32:52:87 | MacroExpr | sqlx.rs:52:32:52:87 | ...::format(...) | provenance | MaD:3 | +| sqlx.rs:52:32:52:87 | { ... } | sqlx.rs:52:32:52:87 | ...::must_use(...) | provenance | MaD:7 | | sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:67:30:67:43 | unsafe_query_4 | provenance | | | sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:78:29:78:42 | unsafe_query_4 | provenance | | | sqlx.rs:56:26:56:90 | res | sqlx.rs:56:34:56:89 | { ... } | provenance | | | sqlx.rs:56:34:56:89 | ...::format(...) | sqlx.rs:56:26:56:90 | res | provenance | | | sqlx.rs:56:34:56:89 | ...::must_use(...) | sqlx.rs:56:9:56:22 | unsafe_query_4 | provenance | | | sqlx.rs:56:34:56:89 | MacroExpr | sqlx.rs:56:34:56:89 | ...::format(...) | provenance | MaD:3 | -| sqlx.rs:56:34:56:89 | { ... } | sqlx.rs:56:34:56:89 | ...::must_use(...) | provenance | MaD:6 | +| sqlx.rs:56:34:56:89 | { ... } | sqlx.rs:56:34:56:89 | ...::must_use(...) | provenance | MaD:7 | +| sqlx.rs:62:26:62:37 | safe_query_3 | sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | provenance | MaD:2 | | sqlx.rs:67:30:67:43 | unsafe_query_4 | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | provenance | MaD:2 | +| sqlx.rs:73:25:73:36 | safe_query_3 | sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | provenance | MaD:2 | | sqlx.rs:78:29:78:42 | unsafe_query_4 | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | provenance | MaD:2 | models | 1 | Source: repo:https://github.com/seanmonstar/reqwest:reqwest; crate::blocking::get; remote; ReturnValue.Field[crate::result::Result::Ok(0)] | @@ -23,8 +39,9 @@ models | 3 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint | | 4 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | | 5 | Summary: lang:core; ::unwrap_or; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | -| 6 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | -| 7 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 6 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 7 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | +| 8 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | nodes | sqlx.rs:48:9:48:21 | remote_string | semmle.label | remote_string | | sqlx.rs:48:25:48:46 | ...::get | semmle.label | ...::get | @@ -32,17 +49,28 @@ nodes | sqlx.rs:48:25:48:78 | ... .unwrap(...) | semmle.label | ... .unwrap(...) | | sqlx.rs:48:25:48:85 | ... .text(...) [Ok] | semmle.label | ... .text(...) [Ok] | | sqlx.rs:48:25:48:118 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) | +| sqlx.rs:49:9:49:21 | remote_number | semmle.label | remote_number | +| sqlx.rs:49:25:49:37 | remote_string | semmle.label | remote_string | +| sqlx.rs:49:25:49:52 | remote_string.parse(...) [Ok] | semmle.label | remote_string.parse(...) [Ok] | +| sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) | +| sqlx.rs:52:9:52:20 | safe_query_3 | semmle.label | safe_query_3 | +| sqlx.rs:52:24:52:88 | res | semmle.label | res | +| sqlx.rs:52:32:52:87 | ...::format(...) | semmle.label | ...::format(...) | +| sqlx.rs:52:32:52:87 | ...::must_use(...) | semmle.label | ...::must_use(...) | +| sqlx.rs:52:32:52:87 | MacroExpr | semmle.label | MacroExpr | +| sqlx.rs:52:32:52:87 | { ... } | semmle.label | { ... } | | sqlx.rs:56:9:56:22 | unsafe_query_4 | semmle.label | unsafe_query_4 | | sqlx.rs:56:26:56:90 | res | semmle.label | res | | sqlx.rs:56:34:56:89 | ...::format(...) | semmle.label | ...::format(...) | | sqlx.rs:56:34:56:89 | ...::must_use(...) | semmle.label | ...::must_use(...) | | sqlx.rs:56:34:56:89 | MacroExpr | semmle.label | MacroExpr | | sqlx.rs:56:34:56:89 | { ... } | semmle.label | { ... } | +| sqlx.rs:62:26:62:37 | safe_query_3 | semmle.label | safe_query_3 | +| sqlx.rs:62:26:62:46 | safe_query_3.as_str(...) | semmle.label | safe_query_3.as_str(...) | | sqlx.rs:67:30:67:43 | unsafe_query_4 | semmle.label | unsafe_query_4 | | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str(...) | semmle.label | unsafe_query_4.as_str(...) | +| sqlx.rs:73:25:73:36 | safe_query_3 | semmle.label | safe_query_3 | +| sqlx.rs:73:25:73:45 | safe_query_3.as_str(...) | semmle.label | safe_query_3.as_str(...) | | sqlx.rs:78:29:78:42 | unsafe_query_4 | semmle.label | unsafe_query_4 | | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str(...) | semmle.label | unsafe_query_4.as_str(...) | subpaths -testFailures -| sqlx.rs:62:57:62:113 | //... | Fixed spurious result: Alert[rust/sql-injection]=remote1 | -| sqlx.rs:73:71:73:127 | //... | Fixed spurious result: Alert[rust/sql-injection]=remote1 | From 8024fb6812e0141d0c43400c3693a7c40c2efdd9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:45:04 +0000 Subject: [PATCH 15/18] Rust: Add more models for Iterator. --- .../frameworks/stdlib/lang-core.model.yml | 11 ++++ .../dataflow/local/DataFlowStep.expected | 52 ++++++++++++++++--- .../dataflow/taint/TaintFlowStep.expected | 38 +++++++++----- .../diagnostics/SummaryStats.expected | 2 +- 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml index a5506c06e7e2..04c4fceb87a2 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml @@ -8,8 +8,19 @@ extensions: # Hint - ["lang:core", "crate::hint::must_use", "Argument[0]", "ReturnValue", "value", "manual"] # Iterator + - ["lang:core", "<[_]>::iter", "Argument[Self].Element", "ReturnValue.Element", "value", "manual"] + - ["lang:core", "<[_]>::iter_mut", "Argument[Self].Element", "ReturnValue.Element", "value", "manual"] + - ["lang:core", "<[_]>::into_iter", "Argument[Self].Element", "ReturnValue.Element", "value", "manual"] - ["lang:core", "crate::iter::traits::iterator::Iterator::nth", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "manual"] + - ["lang:core", "crate::iter::traits::iterator::Iterator::next", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "manual"] - ["lang:core", "crate::iter::traits::iterator::Iterator::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["lang:core", "crate::iter::traits::iterator::Iterator::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["lang:core", "crate::iter::traits::iterator::Iterator::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["lang:core", "::nth", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "manual"] + - ["lang:core", "::next", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "manual"] + - ["lang:core", "::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["lang:core", "::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["lang:core", "::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] # Option - ["lang:core", "::expect", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"] # Result diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index d59ecd44e932..5c274ea97863 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -4,6 +4,10 @@ localStep | file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::::is_some_and | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_some_and | MaD:26 | | file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::::map | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map | MaD:28 | | file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::::take_if | file://:0:0:0:0 | [summary] to write: Argument[self].Reference.Field[crate::option::Option::Some(0)] in lang:core::_::::take_if | MaD:43 | +| file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::::for_each | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::::for_each | MaD:74 | +| file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::::map | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::::map | MaD:75 | +| file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | MaD:80 | +| file://:0:0:0:0 | [post] [summary] to write: Argument[0].Parameter[0] in lang:core::_::crate::iter::traits::iterator::Iterator::map | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::map | MaD:81 | | file://:0:0:0:0 | [post] [summary] to write: Argument[1].Parameter[0] in lang:core::_::::map_or | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map_or | MaD:31 | | file://:0:0:0:0 | [post] [summary] to write: Argument[1].Parameter[0] in lang:core::_::::map_or_else | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map_or_else | MaD:34 | | file://:0:0:0:0 | [post] [summary] to write: Argument[1].Parameter[0] in lang:core::_::::zip_with | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | MaD:61 | @@ -34,7 +38,11 @@ localStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::xor | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::xor | MaD:55 | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::unwrap_or | MaD:67 | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[closure self] in lang:core::_::::unwrap_or_else | MaD:70 | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::hint::must_use | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::hint::must_use | MaD:73 | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::for_each | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[closure self] in lang:core::_::::for_each | MaD:74 | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[closure self] in lang:core::_::::map | MaD:75 | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::hint::must_use | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::hint::must_use | MaD:78 | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[closure self] in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | MaD:80 | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::iter::traits::iterator::Iterator::map | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[closure self] in lang:core::_::crate::iter::traits::iterator::Iterator::map | MaD:81 | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::map_or | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[closure self] in lang:core::_::::map_or | MaD:30 | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::map_or | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[closure self] in lang:core::_::::map_or | MaD:31 | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::map_or_else | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[closure self] in lang:core::_::::map_or_else | MaD:33 | @@ -61,8 +69,16 @@ localStep | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::map_or | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::map_or | MaD:30 | | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::map_or_else | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::map_or_else | MaD:33 | | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::zip_with | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | MaD:60 | -| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | MaD:74 | -| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::nth | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::nth | MaD:75 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::collect | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::::collect | MaD:73 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::for_each | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:core::_::::for_each | MaD:74 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::map | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:core::_::::map | MaD:75 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::next | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::next | MaD:76 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::nth | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | MaD:77 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | MaD:79 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | MaD:80 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::map | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:core::_::crate::iter::traits::iterator::Iterator::map | MaD:81 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::next | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::next | MaD:82 | +| file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::nth | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::nth | MaD:83 | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::clone | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::clone | MaD:2 | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::and_then | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:core::_::::and_then | MaD:7 | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::cloned | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::cloned | MaD:10 | @@ -749,11 +765,23 @@ models | 70 | Summary: lang:core; ::unwrap_or_else; Argument[0].ReturnValue; ReturnValue; value | | 71 | Summary: lang:core; ::unwrap_or_else; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | | 72 | Summary: lang:core; ::unwrap_unchecked; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | -| 73 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | -| 74 | Summary: lang:core; crate::iter::traits::iterator::Iterator::collect; Argument[self].Element; ReturnValue.Element; value | -| 75 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value | +| 73 | Summary: lang:core; ::collect; Argument[self].Element; ReturnValue.Element; value | +| 74 | Summary: lang:core; ::for_each; Argument[self].Element; Argument[0].Parameter[0]; value | +| 75 | Summary: lang:core; ::map; Argument[self].Element; Argument[0].Parameter[0]; value | +| 76 | Summary: lang:core; ::next; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value | +| 77 | Summary: lang:core; ::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value | +| 78 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value | +| 79 | Summary: lang:core; crate::iter::traits::iterator::Iterator::collect; Argument[self].Element; ReturnValue.Element; value | +| 80 | Summary: lang:core; crate::iter::traits::iterator::Iterator::for_each; Argument[self].Element; Argument[0].Parameter[0]; value | +| 81 | Summary: lang:core; crate::iter::traits::iterator::Iterator::map; Argument[self].Element; Argument[0].Parameter[0]; value | +| 82 | Summary: lang:core; crate::iter::traits::iterator::Iterator::next; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value | +| 83 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value | storeStep | file://:0:0:0:0 | [summary] to write: Argument[0].Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::::zip_with | +| file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::::for_each | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::for_each | +| file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::::map | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::map | +| file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | +| file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::map | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::map | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::and_then | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::and_then | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_none_or | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::is_none_or | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_some_and | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::is_some_and | @@ -767,6 +795,7 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[self].Reference.Field[crate::option::Option::Some(0)] in lang:core::_::::get_or_insert | Some | file://:0:0:0:0 | [summary] to write: Argument[self].Reference in lang:core::_::::get_or_insert | | file://:0:0:0:0 | [summary] to write: Argument[self].Reference.Field[crate::option::Option::Some(0)] in lang:core::_::::insert | Some | file://:0:0:0:0 | [summary] to write: Argument[self].Reference in lang:core::_::::insert | | file://:0:0:0:0 | [summary] to write: Argument[self].Reference.Field[crate::option::Option::Some(0)] in lang:core::_::::take_if | Some | file://:0:0:0:0 | [summary] to write: Argument[self].Reference in lang:core::_::::take_if | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::::collect | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::collect | | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::iter::traits::iterator::Iterator::collect | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::unzip | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::unzip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0].Field[crate::option::Option::Some(0)] in lang:core::_::::unzip | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::unzip | @@ -781,6 +810,9 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::map | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::map | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::zip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::zip_with | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::next | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::iter::traits::iterator::Iterator::next | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::iter::traits::iterator::Iterator::nth | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::zip | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[1] in lang:core::_::::zip | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip | @@ -936,7 +968,15 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:core::_::::unwrap_or_default | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::unwrap_or_default | | file://:0:0:0:0 | [summary param] self in lang:core::_::::unwrap_or_else | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] self in lang:core::_::::unwrap_unchecked | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::unwrap_unchecked | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::collect | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::collect | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::for_each | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::for_each | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::map | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::map | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::next | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::next | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::nth | | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::collect | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | +| file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | +| file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::map | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::map | +| file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::next | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::next | | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::nth | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::from | Some | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Field[crate::option::Option::Some(0)] in lang:core::_::::from | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::copied | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Reference in lang:core::_::::copied | diff --git a/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected index 6319b173aa43..0b92620437c2 100644 --- a/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected @@ -3,15 +3,24 @@ additionalTaintStep | file://:0:0:0:0 | [summary param] self in lang:alloc::_::<_ as crate::string::ToString>::to_string | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<_ as crate::string::ToString>::to_string | MaD:1 | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_bytes | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_bytes | MaD:2 | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_str | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_str | MaD:3 | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::collect | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::collect | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::for_each | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::for_each | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::map | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::map | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::next | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::next | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::nth | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::parse | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::parse | MaD:5 | | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::collect | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::map | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::map | | +| file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::next | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::next | | | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::nth | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::nth | | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:5 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:6 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:7 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:8 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | MaD:9 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:10 | -| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:11 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:6 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:7 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:8 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | MaD:9 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | MaD:10 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | MaD:11 | +| file://:0:0:0:0 | [summary param] self in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | MaD:12 | | main.rs:4:5:4:8 | 1000 | main.rs:4:5:4:12 | ... + ... | | | main.rs:4:12:4:12 | i | main.rs:4:5:4:12 | ... + ... | | | main.rs:8:20:8:20 | s | main.rs:8:14:8:20 | FormatArgsExpr | | @@ -33,10 +42,11 @@ models | 2 | Summary: lang:alloc; ::as_bytes; Argument[self]; ReturnValue; taint | | 3 | Summary: lang:alloc; ::as_str; Argument[self]; ReturnValue; taint | | 4 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint | -| 5 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | -| 6 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | -| 7 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | -| 8 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | -| 9 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::chunk; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]; taint | -| 10 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | -| 11 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 5 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 6 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 7 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 8 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 9 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::bytes; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 10 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::chunk; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]; taint | +| 11 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | +| 12 | Summary: repo:https://github.com/seanmonstar/reqwest:reqwest; ::text_with_charset; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint | diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected index f572b5b4afcc..97672c441163 100644 --- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected +++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 8 | | Macro calls - total | 9 | | Macro calls - unresolved | 1 | -| Taint edges - number of edges | 5 | +| Taint edges - number of edges | 10 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | From 12d5a3070359b0d03e7c756eb370e692a9c2844c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 18 Feb 2025 17:09:28 +0000 Subject: [PATCH 16/18] Rust: Add a test of mutable iterators as well. --- .../dataflow/local/DataFlowStep.expected | 54 +++++++++++-------- .../dataflow/local/inline-flow.expected | 40 +++++++------- .../test/library-tests/dataflow/local/main.rs | 10 ++++ 3 files changed, 63 insertions(+), 41 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 5c274ea97863..04627c06111d 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -673,25 +673,28 @@ localStep | main.rs:484:25:484:25 | ... | main.rs:484:25:484:25 | x | | | main.rs:484:25:484:25 | [SSA] x | main.rs:484:34:484:34 | x | | | main.rs:484:25:484:25 | x | main.rs:484:25:484:25 | [SSA] x | | -| main.rs:486:5:488:5 | for ... in ... { ... } | main.rs:464:16:489:1 | { ... } | | | main.rs:486:9:486:9 | [SSA] v | main.rs:487:14:487:14 | v | | | main.rs:486:9:486:9 | v | main.rs:486:9:486:9 | [SSA] v | | -| main.rs:492:9:492:9 | [SSA] a | main.rs:497:10:497:10 | a | | -| main.rs:492:9:492:9 | a | main.rs:492:9:492:9 | [SSA] a | | -| main.rs:492:13:492:22 | source(...) | main.rs:492:9:492:9 | a | | -| main.rs:493:9:493:9 | [SSA] b | main.rs:498:15:498:15 | b | | -| main.rs:493:9:493:9 | b | main.rs:493:9:493:9 | [SSA] b | | -| main.rs:493:13:493:22 | source(...) | main.rs:493:9:493:9 | b | | -| main.rs:494:9:494:9 | [SSA] c | main.rs:495:18:495:18 | c | | -| main.rs:494:9:494:9 | c | main.rs:494:9:494:9 | [SSA] c | | -| main.rs:494:13:494:22 | source(...) | main.rs:494:9:494:9 | c | | -| main.rs:495:9:495:13 | [SSA] c_ref | main.rs:499:14:499:18 | c_ref | | -| main.rs:495:9:495:13 | c_ref | main.rs:495:9:495:13 | [SSA] c_ref | | -| main.rs:495:17:495:18 | &c | main.rs:495:9:495:13 | c_ref | | -| main.rs:499:14:499:18 | [post] c_ref | main.rs:500:11:500:15 | c_ref | | -| main.rs:499:14:499:18 | c_ref | main.rs:500:11:500:15 | c_ref | | -| main.rs:526:13:526:33 | result_questionmark(...) | main.rs:526:9:526:9 | _ | | -| main.rs:538:36:538:41 | ...::new(...) | main.rs:538:36:538:41 | MacroExpr | | +| main.rs:490:22:490:42 | [...] | main.rs:490:9:490:18 | mut vs_mut | | +| main.rs:496:5:498:5 | for ... in ... { ... } | main.rs:464:16:499:1 | { ... } | | +| main.rs:496:14:496:14 | [SSA] v | main.rs:497:14:497:14 | v | | +| main.rs:496:14:496:14 | v | main.rs:496:14:496:14 | [SSA] v | | +| main.rs:502:9:502:9 | [SSA] a | main.rs:507:10:507:10 | a | | +| main.rs:502:9:502:9 | a | main.rs:502:9:502:9 | [SSA] a | | +| main.rs:502:13:502:22 | source(...) | main.rs:502:9:502:9 | a | | +| main.rs:503:9:503:9 | [SSA] b | main.rs:508:15:508:15 | b | | +| main.rs:503:9:503:9 | b | main.rs:503:9:503:9 | [SSA] b | | +| main.rs:503:13:503:22 | source(...) | main.rs:503:9:503:9 | b | | +| main.rs:504:9:504:9 | [SSA] c | main.rs:505:18:505:18 | c | | +| main.rs:504:9:504:9 | c | main.rs:504:9:504:9 | [SSA] c | | +| main.rs:504:13:504:22 | source(...) | main.rs:504:9:504:9 | c | | +| main.rs:505:9:505:13 | [SSA] c_ref | main.rs:509:14:509:18 | c_ref | | +| main.rs:505:9:505:13 | c_ref | main.rs:505:9:505:13 | [SSA] c_ref | | +| main.rs:505:17:505:18 | &c | main.rs:505:9:505:13 | c_ref | | +| main.rs:509:14:509:18 | [post] c_ref | main.rs:510:11:510:15 | c_ref | | +| main.rs:509:14:509:18 | c_ref | main.rs:510:11:510:15 | c_ref | | +| main.rs:536:13:536:33 | result_questionmark(...) | main.rs:536:9:536:9 | _ | | +| main.rs:548:36:548:41 | ...::new(...) | main.rs:548:36:548:41 | MacroExpr | | models | 1 | Sink: lang:std; crate::io::stdio::_print; log-injection; Argument[0] | | 2 | Summary: lang:core; ::clone; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue.Field[crate::option::Option::Some(0)]; value | @@ -911,9 +914,13 @@ storeStep | main.rs:465:27:465:27 | 2 | element | main.rs:465:14:465:34 | [...] | | main.rs:465:30:465:30 | 3 | element | main.rs:465:14:465:34 | [...] | | main.rs:465:33:465:33 | 4 | element | main.rs:465:14:465:34 | [...] | -| main.rs:495:18:495:18 | c | &ref | main.rs:495:17:495:18 | &c | -| main.rs:498:15:498:15 | b | &ref | main.rs:498:14:498:15 | &b | -| main.rs:507:27:507:27 | 0 | Some | main.rs:507:22:507:28 | Some(...) | +| main.rs:490:23:490:32 | source(...) | element | main.rs:490:22:490:42 | [...] | +| main.rs:490:35:490:35 | 2 | element | main.rs:490:22:490:42 | [...] | +| main.rs:490:38:490:38 | 3 | element | main.rs:490:22:490:42 | [...] | +| main.rs:490:41:490:41 | 4 | element | main.rs:490:22:490:42 | [...] | +| main.rs:505:18:505:18 | c | &ref | main.rs:505:17:505:18 | &c | +| main.rs:508:15:508:15 | b | &ref | main.rs:508:14:508:15 | &b | +| main.rs:517:27:517:27 | 0 | Some | main.rs:517:22:517:28 | Some(...) | readStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::from | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::from | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::and_then | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::and_then | @@ -1085,4 +1092,9 @@ readStep | main.rs:483:29:483:29 | x | &ref | main.rs:483:28:483:29 | * ... | | main.rs:484:34:484:34 | x | &ref | main.rs:484:33:484:34 | * ... | | main.rs:486:14:486:27 | vs.into_iter(...) | element | main.rs:486:9:486:9 | v | -| main.rs:500:11:500:15 | c_ref | &ref | main.rs:500:10:500:15 | * ... | +| main.rs:492:10:492:15 | vs_mut | element | main.rs:492:10:492:18 | vs_mut[0] | +| main.rs:493:11:493:39 | ... .unwrap(...) | &ref | main.rs:493:10:493:39 | * ... | +| main.rs:494:11:494:39 | ... .unwrap(...) | &ref | main.rs:494:10:494:39 | * ... | +| main.rs:496:9:496:14 | &mut ... | &ref | main.rs:496:14:496:14 | v | +| main.rs:496:19:496:35 | vs_mut.iter_mut(...) | element | main.rs:496:9:496:14 | &mut ... | +| main.rs:510:11:510:15 | c_ref | &ref | main.rs:510:10:510:15 | * ... | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index ed25680e4fac..0c9dad76710b 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -196,14 +196,14 @@ edges | main.rs:467:10:467:11 | vs [element] | main.rs:467:10:467:14 | vs[0] | provenance | | | main.rs:471:9:471:9 | v | main.rs:472:14:472:14 | v | provenance | | | main.rs:471:14:471:15 | vs [element] | main.rs:471:9:471:9 | v | provenance | | -| main.rs:492:9:492:9 | a | main.rs:497:10:497:10 | a | provenance | | -| main.rs:492:13:492:22 | source(...) | main.rs:492:9:492:9 | a | provenance | | -| main.rs:494:9:494:9 | c | main.rs:495:18:495:18 | c | provenance | | -| main.rs:494:13:494:22 | source(...) | main.rs:494:9:494:9 | c | provenance | | -| main.rs:495:9:495:13 | c_ref [&ref] | main.rs:500:11:500:15 | c_ref [&ref] | provenance | | -| main.rs:495:17:495:18 | &c [&ref] | main.rs:495:9:495:13 | c_ref [&ref] | provenance | | -| main.rs:495:18:495:18 | c | main.rs:495:17:495:18 | &c [&ref] | provenance | | -| main.rs:500:11:500:15 | c_ref [&ref] | main.rs:500:10:500:15 | * ... | provenance | | +| main.rs:502:9:502:9 | a | main.rs:507:10:507:10 | a | provenance | | +| main.rs:502:13:502:22 | source(...) | main.rs:502:9:502:9 | a | provenance | | +| main.rs:504:9:504:9 | c | main.rs:505:18:505:18 | c | provenance | | +| main.rs:504:13:504:22 | source(...) | main.rs:504:9:504:9 | c | provenance | | +| main.rs:505:9:505:13 | c_ref [&ref] | main.rs:510:11:510:15 | c_ref [&ref] | provenance | | +| main.rs:505:17:505:18 | &c [&ref] | main.rs:505:9:505:13 | c_ref [&ref] | provenance | | +| main.rs:505:18:505:18 | c | main.rs:505:17:505:18 | &c [&ref] | provenance | | +| main.rs:510:11:510:15 | c_ref [&ref] | main.rs:510:10:510:15 | * ... | provenance | | nodes | main.rs:18:10:18:18 | source(...) | semmle.label | source(...) | | main.rs:22:9:22:9 | s | semmle.label | s | @@ -431,16 +431,16 @@ nodes | main.rs:471:9:471:9 | v | semmle.label | v | | main.rs:471:14:471:15 | vs [element] | semmle.label | vs [element] | | main.rs:472:14:472:14 | v | semmle.label | v | -| main.rs:492:9:492:9 | a | semmle.label | a | -| main.rs:492:13:492:22 | source(...) | semmle.label | source(...) | -| main.rs:494:9:494:9 | c | semmle.label | c | -| main.rs:494:13:494:22 | source(...) | semmle.label | source(...) | -| main.rs:495:9:495:13 | c_ref [&ref] | semmle.label | c_ref [&ref] | -| main.rs:495:17:495:18 | &c [&ref] | semmle.label | &c [&ref] | -| main.rs:495:18:495:18 | c | semmle.label | c | -| main.rs:497:10:497:10 | a | semmle.label | a | -| main.rs:500:10:500:15 | * ... | semmle.label | * ... | -| main.rs:500:11:500:15 | c_ref [&ref] | semmle.label | c_ref [&ref] | +| main.rs:502:9:502:9 | a | semmle.label | a | +| main.rs:502:13:502:22 | source(...) | semmle.label | source(...) | +| main.rs:504:9:504:9 | c | semmle.label | c | +| main.rs:504:13:504:22 | source(...) | semmle.label | source(...) | +| main.rs:505:9:505:13 | c_ref [&ref] | semmle.label | c_ref [&ref] | +| main.rs:505:17:505:18 | &c [&ref] | semmle.label | &c [&ref] | +| main.rs:505:18:505:18 | c | semmle.label | c | +| main.rs:507:10:507:10 | a | semmle.label | a | +| main.rs:510:10:510:15 | * ... | semmle.label | * ... | +| main.rs:510:11:510:15 | c_ref [&ref] | semmle.label | c_ref [&ref] | subpaths testFailures #select @@ -489,5 +489,5 @@ testFailures | main.rs:458:10:458:10 | a | main.rs:453:13:453:22 | source(...) | main.rs:458:10:458:10 | a | $@ | main.rs:453:13:453:22 | source(...) | source(...) | | main.rs:467:10:467:14 | vs[0] | main.rs:465:15:465:24 | source(...) | main.rs:467:10:467:14 | vs[0] | $@ | main.rs:465:15:465:24 | source(...) | source(...) | | main.rs:472:14:472:14 | v | main.rs:465:15:465:24 | source(...) | main.rs:472:14:472:14 | v | $@ | main.rs:465:15:465:24 | source(...) | source(...) | -| main.rs:497:10:497:10 | a | main.rs:492:13:492:22 | source(...) | main.rs:497:10:497:10 | a | $@ | main.rs:492:13:492:22 | source(...) | source(...) | -| main.rs:500:10:500:15 | * ... | main.rs:494:13:494:22 | source(...) | main.rs:500:10:500:15 | * ... | $@ | main.rs:494:13:494:22 | source(...) | source(...) | +| main.rs:507:10:507:10 | a | main.rs:502:13:502:22 | source(...) | main.rs:507:10:507:10 | a | $@ | main.rs:502:13:502:22 | source(...) | source(...) | +| main.rs:510:10:510:15 | * ... | main.rs:504:13:504:22 | source(...) | main.rs:510:10:510:15 | * ... | $@ | main.rs:504:13:504:22 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index 3cd7158a4ae0..33872fa8e720 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -486,6 +486,16 @@ fn iterators() { for v in vs.into_iter() { sink(v); // $ MISSING: hasValueFlow=91 } + + let mut vs_mut = [source(92), 2, 3, 4]; + + sink(vs_mut[0]); // $ MISSING: hasValueFlow=92 + sink(*vs_mut.iter().next().unwrap()); // $ MISSING: hasValueFlow=92 + sink(*vs_mut.iter().nth(0).unwrap()); // $ MISSING: hasValueFlow=92 + + for &mut v in vs_mut.iter_mut() { + sink(v); // $ MISSING: hasValueFlow=92 + } } fn references() { From 1a6c6a454dd5a3ab88ff8401325f89b25422a82e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 18 Feb 2025 17:50:26 +0000 Subject: [PATCH 17/18] Rust: Effect on integration tests. --- rust/ql/integration-tests/hello-project/summary.expected | 2 +- .../ql/integration-tests/hello-workspace/summary.cargo.expected | 2 +- .../hello-workspace/summary.rust-project.expected | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/integration-tests/hello-project/summary.expected b/rust/ql/integration-tests/hello-project/summary.expected index 0eeeeffbffdb..f8e1a1e4c7cb 100644 --- a/rust/ql/integration-tests/hello-project/summary.expected +++ b/rust/ql/integration-tests/hello-project/summary.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 5 | +| Taint edges - number of edges | 10 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | diff --git a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected index e5671bbd2d60..efea91e69a1d 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 5 | +| Taint edges - number of edges | 10 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | diff --git a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected index e5671bbd2d60..efea91e69a1d 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected @@ -14,7 +14,7 @@ | Macro calls - resolved | 2 | | Macro calls - total | 2 | | Macro calls - unresolved | 0 | -| Taint edges - number of edges | 5 | +| Taint edges - number of edges | 10 | | Taint reach - nodes tainted | 0 | | Taint reach - per million nodes | 0 | | Taint sinks - cryptographic operations | 0 | From 6cb8f65076d9e8244c081a047fc25ee7edd399d2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 24 Feb 2025 10:58:19 +0000 Subject: [PATCH 18/18] Rust: Fix up .expected after merge. --- .../dataflow/local/DataFlowStep.expected | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 5d27ff9d3711..432aade94030 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -737,7 +737,103 @@ localStep | main.rs:444:9:444:9 | s | main.rs:444:9:444:9 | s | | | main.rs:444:13:444:27 | MacroExpr | main.rs:444:9:444:9 | s | | | main.rs:444:25:444:26 | source(...) | main.rs:444:13:444:27 | MacroExpr | | -? +| main.rs:448:16:448:16 | [SSA] s | main.rs:449:20:449:20 | s | | +| main.rs:448:16:448:16 | s | main.rs:448:16:448:16 | [SSA] s | | +| main.rs:448:16:448:16 | s | main.rs:448:16:448:16 | s | | +| main.rs:448:16:448:24 | ...: String | main.rs:448:16:448:16 | s | | +| main.rs:449:14:449:20 | FormatArgsExpr | main.rs:449:14:449:20 | MacroExpr | | +| main.rs:449:14:449:20 | MacroExpr | main.rs:449:5:449:21 | ...::_print | MaD:1 | +| main.rs:453:9:453:9 | [SSA] a | main.rs:454:13:454:13 | a | | +| main.rs:453:9:453:9 | a | main.rs:453:9:453:9 | [SSA] a | | +| main.rs:453:9:453:9 | a | main.rs:453:9:453:9 | a | | +| main.rs:453:13:453:22 | source(...) | main.rs:453:9:453:9 | a | | +| main.rs:454:9:454:9 | [SSA] b | main.rs:455:13:455:13 | b | | +| main.rs:454:9:454:9 | b | main.rs:454:9:454:9 | [SSA] b | | +| main.rs:454:9:454:9 | b | main.rs:454:9:454:9 | b | | +| main.rs:454:13:454:13 | [post] a | main.rs:458:10:458:10 | a | | +| main.rs:454:13:454:13 | a | main.rs:458:10:458:10 | a | | +| main.rs:454:13:454:25 | a.to_string(...) | main.rs:454:9:454:9 | b | | +| main.rs:455:9:455:9 | [SSA] c | main.rs:460:10:460:10 | c | | +| main.rs:455:9:455:9 | c | main.rs:455:9:455:9 | [SSA] c | | +| main.rs:455:9:455:9 | c | main.rs:455:9:455:9 | c | | +| main.rs:455:13:455:13 | [post] b | main.rs:456:19:456:19 | b | | +| main.rs:455:13:455:13 | b | main.rs:456:19:456:19 | b | | +| main.rs:455:13:455:37 | ... .unwrap(...) | main.rs:455:9:455:9 | c | | +| main.rs:456:9:456:9 | [SSA] d | main.rs:461:10:461:10 | d | | +| main.rs:456:9:456:9 | d | main.rs:456:9:456:9 | [SSA] d | | +| main.rs:456:9:456:9 | d | main.rs:456:9:456:9 | d | | +| main.rs:456:19:456:19 | [post] b | main.rs:459:17:459:17 | b | | +| main.rs:456:19:456:19 | b | main.rs:459:17:459:17 | b | | +| main.rs:456:19:456:36 | ... .unwrap(...) | main.rs:456:9:456:9 | d | | +| main.rs:465:9:465:10 | [SSA] vs | main.rs:467:10:467:11 | vs | | +| main.rs:465:9:465:10 | vs | main.rs:465:9:465:10 | [SSA] vs | | +| main.rs:465:9:465:10 | vs | main.rs:465:9:465:10 | vs | | +| main.rs:465:14:465:34 | [...] | main.rs:465:9:465:10 | vs | | +| main.rs:467:10:467:11 | [post] vs | main.rs:468:11:468:12 | vs | | +| main.rs:467:10:467:11 | vs | main.rs:468:11:468:12 | vs | | +| main.rs:468:11:468:12 | [post] vs | main.rs:469:11:469:12 | vs | | +| main.rs:468:11:468:12 | vs | main.rs:469:11:469:12 | vs | | +| main.rs:469:11:469:12 | [post] vs | main.rs:471:14:471:15 | vs | | +| main.rs:469:11:469:12 | vs | main.rs:471:14:471:15 | vs | | +| main.rs:471:9:471:9 | [SSA] v | main.rs:472:14:472:14 | v | | +| main.rs:471:9:471:9 | v | main.rs:471:9:471:9 | [SSA] v | | +| main.rs:471:9:471:9 | v | main.rs:471:9:471:9 | v | | +| main.rs:471:14:471:15 | vs | main.rs:474:15:474:16 | vs | | +| main.rs:474:10:474:10 | [SSA] v | main.rs:475:14:475:14 | v | | +| main.rs:474:10:474:10 | v | main.rs:474:10:474:10 | [SSA] v | | +| main.rs:474:10:474:10 | v | main.rs:474:10:474:10 | v | | +| main.rs:474:15:474:16 | [post] vs | main.rs:478:27:478:28 | vs | | +| main.rs:474:15:474:16 | vs | main.rs:478:27:478:28 | vs | | +| main.rs:478:9:478:11 | [SSA] vs2 | main.rs:479:15:479:17 | vs2 | | +| main.rs:478:9:478:11 | vs2 | main.rs:478:9:478:11 | [SSA] vs2 | | +| main.rs:478:9:478:11 | vs2 | main.rs:478:9:478:11 | vs2 | | +| main.rs:478:27:478:28 | [post] vs | main.rs:483:5:483:6 | vs | | +| main.rs:478:27:478:28 | vs | main.rs:483:5:483:6 | vs | | +| main.rs:478:27:478:45 | ... .collect(...) | main.rs:478:9:478:11 | vs2 | | +| main.rs:479:10:479:10 | [SSA] v | main.rs:480:14:480:14 | v | | +| main.rs:479:10:479:10 | v | main.rs:479:10:479:10 | [SSA] v | | +| main.rs:479:10:479:10 | v | main.rs:479:10:479:10 | v | | +| main.rs:483:5:483:6 | [post] vs | main.rs:484:5:484:6 | vs | | +| main.rs:483:5:483:6 | vs | main.rs:484:5:484:6 | vs | | +| main.rs:483:20:483:20 | ... | main.rs:483:20:483:20 | x | | +| main.rs:483:20:483:20 | [SSA] x | main.rs:483:29:483:29 | x | | +| main.rs:483:20:483:20 | x | main.rs:483:20:483:20 | [SSA] x | | +| main.rs:483:20:483:20 | x | main.rs:483:20:483:20 | x | | +| main.rs:484:5:484:6 | [post] vs | main.rs:486:14:486:15 | vs | | +| main.rs:484:5:484:6 | vs | main.rs:486:14:486:15 | vs | | +| main.rs:484:25:484:25 | ... | main.rs:484:25:484:25 | x | | +| main.rs:484:25:484:25 | [SSA] x | main.rs:484:34:484:34 | x | | +| main.rs:484:25:484:25 | x | main.rs:484:25:484:25 | [SSA] x | | +| main.rs:484:25:484:25 | x | main.rs:484:25:484:25 | x | | +| main.rs:486:9:486:9 | [SSA] v | main.rs:487:14:487:14 | v | | +| main.rs:486:9:486:9 | v | main.rs:486:9:486:9 | [SSA] v | | +| main.rs:486:9:486:9 | v | main.rs:486:9:486:9 | v | | +| main.rs:490:9:490:18 | mut vs_mut | main.rs:490:13:490:18 | vs_mut | | +| main.rs:490:22:490:42 | [...] | main.rs:490:9:490:18 | mut vs_mut | | +| main.rs:496:5:498:5 | for ... in ... { ... } | main.rs:464:16:499:1 | { ... } | | +| main.rs:496:14:496:14 | [SSA] v | main.rs:497:14:497:14 | v | | +| main.rs:496:14:496:14 | v | main.rs:496:14:496:14 | [SSA] v | | +| main.rs:496:14:496:14 | v | main.rs:496:14:496:14 | v | | +| main.rs:502:9:502:9 | [SSA] a | main.rs:507:10:507:10 | a | | +| main.rs:502:9:502:9 | a | main.rs:502:9:502:9 | [SSA] a | | +| main.rs:502:9:502:9 | a | main.rs:502:9:502:9 | a | | +| main.rs:502:13:502:22 | source(...) | main.rs:502:9:502:9 | a | | +| main.rs:503:9:503:9 | [SSA] b | main.rs:508:15:508:15 | b | | +| main.rs:503:9:503:9 | b | main.rs:503:9:503:9 | [SSA] b | | +| main.rs:503:9:503:9 | b | main.rs:503:9:503:9 | b | | +| main.rs:503:13:503:22 | source(...) | main.rs:503:9:503:9 | b | | +| main.rs:504:9:504:9 | [SSA] c | main.rs:505:18:505:18 | c | | +| main.rs:504:9:504:9 | c | main.rs:504:9:504:9 | [SSA] c | | +| main.rs:504:9:504:9 | c | main.rs:504:9:504:9 | c | | +| main.rs:504:13:504:22 | source(...) | main.rs:504:9:504:9 | c | | +| main.rs:505:9:505:13 | [SSA] c_ref | main.rs:509:14:509:18 | c_ref | | +| main.rs:505:9:505:13 | c_ref | main.rs:505:9:505:13 | [SSA] c_ref | | +| main.rs:505:9:505:13 | c_ref | main.rs:505:9:505:13 | c_ref | | +| main.rs:505:17:505:18 | &c | main.rs:505:9:505:13 | c_ref | | +| main.rs:509:14:509:18 | [post] c_ref | main.rs:510:11:510:15 | c_ref | | +| main.rs:509:14:509:18 | c_ref | main.rs:510:11:510:15 | c_ref | | +| main.rs:536:13:536:33 | result_questionmark(...) | main.rs:536:9:536:9 | _ | | +| main.rs:548:36:548:41 | ...::new(...) | main.rs:548:36:548:41 | MacroExpr | | models | 1 | Sink: lang:std; crate::io::stdio::_print; log-injection; Argument[0] | | 2 | Summary: lang:core; ::clone; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue.Field[crate::option::Option::Some(0)]; value |