From e082ae85db41e0f8172cb381957c0c5c1eba2034 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:51:28 +0100 Subject: [PATCH 1/5] Rust: Expand the test cases. --- .../format-macros-legacy/FormatArgs.expected | 14 ++++--- .../LogInjection.expected | 38 +++++++++---------- .../inline-taint-flow.expected | 14 +++++++ .../format-macros-legacy/main.rs | 37 ++++++++++++++---- 4 files changed, 70 insertions(+), 33 deletions(-) diff --git a/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected b/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected index ed2b1199c6aa..0935662bb71c 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected @@ -2,9 +2,11 @@ | main.rs:16:10:16:23 | FormatArgsExpr | 0 | | main.rs:19:13:19:36 | FormatArgsExpr | 1 | | main.rs:33:25:33:33 | FormatArgsExpr | 1 | -| main.rs:38:13:38:32 | FormatArgsExpr | 1 | -| main.rs:39:13:39:32 | FormatArgsExpr | 0 | -| main.rs:49:5:49:27 | FormatArgsExpr | 1 | -| main.rs:50:5:50:26 | FormatArgsExpr | 0 | -| main.rs:51:5:51:25 | FormatArgsExpr | 1 | -| main.rs:52:5:52:24 | FormatArgsExpr | 0 | +| main.rs:44:40:44:46 | FormatArgsExpr | 0 | +| main.rs:49:52:49:58 | FormatArgsExpr | 0 | +| main.rs:55:13:55:33 | FormatArgsExpr | 1 | +| main.rs:60:13:60:33 | FormatArgsExpr | 0 | +| main.rs:70:5:70:27 | FormatArgsExpr | 1 | +| main.rs:71:5:71:26 | FormatArgsExpr | 0 | +| main.rs:72:5:72:25 | FormatArgsExpr | 1 | +| main.rs:73:5:73:24 | FormatArgsExpr | 0 | diff --git a/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected b/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected index 6ab010521f33..a08e58f094fc 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected @@ -1,28 +1,28 @@ #select -| main.rs:49:5:49:27 | FormatArgsExpr | main.rs:47:19:47:45 | ...::var(...) | main.rs:49:5:49:27 | FormatArgsExpr | Log entry depends on a $@. | main.rs:47:19:47:45 | ...::var(...) | user-provided value | -| main.rs:50:5:50:26 | FormatArgsExpr | main.rs:47:19:47:45 | ...::var(...) | main.rs:50:5:50:26 | FormatArgsExpr | Log entry depends on a $@. | main.rs:47:19:47:45 | ...::var(...) | user-provided value | -| main.rs:51:5:51:25 | FormatArgsExpr | main.rs:47:19:47:45 | ...::var(...) | main.rs:51:5:51:25 | FormatArgsExpr | Log entry depends on a $@. | main.rs:47:19:47:45 | ...::var(...) | user-provided value | -| main.rs:52:5:52:24 | FormatArgsExpr | main.rs:47:19:47:45 | ...::var(...) | main.rs:52:5:52:24 | FormatArgsExpr | Log entry depends on a $@. | main.rs:47:19:47:45 | ...::var(...) | user-provided value | +| main.rs:70:5:70:27 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:70:5:70:27 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | +| main.rs:71:5:71:26 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:71:5:71:26 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | +| main.rs:72:5:72:25 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:72:5:72:25 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | +| main.rs:73:5:73:24 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:73:5:73:24 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | edges -| main.rs:47:9:47:15 | tainted | main.rs:49:5:49:27 | FormatArgsExpr | provenance | Sink:MaD:2 | -| main.rs:47:9:47:15 | tainted | main.rs:50:5:50:26 | FormatArgsExpr | provenance | Sink:MaD:1 | -| main.rs:47:9:47:15 | tainted | main.rs:51:5:51:25 | FormatArgsExpr | provenance | Sink:MaD:2 | -| main.rs:47:9:47:15 | tainted | main.rs:52:5:52:24 | FormatArgsExpr | provenance | Sink:MaD:1 | -| main.rs:47:19:47:45 | ...::var(...) | main.rs:47:19:47:45 | ...::var(...) [Ok] | provenance | Src:MaD:3 | -| main.rs:47:19:47:45 | ...::var(...) [Ok] | main.rs:47:19:47:65 | ... .unwrap_or_default() | provenance | MaD:4 | -| main.rs:47:19:47:65 | ... .unwrap_or_default() | main.rs:47:9:47:15 | tainted | provenance | | +| main.rs:68:9:68:15 | tainted | main.rs:70:5:70:27 | FormatArgsExpr | provenance | Sink:MaD:2 | +| main.rs:68:9:68:15 | tainted | main.rs:71:5:71:26 | FormatArgsExpr | provenance | Sink:MaD:1 | +| main.rs:68:9:68:15 | tainted | main.rs:72:5:72:25 | FormatArgsExpr | provenance | Sink:MaD:2 | +| main.rs:68:9:68:15 | tainted | main.rs:73:5:73:24 | FormatArgsExpr | provenance | Sink:MaD:1 | +| main.rs:68:19:68:45 | ...::var(...) | main.rs:68:19:68:45 | ...::var(...) [Ok] | provenance | Src:MaD:3 | +| main.rs:68:19:68:45 | ...::var(...) [Ok] | main.rs:68:19:68:65 | ... .unwrap_or_default() | provenance | MaD:4 | +| main.rs:68:19:68:65 | ... .unwrap_or_default() | main.rs:68:9:68:15 | tainted | provenance | | models | 1 | Sink: std::io::stdio::_eprint; Argument[0]; log-injection | | 2 | Sink: std::io::stdio::_print; Argument[0]; log-injection | | 3 | Source: std::env::var; ReturnValue.Field[core::result::Result::Ok(0)]; environment | | 4 | Summary: ::unwrap_or_default; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | nodes -| main.rs:47:9:47:15 | tainted | semmle.label | tainted | -| main.rs:47:19:47:45 | ...::var(...) | semmle.label | ...::var(...) | -| main.rs:47:19:47:45 | ...::var(...) [Ok] | semmle.label | ...::var(...) [Ok] | -| main.rs:47:19:47:65 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() | -| main.rs:49:5:49:27 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:50:5:50:26 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:51:5:51:25 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:52:5:52:24 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:68:9:68:15 | tainted | semmle.label | tainted | +| main.rs:68:19:68:45 | ...::var(...) | semmle.label | ...::var(...) | +| main.rs:68:19:68:45 | ...::var(...) [Ok] | semmle.label | ...::var(...) [Ok] | +| main.rs:68:19:68:65 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() | +| main.rs:70:5:70:27 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:71:5:71:26 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:72:5:72:25 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:73:5:73:24 | FormatArgsExpr | semmle.label | FormatArgsExpr | subpaths diff --git a/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected b/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected index 59e89e2641a0..b2503dd3a2e5 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected @@ -14,6 +14,12 @@ edges | main.rs:19:9:19:9 | s | main.rs:20:10:20:10 | s | provenance | | | main.rs:19:13:19:36 | ...::format(...) | main.rs:19:9:19:9 | s | provenance | | | main.rs:19:13:19:36 | FormatArgsExpr | main.rs:19:13:19:36 | ...::format(...) | provenance | MaD:1 | +| main.rs:32:9:32:9 | a | main.rs:33:9:33:9 | b | provenance | | +| main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | a | provenance | | +| main.rs:33:9:33:9 | b | main.rs:34:30:34:30 | b | provenance | | +| main.rs:34:9:34:9 | c | main.rs:35:10:35:10 | c | provenance | | +| main.rs:34:13:34:31 | ...::format(...) | main.rs:34:9:34:9 | c | provenance | | +| main.rs:34:30:34:30 | b | main.rs:34:13:34:31 | ...::format(...) | provenance | MaD:1 | nodes | main.rs:12:9:12:9 | a | semmle.label | a | | main.rs:12:13:12:21 | source(...) | semmle.label | source(...) | @@ -31,9 +37,17 @@ nodes | main.rs:19:13:19:36 | ...::format(...) | semmle.label | ...::format(...) | | main.rs:19:13:19:36 | FormatArgsExpr | semmle.label | FormatArgsExpr | | main.rs:20:10:20:10 | s | semmle.label | s | +| main.rs:32:9:32:9 | a | semmle.label | a | +| main.rs:32:13:32:21 | source(...) | semmle.label | source(...) | +| main.rs:33:9:33:9 | b | semmle.label | b | +| main.rs:34:9:34:9 | c | semmle.label | c | +| main.rs:34:13:34:31 | ...::format(...) | semmle.label | ...::format(...) | +| main.rs:34:30:34:30 | b | semmle.label | b | +| main.rs:35:10:35:10 | c | semmle.label | c | subpaths testFailures #select | main.rs:13:10:13:25 | MacroExpr | main.rs:12:13:12:21 | source(...) | main.rs:13:10:13:25 | MacroExpr | $@ | main.rs:12:13:12:21 | source(...) | source(...) | | main.rs:16:10:16:23 | MacroExpr | main.rs:15:13:15:21 | source(...) | main.rs:16:10:16:23 | MacroExpr | $@ | main.rs:15:13:15:21 | source(...) | source(...) | | main.rs:20:10:20:10 | s | main.rs:18:13:18:21 | source(...) | main.rs:20:10:20:10 | s | $@ | main.rs:18:13:18:21 | source(...) | source(...) | +| main.rs:35:10:35:10 | c | main.rs:32:13:32:21 | source(...) | main.rs:35:10:35:10 | c | $@ | main.rs:32:13:32:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/format-macros-legacy/main.rs b/rust/ql/test/library-tests/format-macros-legacy/main.rs index df0d740a1443..2fe9acba1213 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/main.rs +++ b/rust/ql/test/library-tests/format-macros-legacy/main.rs @@ -6,7 +6,7 @@ fn source(i: i64) -> String { i.to_string() } -fn sink(s: String) {} +fn sink(_s: String) {} pub fn format_flow() { let a = source(1); @@ -29,15 +29,36 @@ pub fn exercises_reconstruction() { // behavior on >=1.94, where the `Write::write_fmt` content-to-self taint // model is also missing. So it is a pre-existing model gap, not a // regression from the reconstruction. - let d = source(4); - let _ = format_args!("{}", d); + let a = source(4); + let b = format_args!("{}", a); + let c = std::fmt::format(b); + sink(c); // $ hasTaintFlow=4 + + let mut buf1 = String::new(); + let d = source(5); + let _ = buf1.write_str(d.as_str()); + sink(buf1); // $ MISSING: hasTaintFlow=5 + + let mut buf2 = String::new(); + let e = source(6); + let _ = buf2.write_fmt(format_args!("{e}")); + sink(buf2); // $ MISSING: hasTaintFlow=6 + + let mut buf3 = String::new(); + let f = source(7); + let _ = std::fmt::write(&mut buf3, format_args!("{f}")); + sink(buf3); // $ MISSING: hasTaintFlow=7 use std::fmt::Write; - let mut buf = String::new(); - let e = source(5); - let _ = write!(buf, "{}", e); - let _ = writeln!(buf, "{e}"); - sink(buf); + let mut buf4 = String::new(); + let g = source(8); + let _ = write!(buf4, "{}", g); + sink(buf4); // $ MISSING: hasTaintFlow=8 + + let mut buf5 = String::new(); + let h = source(9); + let _ = writeln!(buf5, "{h}"); + sink(buf5); // $ MISSING: hasTaintFlow=9 } // The log-injection sinks (`println!`/`eprintln!`/`panic!`) are reconstructed From 0ce4b7bc39df02eea2e9d230f44b842d2a86e0b1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:39:57 +0100 Subject: [PATCH 2/5] Rust: Add models. --- .../rust/frameworks/stdlib/core.model.yml | 5 ++ .../inline-taint-flow.expected | 68 +++++++++++++++++-- .../format-macros-legacy/main.rs | 10 +-- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml index 895ebe98bd6b..4a0e85764ec7 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/core.model.yml @@ -129,6 +129,11 @@ extensions: - ["::parse", "Argument[self].Reference", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - ["::trim", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] - ["::to_string", "Argument[self].Reference", "ReturnValue", "taint", "manual"] + # Fmt + - ["<_ as core::fmt::Write>::write_fmt", "Argument[0]", "Argument[self].Reference", "taint", "manual"] + - ["<_ as core::fmt::Write>::write_str", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"] + - ["<_ as core::fmt::Write>::write_char", "Argument[0]", "Argument[self].Reference", "taint", "manual"] + - ["core::fmt::write", "Argument[1]", "Argument[0].Reference", "taint", "manual"] # Ord - ["<_ as core::cmp::Ord>::min", "Argument[self,0]", "ReturnValue", "value", "manual"] - ["<_ as core::cmp::Ord>::max", "Argument[self,0]", "ReturnValue", "value", "manual"] diff --git a/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected b/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected index b2503dd3a2e5..052888d641f7 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected @@ -1,25 +1,51 @@ models -| 1 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint | +| 1 | Summary: <_ as core::fmt::Write>::write_fmt; Argument[0]; Argument[self].Reference; taint | +| 2 | Summary: <_ as core::fmt::Write>::write_str; Argument[0].Reference; Argument[self].Reference; taint | +| 3 | Summary: ::as_str; Argument[self].Reference; ReturnValue.Reference; taint | +| 4 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint | +| 5 | Summary: core::fmt::write; Argument[1]; Argument[0].Reference; taint | edges | main.rs:12:9:12:9 | a | main.rs:13:10:13:25 | FormatArgsExpr | provenance | | | main.rs:12:13:12:21 | source(...) | main.rs:12:9:12:9 | a | provenance | | | main.rs:13:10:13:25 | ...::format(...) | main.rs:13:10:13:25 | MacroExpr | provenance | | -| main.rs:13:10:13:25 | FormatArgsExpr | main.rs:13:10:13:25 | ...::format(...) | provenance | MaD:1 | +| main.rs:13:10:13:25 | FormatArgsExpr | main.rs:13:10:13:25 | ...::format(...) | provenance | MaD:4 | | main.rs:15:9:15:9 | b | main.rs:16:10:16:23 | FormatArgsExpr | provenance | | | main.rs:15:13:15:21 | source(...) | main.rs:15:9:15:9 | b | provenance | | | main.rs:16:10:16:23 | ...::format(...) | main.rs:16:10:16:23 | MacroExpr | provenance | | -| main.rs:16:10:16:23 | FormatArgsExpr | main.rs:16:10:16:23 | ...::format(...) | provenance | MaD:1 | +| main.rs:16:10:16:23 | FormatArgsExpr | main.rs:16:10:16:23 | ...::format(...) | provenance | MaD:4 | | main.rs:18:9:18:9 | c | main.rs:19:13:19:36 | FormatArgsExpr | provenance | | | main.rs:18:13:18:21 | source(...) | main.rs:18:9:18:9 | c | provenance | | | main.rs:19:9:19:9 | s | main.rs:20:10:20:10 | s | provenance | | | main.rs:19:13:19:36 | ...::format(...) | main.rs:19:9:19:9 | s | provenance | | -| main.rs:19:13:19:36 | FormatArgsExpr | main.rs:19:13:19:36 | ...::format(...) | provenance | MaD:1 | +| main.rs:19:13:19:36 | FormatArgsExpr | main.rs:19:13:19:36 | ...::format(...) | provenance | MaD:4 | | main.rs:32:9:32:9 | a | main.rs:33:9:33:9 | b | provenance | | | main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | a | provenance | | | main.rs:33:9:33:9 | b | main.rs:34:30:34:30 | b | provenance | | | main.rs:34:9:34:9 | c | main.rs:35:10:35:10 | c | provenance | | | main.rs:34:13:34:31 | ...::format(...) | main.rs:34:9:34:9 | c | provenance | | -| main.rs:34:30:34:30 | b | main.rs:34:13:34:31 | ...::format(...) | provenance | MaD:1 | +| main.rs:34:30:34:30 | b | main.rs:34:13:34:31 | ...::format(...) | provenance | MaD:4 | +| main.rs:38:9:38:9 | d | main.rs:39:28:39:28 | d | provenance | | +| main.rs:38:13:38:21 | source(...) | main.rs:38:9:38:9 | d | provenance | | +| main.rs:39:13:39:16 | [post] buf1 | main.rs:40:10:40:13 | buf1 | provenance | | +| main.rs:39:28:39:28 | d | main.rs:39:28:39:37 | d.as_str() [&ref] | provenance | MaD:3 | +| main.rs:39:28:39:37 | d.as_str() [&ref] | main.rs:39:13:39:16 | [post] buf1 | provenance | MaD:2 | +| main.rs:43:9:43:9 | e | main.rs:44:28:44:46 | MacroExpr | provenance | | +| main.rs:43:13:43:21 | source(...) | main.rs:43:9:43:9 | e | provenance | | +| main.rs:44:13:44:16 | [post] buf2 | main.rs:45:10:45:13 | buf2 | provenance | | +| main.rs:44:28:44:46 | MacroExpr | main.rs:44:13:44:16 | [post] buf2 | provenance | MaD:1 | +| main.rs:48:9:48:9 | f | main.rs:49:40:49:58 | MacroExpr | provenance | | +| main.rs:48:13:48:21 | source(...) | main.rs:48:9:48:9 | f | provenance | | +| main.rs:49:29:49:37 | [post] &mut buf3 [&ref] | main.rs:49:34:49:37 | [post] buf3 | provenance | | +| main.rs:49:34:49:37 | [post] buf3 | main.rs:50:10:50:13 | buf3 | provenance | | +| main.rs:49:40:49:58 | MacroExpr | main.rs:49:29:49:37 | [post] &mut buf3 [&ref] | provenance | MaD:5 | +| main.rs:54:9:54:9 | g | main.rs:55:13:55:33 | FormatArgsExpr | provenance | | +| main.rs:54:13:54:21 | source(...) | main.rs:54:9:54:9 | g | provenance | | +| main.rs:55:13:55:33 | FormatArgsExpr | main.rs:55:20:55:23 | [post] buf4 | provenance | MaD:1 | +| main.rs:55:20:55:23 | [post] buf4 | main.rs:56:10:56:13 | buf4 | provenance | | +| main.rs:59:9:59:9 | h | main.rs:60:13:60:33 | FormatArgsExpr | provenance | | +| main.rs:59:13:59:21 | source(...) | main.rs:59:9:59:9 | h | provenance | | +| main.rs:60:13:60:33 | FormatArgsExpr | main.rs:60:22:60:25 | [post] buf5 | provenance | MaD:1 | +| main.rs:60:22:60:25 | [post] buf5 | main.rs:61:10:61:13 | buf5 | provenance | | nodes | main.rs:12:9:12:9 | a | semmle.label | a | | main.rs:12:13:12:21 | source(...) | semmle.label | source(...) | @@ -44,6 +70,33 @@ nodes | main.rs:34:13:34:31 | ...::format(...) | semmle.label | ...::format(...) | | main.rs:34:30:34:30 | b | semmle.label | b | | main.rs:35:10:35:10 | c | semmle.label | c | +| main.rs:38:9:38:9 | d | semmle.label | d | +| main.rs:38:13:38:21 | source(...) | semmle.label | source(...) | +| main.rs:39:13:39:16 | [post] buf1 | semmle.label | [post] buf1 | +| main.rs:39:28:39:28 | d | semmle.label | d | +| main.rs:39:28:39:37 | d.as_str() [&ref] | semmle.label | d.as_str() [&ref] | +| main.rs:40:10:40:13 | buf1 | semmle.label | buf1 | +| main.rs:43:9:43:9 | e | semmle.label | e | +| main.rs:43:13:43:21 | source(...) | semmle.label | source(...) | +| main.rs:44:13:44:16 | [post] buf2 | semmle.label | [post] buf2 | +| main.rs:44:28:44:46 | MacroExpr | semmle.label | MacroExpr | +| main.rs:45:10:45:13 | buf2 | semmle.label | buf2 | +| main.rs:48:9:48:9 | f | semmle.label | f | +| main.rs:48:13:48:21 | source(...) | semmle.label | source(...) | +| main.rs:49:29:49:37 | [post] &mut buf3 [&ref] | semmle.label | [post] &mut buf3 [&ref] | +| main.rs:49:34:49:37 | [post] buf3 | semmle.label | [post] buf3 | +| main.rs:49:40:49:58 | MacroExpr | semmle.label | MacroExpr | +| main.rs:50:10:50:13 | buf3 | semmle.label | buf3 | +| main.rs:54:9:54:9 | g | semmle.label | g | +| main.rs:54:13:54:21 | source(...) | semmle.label | source(...) | +| main.rs:55:13:55:33 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:55:20:55:23 | [post] buf4 | semmle.label | [post] buf4 | +| main.rs:56:10:56:13 | buf4 | semmle.label | buf4 | +| main.rs:59:9:59:9 | h | semmle.label | h | +| main.rs:59:13:59:21 | source(...) | semmle.label | source(...) | +| main.rs:60:13:60:33 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:60:22:60:25 | [post] buf5 | semmle.label | [post] buf5 | +| main.rs:61:10:61:13 | buf5 | semmle.label | buf5 | subpaths testFailures #select @@ -51,3 +104,8 @@ testFailures | main.rs:16:10:16:23 | MacroExpr | main.rs:15:13:15:21 | source(...) | main.rs:16:10:16:23 | MacroExpr | $@ | main.rs:15:13:15:21 | source(...) | source(...) | | main.rs:20:10:20:10 | s | main.rs:18:13:18:21 | source(...) | main.rs:20:10:20:10 | s | $@ | main.rs:18:13:18:21 | source(...) | source(...) | | main.rs:35:10:35:10 | c | main.rs:32:13:32:21 | source(...) | main.rs:35:10:35:10 | c | $@ | main.rs:32:13:32:21 | source(...) | source(...) | +| main.rs:40:10:40:13 | buf1 | main.rs:38:13:38:21 | source(...) | main.rs:40:10:40:13 | buf1 | $@ | main.rs:38:13:38:21 | source(...) | source(...) | +| main.rs:45:10:45:13 | buf2 | main.rs:43:13:43:21 | source(...) | main.rs:45:10:45:13 | buf2 | $@ | main.rs:43:13:43:21 | source(...) | source(...) | +| main.rs:50:10:50:13 | buf3 | main.rs:48:13:48:21 | source(...) | main.rs:50:10:50:13 | buf3 | $@ | main.rs:48:13:48:21 | source(...) | source(...) | +| main.rs:56:10:56:13 | buf4 | main.rs:54:13:54:21 | source(...) | main.rs:56:10:56:13 | buf4 | $@ | main.rs:54:13:54:21 | source(...) | source(...) | +| main.rs:61:10:61:13 | buf5 | main.rs:59:13:59:21 | source(...) | main.rs:61:10:61:13 | buf5 | $@ | main.rs:59:13:59:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/format-macros-legacy/main.rs b/rust/ql/test/library-tests/format-macros-legacy/main.rs index 2fe9acba1213..24b955c65356 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/main.rs +++ b/rust/ql/test/library-tests/format-macros-legacy/main.rs @@ -37,28 +37,28 @@ pub fn exercises_reconstruction() { let mut buf1 = String::new(); let d = source(5); let _ = buf1.write_str(d.as_str()); - sink(buf1); // $ MISSING: hasTaintFlow=5 + sink(buf1); // $ hasTaintFlow=5 let mut buf2 = String::new(); let e = source(6); let _ = buf2.write_fmt(format_args!("{e}")); - sink(buf2); // $ MISSING: hasTaintFlow=6 + sink(buf2); // $ hasTaintFlow=6 let mut buf3 = String::new(); let f = source(7); let _ = std::fmt::write(&mut buf3, format_args!("{f}")); - sink(buf3); // $ MISSING: hasTaintFlow=7 + sink(buf3); // $ hasTaintFlow=7 use std::fmt::Write; let mut buf4 = String::new(); let g = source(8); let _ = write!(buf4, "{}", g); - sink(buf4); // $ MISSING: hasTaintFlow=8 + sink(buf4); // $ hasTaintFlow=8 let mut buf5 = String::new(); let h = source(9); let _ = writeln!(buf5, "{h}"); - sink(buf5); // $ MISSING: hasTaintFlow=9 + sink(buf5); // $ hasTaintFlow=9 } // The log-injection sinks (`println!`/`eprintln!`/`panic!`) are reconstructed From ac0cf1a7832484ee081eebd66ab71c64ba2316a3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:50:48 +0100 Subject: [PATCH 3/5] Rust: Change note. --- .../lib/change-notes/2026-08-19-rust-core-fmt-flow-models.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 rust/ql/lib/change-notes/2026-08-19-rust-core-fmt-flow-models.md diff --git a/rust/ql/lib/change-notes/2026-08-19-rust-core-fmt-flow-models.md b/rust/ql/lib/change-notes/2026-08-19-rust-core-fmt-flow-models.md new file mode 100644 index 000000000000..87b8b08ed067 --- /dev/null +++ b/rust/ql/lib/change-notes/2026-08-19-rust-core-fmt-flow-models.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added data-flow models for `core::fmt::Write`. This may improve detection of vulnerabilities where tainted data is written to a formatted output buffer. From 846666e3e067ca2ca01f5039f4f5fe13ab747344 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:17:20 +0100 Subject: [PATCH 4/5] Rust: Update comment. --- .../format-macros-legacy/FormatArgs.expected | 18 +-- .../LogInjection.expected | 38 ++--- .../inline-taint-flow.expected | 132 +++++++++--------- .../format-macros-legacy/main.rs | 10 +- 4 files changed, 96 insertions(+), 102 deletions(-) diff --git a/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected b/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected index 0935662bb71c..56bf946de0e7 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/FormatArgs.expected @@ -1,12 +1,12 @@ | main.rs:13:10:13:25 | FormatArgsExpr | 1 | | main.rs:16:10:16:23 | FormatArgsExpr | 0 | | main.rs:19:13:19:36 | FormatArgsExpr | 1 | -| main.rs:33:25:33:33 | FormatArgsExpr | 1 | -| main.rs:44:40:44:46 | FormatArgsExpr | 0 | -| main.rs:49:52:49:58 | FormatArgsExpr | 0 | -| main.rs:55:13:55:33 | FormatArgsExpr | 1 | -| main.rs:60:13:60:33 | FormatArgsExpr | 0 | -| main.rs:70:5:70:27 | FormatArgsExpr | 1 | -| main.rs:71:5:71:26 | FormatArgsExpr | 0 | -| main.rs:72:5:72:25 | FormatArgsExpr | 1 | -| main.rs:73:5:73:24 | FormatArgsExpr | 0 | +| main.rs:27:25:27:33 | FormatArgsExpr | 1 | +| main.rs:38:40:38:46 | FormatArgsExpr | 0 | +| main.rs:43:52:43:58 | FormatArgsExpr | 0 | +| main.rs:49:13:49:33 | FormatArgsExpr | 1 | +| main.rs:54:13:54:33 | FormatArgsExpr | 0 | +| main.rs:64:5:64:27 | FormatArgsExpr | 1 | +| main.rs:65:5:65:26 | FormatArgsExpr | 0 | +| main.rs:66:5:66:25 | FormatArgsExpr | 1 | +| main.rs:67:5:67:24 | FormatArgsExpr | 0 | diff --git a/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected b/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected index a08e58f094fc..853f6f401549 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/LogInjection.expected @@ -1,28 +1,28 @@ #select -| main.rs:70:5:70:27 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:70:5:70:27 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | -| main.rs:71:5:71:26 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:71:5:71:26 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | -| main.rs:72:5:72:25 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:72:5:72:25 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | -| main.rs:73:5:73:24 | FormatArgsExpr | main.rs:68:19:68:45 | ...::var(...) | main.rs:73:5:73:24 | FormatArgsExpr | Log entry depends on a $@. | main.rs:68:19:68:45 | ...::var(...) | user-provided value | +| main.rs:64:5:64:27 | FormatArgsExpr | main.rs:62:19:62:45 | ...::var(...) | main.rs:64:5:64:27 | FormatArgsExpr | Log entry depends on a $@. | main.rs:62:19:62:45 | ...::var(...) | user-provided value | +| main.rs:65:5:65:26 | FormatArgsExpr | main.rs:62:19:62:45 | ...::var(...) | main.rs:65:5:65:26 | FormatArgsExpr | Log entry depends on a $@. | main.rs:62:19:62:45 | ...::var(...) | user-provided value | +| main.rs:66:5:66:25 | FormatArgsExpr | main.rs:62:19:62:45 | ...::var(...) | main.rs:66:5:66:25 | FormatArgsExpr | Log entry depends on a $@. | main.rs:62:19:62:45 | ...::var(...) | user-provided value | +| main.rs:67:5:67:24 | FormatArgsExpr | main.rs:62:19:62:45 | ...::var(...) | main.rs:67:5:67:24 | FormatArgsExpr | Log entry depends on a $@. | main.rs:62:19:62:45 | ...::var(...) | user-provided value | edges -| main.rs:68:9:68:15 | tainted | main.rs:70:5:70:27 | FormatArgsExpr | provenance | Sink:MaD:2 | -| main.rs:68:9:68:15 | tainted | main.rs:71:5:71:26 | FormatArgsExpr | provenance | Sink:MaD:1 | -| main.rs:68:9:68:15 | tainted | main.rs:72:5:72:25 | FormatArgsExpr | provenance | Sink:MaD:2 | -| main.rs:68:9:68:15 | tainted | main.rs:73:5:73:24 | FormatArgsExpr | provenance | Sink:MaD:1 | -| main.rs:68:19:68:45 | ...::var(...) | main.rs:68:19:68:45 | ...::var(...) [Ok] | provenance | Src:MaD:3 | -| main.rs:68:19:68:45 | ...::var(...) [Ok] | main.rs:68:19:68:65 | ... .unwrap_or_default() | provenance | MaD:4 | -| main.rs:68:19:68:65 | ... .unwrap_or_default() | main.rs:68:9:68:15 | tainted | provenance | | +| main.rs:62:9:62:15 | tainted | main.rs:64:5:64:27 | FormatArgsExpr | provenance | Sink:MaD:2 | +| main.rs:62:9:62:15 | tainted | main.rs:65:5:65:26 | FormatArgsExpr | provenance | Sink:MaD:1 | +| main.rs:62:9:62:15 | tainted | main.rs:66:5:66:25 | FormatArgsExpr | provenance | Sink:MaD:2 | +| main.rs:62:9:62:15 | tainted | main.rs:67:5:67:24 | FormatArgsExpr | provenance | Sink:MaD:1 | +| main.rs:62:19:62:45 | ...::var(...) | main.rs:62:19:62:45 | ...::var(...) [Ok] | provenance | Src:MaD:3 | +| main.rs:62:19:62:45 | ...::var(...) [Ok] | main.rs:62:19:62:65 | ... .unwrap_or_default() | provenance | MaD:4 | +| main.rs:62:19:62:65 | ... .unwrap_or_default() | main.rs:62:9:62:15 | tainted | provenance | | models | 1 | Sink: std::io::stdio::_eprint; Argument[0]; log-injection | | 2 | Sink: std::io::stdio::_print; Argument[0]; log-injection | | 3 | Source: std::env::var; ReturnValue.Field[core::result::Result::Ok(0)]; environment | | 4 | Summary: ::unwrap_or_default; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | nodes -| main.rs:68:9:68:15 | tainted | semmle.label | tainted | -| main.rs:68:19:68:45 | ...::var(...) | semmle.label | ...::var(...) | -| main.rs:68:19:68:45 | ...::var(...) [Ok] | semmle.label | ...::var(...) [Ok] | -| main.rs:68:19:68:65 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() | -| main.rs:70:5:70:27 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:71:5:71:26 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:72:5:72:25 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:73:5:73:24 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:62:9:62:15 | tainted | semmle.label | tainted | +| main.rs:62:19:62:45 | ...::var(...) | semmle.label | ...::var(...) | +| main.rs:62:19:62:45 | ...::var(...) [Ok] | semmle.label | ...::var(...) [Ok] | +| main.rs:62:19:62:65 | ... .unwrap_or_default() | semmle.label | ... .unwrap_or_default() | +| main.rs:64:5:64:27 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:65:5:65:26 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:66:5:66:25 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:67:5:67:24 | FormatArgsExpr | semmle.label | FormatArgsExpr | subpaths diff --git a/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected b/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected index 052888d641f7..7123164d2bfb 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected +++ b/rust/ql/test/library-tests/format-macros-legacy/inline-taint-flow.expected @@ -18,34 +18,34 @@ edges | main.rs:19:9:19:9 | s | main.rs:20:10:20:10 | s | provenance | | | main.rs:19:13:19:36 | ...::format(...) | main.rs:19:9:19:9 | s | provenance | | | main.rs:19:13:19:36 | FormatArgsExpr | main.rs:19:13:19:36 | ...::format(...) | provenance | MaD:4 | -| main.rs:32:9:32:9 | a | main.rs:33:9:33:9 | b | provenance | | -| main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | a | provenance | | -| main.rs:33:9:33:9 | b | main.rs:34:30:34:30 | b | provenance | | -| main.rs:34:9:34:9 | c | main.rs:35:10:35:10 | c | provenance | | -| main.rs:34:13:34:31 | ...::format(...) | main.rs:34:9:34:9 | c | provenance | | -| main.rs:34:30:34:30 | b | main.rs:34:13:34:31 | ...::format(...) | provenance | MaD:4 | -| main.rs:38:9:38:9 | d | main.rs:39:28:39:28 | d | provenance | | -| main.rs:38:13:38:21 | source(...) | main.rs:38:9:38:9 | d | provenance | | -| main.rs:39:13:39:16 | [post] buf1 | main.rs:40:10:40:13 | buf1 | provenance | | -| main.rs:39:28:39:28 | d | main.rs:39:28:39:37 | d.as_str() [&ref] | provenance | MaD:3 | -| main.rs:39:28:39:37 | d.as_str() [&ref] | main.rs:39:13:39:16 | [post] buf1 | provenance | MaD:2 | -| main.rs:43:9:43:9 | e | main.rs:44:28:44:46 | MacroExpr | provenance | | -| main.rs:43:13:43:21 | source(...) | main.rs:43:9:43:9 | e | provenance | | -| main.rs:44:13:44:16 | [post] buf2 | main.rs:45:10:45:13 | buf2 | provenance | | -| main.rs:44:28:44:46 | MacroExpr | main.rs:44:13:44:16 | [post] buf2 | provenance | MaD:1 | -| main.rs:48:9:48:9 | f | main.rs:49:40:49:58 | MacroExpr | provenance | | -| main.rs:48:13:48:21 | source(...) | main.rs:48:9:48:9 | f | provenance | | -| main.rs:49:29:49:37 | [post] &mut buf3 [&ref] | main.rs:49:34:49:37 | [post] buf3 | provenance | | -| main.rs:49:34:49:37 | [post] buf3 | main.rs:50:10:50:13 | buf3 | provenance | | -| main.rs:49:40:49:58 | MacroExpr | main.rs:49:29:49:37 | [post] &mut buf3 [&ref] | provenance | MaD:5 | -| main.rs:54:9:54:9 | g | main.rs:55:13:55:33 | FormatArgsExpr | provenance | | -| main.rs:54:13:54:21 | source(...) | main.rs:54:9:54:9 | g | provenance | | -| main.rs:55:13:55:33 | FormatArgsExpr | main.rs:55:20:55:23 | [post] buf4 | provenance | MaD:1 | -| main.rs:55:20:55:23 | [post] buf4 | main.rs:56:10:56:13 | buf4 | provenance | | -| main.rs:59:9:59:9 | h | main.rs:60:13:60:33 | FormatArgsExpr | provenance | | -| main.rs:59:13:59:21 | source(...) | main.rs:59:9:59:9 | h | provenance | | -| main.rs:60:13:60:33 | FormatArgsExpr | main.rs:60:22:60:25 | [post] buf5 | provenance | MaD:1 | -| main.rs:60:22:60:25 | [post] buf5 | main.rs:61:10:61:13 | buf5 | provenance | | +| main.rs:26:9:26:9 | a | main.rs:27:9:27:9 | b | provenance | | +| main.rs:26:13:26:21 | source(...) | main.rs:26:9:26:9 | a | provenance | | +| main.rs:27:9:27:9 | b | main.rs:28:30:28:30 | b | provenance | | +| main.rs:28:9:28:9 | c | main.rs:29:10:29:10 | c | provenance | | +| main.rs:28:13:28:31 | ...::format(...) | main.rs:28:9:28:9 | c | provenance | | +| main.rs:28:30:28:30 | b | main.rs:28:13:28:31 | ...::format(...) | provenance | MaD:4 | +| main.rs:32:9:32:9 | d | main.rs:33:28:33:28 | d | provenance | | +| main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | d | provenance | | +| main.rs:33:13:33:16 | [post] buf1 | main.rs:34:10:34:13 | buf1 | provenance | | +| main.rs:33:28:33:28 | d | main.rs:33:28:33:37 | d.as_str() [&ref] | provenance | MaD:3 | +| main.rs:33:28:33:37 | d.as_str() [&ref] | main.rs:33:13:33:16 | [post] buf1 | provenance | MaD:2 | +| main.rs:37:9:37:9 | e | main.rs:38:28:38:46 | MacroExpr | provenance | | +| main.rs:37:13:37:21 | source(...) | main.rs:37:9:37:9 | e | provenance | | +| main.rs:38:13:38:16 | [post] buf2 | main.rs:39:10:39:13 | buf2 | provenance | | +| main.rs:38:28:38:46 | MacroExpr | main.rs:38:13:38:16 | [post] buf2 | provenance | MaD:1 | +| main.rs:42:9:42:9 | f | main.rs:43:40:43:58 | MacroExpr | provenance | | +| main.rs:42:13:42:21 | source(...) | main.rs:42:9:42:9 | f | provenance | | +| main.rs:43:29:43:37 | [post] &mut buf3 [&ref] | main.rs:43:34:43:37 | [post] buf3 | provenance | | +| main.rs:43:34:43:37 | [post] buf3 | main.rs:44:10:44:13 | buf3 | provenance | | +| main.rs:43:40:43:58 | MacroExpr | main.rs:43:29:43:37 | [post] &mut buf3 [&ref] | provenance | MaD:5 | +| main.rs:48:9:48:9 | g | main.rs:49:13:49:33 | FormatArgsExpr | provenance | | +| main.rs:48:13:48:21 | source(...) | main.rs:48:9:48:9 | g | provenance | | +| main.rs:49:13:49:33 | FormatArgsExpr | main.rs:49:20:49:23 | [post] buf4 | provenance | MaD:1 | +| main.rs:49:20:49:23 | [post] buf4 | main.rs:50:10:50:13 | buf4 | provenance | | +| main.rs:53:9:53:9 | h | main.rs:54:13:54:33 | FormatArgsExpr | provenance | | +| main.rs:53:13:53:21 | source(...) | main.rs:53:9:53:9 | h | provenance | | +| main.rs:54:13:54:33 | FormatArgsExpr | main.rs:54:22:54:25 | [post] buf5 | provenance | MaD:1 | +| main.rs:54:22:54:25 | [post] buf5 | main.rs:55:10:55:13 | buf5 | provenance | | nodes | main.rs:12:9:12:9 | a | semmle.label | a | | main.rs:12:13:12:21 | source(...) | semmle.label | source(...) | @@ -63,49 +63,49 @@ nodes | main.rs:19:13:19:36 | ...::format(...) | semmle.label | ...::format(...) | | main.rs:19:13:19:36 | FormatArgsExpr | semmle.label | FormatArgsExpr | | main.rs:20:10:20:10 | s | semmle.label | s | -| main.rs:32:9:32:9 | a | semmle.label | a | +| main.rs:26:9:26:9 | a | semmle.label | a | +| main.rs:26:13:26:21 | source(...) | semmle.label | source(...) | +| main.rs:27:9:27:9 | b | semmle.label | b | +| main.rs:28:9:28:9 | c | semmle.label | c | +| main.rs:28:13:28:31 | ...::format(...) | semmle.label | ...::format(...) | +| main.rs:28:30:28:30 | b | semmle.label | b | +| main.rs:29:10:29:10 | c | semmle.label | c | +| main.rs:32:9:32:9 | d | semmle.label | d | | main.rs:32:13:32:21 | source(...) | semmle.label | source(...) | -| main.rs:33:9:33:9 | b | semmle.label | b | -| main.rs:34:9:34:9 | c | semmle.label | c | -| main.rs:34:13:34:31 | ...::format(...) | semmle.label | ...::format(...) | -| main.rs:34:30:34:30 | b | semmle.label | b | -| main.rs:35:10:35:10 | c | semmle.label | c | -| main.rs:38:9:38:9 | d | semmle.label | d | -| main.rs:38:13:38:21 | source(...) | semmle.label | source(...) | -| main.rs:39:13:39:16 | [post] buf1 | semmle.label | [post] buf1 | -| main.rs:39:28:39:28 | d | semmle.label | d | -| main.rs:39:28:39:37 | d.as_str() [&ref] | semmle.label | d.as_str() [&ref] | -| main.rs:40:10:40:13 | buf1 | semmle.label | buf1 | -| main.rs:43:9:43:9 | e | semmle.label | e | -| main.rs:43:13:43:21 | source(...) | semmle.label | source(...) | -| main.rs:44:13:44:16 | [post] buf2 | semmle.label | [post] buf2 | -| main.rs:44:28:44:46 | MacroExpr | semmle.label | MacroExpr | -| main.rs:45:10:45:13 | buf2 | semmle.label | buf2 | -| main.rs:48:9:48:9 | f | semmle.label | f | +| main.rs:33:13:33:16 | [post] buf1 | semmle.label | [post] buf1 | +| main.rs:33:28:33:28 | d | semmle.label | d | +| main.rs:33:28:33:37 | d.as_str() [&ref] | semmle.label | d.as_str() [&ref] | +| main.rs:34:10:34:13 | buf1 | semmle.label | buf1 | +| main.rs:37:9:37:9 | e | semmle.label | e | +| main.rs:37:13:37:21 | source(...) | semmle.label | source(...) | +| main.rs:38:13:38:16 | [post] buf2 | semmle.label | [post] buf2 | +| main.rs:38:28:38:46 | MacroExpr | semmle.label | MacroExpr | +| main.rs:39:10:39:13 | buf2 | semmle.label | buf2 | +| main.rs:42:9:42:9 | f | semmle.label | f | +| main.rs:42:13:42:21 | source(...) | semmle.label | source(...) | +| main.rs:43:29:43:37 | [post] &mut buf3 [&ref] | semmle.label | [post] &mut buf3 [&ref] | +| main.rs:43:34:43:37 | [post] buf3 | semmle.label | [post] buf3 | +| main.rs:43:40:43:58 | MacroExpr | semmle.label | MacroExpr | +| main.rs:44:10:44:13 | buf3 | semmle.label | buf3 | +| main.rs:48:9:48:9 | g | semmle.label | g | | main.rs:48:13:48:21 | source(...) | semmle.label | source(...) | -| main.rs:49:29:49:37 | [post] &mut buf3 [&ref] | semmle.label | [post] &mut buf3 [&ref] | -| main.rs:49:34:49:37 | [post] buf3 | semmle.label | [post] buf3 | -| main.rs:49:40:49:58 | MacroExpr | semmle.label | MacroExpr | -| main.rs:50:10:50:13 | buf3 | semmle.label | buf3 | -| main.rs:54:9:54:9 | g | semmle.label | g | -| main.rs:54:13:54:21 | source(...) | semmle.label | source(...) | -| main.rs:55:13:55:33 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:55:20:55:23 | [post] buf4 | semmle.label | [post] buf4 | -| main.rs:56:10:56:13 | buf4 | semmle.label | buf4 | -| main.rs:59:9:59:9 | h | semmle.label | h | -| main.rs:59:13:59:21 | source(...) | semmle.label | source(...) | -| main.rs:60:13:60:33 | FormatArgsExpr | semmle.label | FormatArgsExpr | -| main.rs:60:22:60:25 | [post] buf5 | semmle.label | [post] buf5 | -| main.rs:61:10:61:13 | buf5 | semmle.label | buf5 | +| main.rs:49:13:49:33 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:49:20:49:23 | [post] buf4 | semmle.label | [post] buf4 | +| main.rs:50:10:50:13 | buf4 | semmle.label | buf4 | +| main.rs:53:9:53:9 | h | semmle.label | h | +| main.rs:53:13:53:21 | source(...) | semmle.label | source(...) | +| main.rs:54:13:54:33 | FormatArgsExpr | semmle.label | FormatArgsExpr | +| main.rs:54:22:54:25 | [post] buf5 | semmle.label | [post] buf5 | +| main.rs:55:10:55:13 | buf5 | semmle.label | buf5 | subpaths testFailures #select | main.rs:13:10:13:25 | MacroExpr | main.rs:12:13:12:21 | source(...) | main.rs:13:10:13:25 | MacroExpr | $@ | main.rs:12:13:12:21 | source(...) | source(...) | | main.rs:16:10:16:23 | MacroExpr | main.rs:15:13:15:21 | source(...) | main.rs:16:10:16:23 | MacroExpr | $@ | main.rs:15:13:15:21 | source(...) | source(...) | | main.rs:20:10:20:10 | s | main.rs:18:13:18:21 | source(...) | main.rs:20:10:20:10 | s | $@ | main.rs:18:13:18:21 | source(...) | source(...) | -| main.rs:35:10:35:10 | c | main.rs:32:13:32:21 | source(...) | main.rs:35:10:35:10 | c | $@ | main.rs:32:13:32:21 | source(...) | source(...) | -| main.rs:40:10:40:13 | buf1 | main.rs:38:13:38:21 | source(...) | main.rs:40:10:40:13 | buf1 | $@ | main.rs:38:13:38:21 | source(...) | source(...) | -| main.rs:45:10:45:13 | buf2 | main.rs:43:13:43:21 | source(...) | main.rs:45:10:45:13 | buf2 | $@ | main.rs:43:13:43:21 | source(...) | source(...) | -| main.rs:50:10:50:13 | buf3 | main.rs:48:13:48:21 | source(...) | main.rs:50:10:50:13 | buf3 | $@ | main.rs:48:13:48:21 | source(...) | source(...) | -| main.rs:56:10:56:13 | buf4 | main.rs:54:13:54:21 | source(...) | main.rs:56:10:56:13 | buf4 | $@ | main.rs:54:13:54:21 | source(...) | source(...) | -| main.rs:61:10:61:13 | buf5 | main.rs:59:13:59:21 | source(...) | main.rs:61:10:61:13 | buf5 | $@ | main.rs:59:13:59:21 | source(...) | source(...) | +| main.rs:29:10:29:10 | c | main.rs:26:13:26:21 | source(...) | main.rs:29:10:29:10 | c | $@ | main.rs:26:13:26:21 | source(...) | source(...) | +| main.rs:34:10:34:13 | buf1 | main.rs:32:13:32:21 | source(...) | main.rs:34:10:34:13 | buf1 | $@ | main.rs:32:13:32:21 | source(...) | source(...) | +| main.rs:39:10:39:13 | buf2 | main.rs:37:13:37:21 | source(...) | main.rs:39:10:39:13 | buf2 | $@ | main.rs:37:13:37:21 | source(...) | source(...) | +| main.rs:44:10:44:13 | buf3 | main.rs:42:13:42:21 | source(...) | main.rs:44:10:44:13 | buf3 | $@ | main.rs:42:13:42:21 | source(...) | source(...) | +| main.rs:50:10:50:13 | buf4 | main.rs:48:13:48:21 | source(...) | main.rs:50:10:50:13 | buf4 | $@ | main.rs:48:13:48:21 | source(...) | source(...) | +| main.rs:55:10:55:13 | buf5 | main.rs:53:13:53:21 | source(...) | main.rs:55:10:55:13 | buf5 | $@ | main.rs:53:13:53:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/format-macros-legacy/main.rs b/rust/ql/test/library-tests/format-macros-legacy/main.rs index 24b955c65356..641391211618 100644 --- a/rust/ql/test/library-tests/format-macros-legacy/main.rs +++ b/rust/ql/test/library-tests/format-macros-legacy/main.rs @@ -21,14 +21,8 @@ pub fn format_flow() { } pub fn exercises_reconstruction() { - // No flow assertions here: these exercise reconstruction of the rest of the - // family, including the writer-argument handling of `write!`/`writeln!`. - // - // Flow into a writer buffer is not recovered on <1.94 (the - // `buf.write_fmt(..)` desugaring is absent), but this matches native - // behavior on >=1.94, where the `Write::write_fmt` content-to-self taint - // model is also missing. So it is a pre-existing model gap, not a - // regression from the reconstruction. + // these exercise reconstruction of the rest of the family, including the + // writer-argument handling of `write!`/`writeln!`. let a = source(4); let b = format_args!("{}", a); let c = std::fmt::format(b); From 35423c22fde84fffffb26c84b67ff892c0e2f946 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:57:42 +0100 Subject: [PATCH 5/5] Rust: Accept fixes for rust/cleartext-logging. --- .../CWE-312/CleartextLogging.expected | 77 ++++++++++++------- .../security/CWE-312/test_logging.rs | 14 ++-- 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected index 3a96605753f6..d719721c3ba4 100644 --- a/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected +++ b/rust/ql/test/query-tests/security/CWE-312/CleartextLogging.expected @@ -26,6 +26,8 @@ | test_logging.rs:94:11:94:28 | MacroExpr | test_logging.rs:93:15:93:22 | password | test_logging.rs:94:11:94:28 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:93:15:93:22 | password | password | | test_logging.rs:97:11:97:18 | MacroExpr | test_logging.rs:96:42:96:49 | password | test_logging.rs:97:11:97:18 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:96:42:96:49 | password | password | | test_logging.rs:100:11:100:18 | MacroExpr | test_logging.rs:99:38:99:45 | password | test_logging.rs:100:11:100:18 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:99:38:99:45 | password | password | +| test_logging.rs:104:11:104:18 | MacroExpr | test_logging.rs:103:37:103:44 | password | test_logging.rs:104:11:104:18 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:103:37:103:44 | password | password | +| test_logging.rs:108:11:108:18 | MacroExpr | test_logging.rs:107:39:107:46 | password | test_logging.rs:108:11:108:18 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:107:39:107:46 | password | password | | test_logging.rs:118:12:118:41 | MacroExpr | test_logging.rs:118:28:118:41 | get_password(...) | test_logging.rs:118:12:118:41 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:118:28:118:41 | get_password(...) | get_password(...) | | test_logging.rs:131:12:131:31 | MacroExpr | test_logging.rs:129:25:129:32 | password | test_logging.rs:131:12:131:31 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:129:25:129:32 | password | password | | test_logging.rs:141:11:141:37 | MacroExpr | test_logging.rs:141:27:141:37 | s1.password | test_logging.rs:141:11:141:37 | MacroExpr | This operation writes $@ to a log file. | test_logging.rs:141:27:141:37 | s1.password | s1.password | @@ -115,16 +117,24 @@ edges | test_logging.rs:93:15:93:22 | password | test_logging.rs:93:14:93:22 | &password | provenance | Config | | test_logging.rs:96:9:96:10 | m2 | test_logging.rs:97:11:97:18 | MacroExpr | provenance | Sink:MaD:11 | | test_logging.rs:96:14:96:49 | ... + ... | test_logging.rs:96:9:96:10 | m2 | provenance | | -| test_logging.rs:96:41:96:49 | &password | test_logging.rs:96:14:96:49 | ... + ... | provenance | MaD:16 | -| test_logging.rs:96:41:96:49 | &password [&ref] | test_logging.rs:96:14:96:49 | ... + ... | provenance | MaD:16 | +| test_logging.rs:96:41:96:49 | &password | test_logging.rs:96:14:96:49 | ... + ... | provenance | MaD:17 | +| test_logging.rs:96:41:96:49 | &password [&ref] | test_logging.rs:96:14:96:49 | ... + ... | provenance | MaD:17 | | test_logging.rs:96:42:96:49 | password | test_logging.rs:96:41:96:49 | &password | provenance | Config | | test_logging.rs:96:42:96:49 | password | test_logging.rs:96:41:96:49 | &password [&ref] | provenance | | | test_logging.rs:99:9:99:10 | m3 | test_logging.rs:100:11:100:18 | MacroExpr | provenance | Sink:MaD:11 | | test_logging.rs:99:22:99:45 | ...::format(...) | test_logging.rs:99:22:99:45 | { ... } | provenance | | | test_logging.rs:99:22:99:45 | ...::must_use(...) | test_logging.rs:99:9:99:10 | m3 | provenance | | -| test_logging.rs:99:22:99:45 | MacroExpr | test_logging.rs:99:22:99:45 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:99:22:99:45 | { ... } | test_logging.rs:99:22:99:45 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:99:22:99:45 | MacroExpr | test_logging.rs:99:22:99:45 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:99:22:99:45 | { ... } | test_logging.rs:99:22:99:45 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:99:38:99:45 | password | test_logging.rs:99:22:99:45 | MacroExpr | provenance | | +| test_logging.rs:103:12:103:18 | [post] &mut m4 [&ref] | test_logging.rs:103:17:103:18 | [post] m4 | provenance | | +| test_logging.rs:103:17:103:18 | [post] m4 | test_logging.rs:104:11:104:18 | MacroExpr | provenance | Sink:MaD:11 | +| test_logging.rs:103:21:103:44 | MacroExpr | test_logging.rs:103:12:103:18 | [post] &mut m4 [&ref] | provenance | MaD:16 | +| test_logging.rs:103:37:103:44 | password | test_logging.rs:103:21:103:44 | MacroExpr | provenance | | +| test_logging.rs:107:14:107:20 | [post] &mut m5 [&ref] | test_logging.rs:107:19:107:20 | [post] m5 | provenance | | +| test_logging.rs:107:19:107:20 | [post] m5 | test_logging.rs:108:11:108:18 | MacroExpr | provenance | Sink:MaD:11 | +| test_logging.rs:107:23:107:46 | MacroExpr | test_logging.rs:107:14:107:20 | [post] &mut m5 [&ref] | provenance | MaD:16 | +| test_logging.rs:107:39:107:46 | password | test_logging.rs:107:23:107:46 | MacroExpr | provenance | | | test_logging.rs:118:28:118:41 | get_password(...) | test_logging.rs:118:12:118:41 | MacroExpr | provenance | Sink:MaD:11 | | test_logging.rs:129:9:129:10 | t1 [tuple.1] | test_logging.rs:131:28:131:29 | t1 [tuple.1] | provenance | | | test_logging.rs:129:14:129:33 | TupleExpr [tuple.1] | test_logging.rs:129:9:129:10 | t1 [tuple.1] | provenance | | @@ -139,8 +149,8 @@ edges | test_logging.rs:176:34:176:79 | MacroExpr | test_logging.rs:176:33:176:79 | &... [&ref] | provenance | | | test_logging.rs:176:42:176:78 | ...::format(...) | test_logging.rs:176:42:176:78 | { ... } | provenance | | | test_logging.rs:176:42:176:78 | ...::must_use(...) | test_logging.rs:176:34:176:79 | MacroExpr | provenance | | -| test_logging.rs:176:42:176:78 | MacroExpr | test_logging.rs:176:42:176:78 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:176:42:176:78 | { ... } | test_logging.rs:176:42:176:78 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:176:42:176:78 | MacroExpr | test_logging.rs:176:42:176:78 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:176:42:176:78 | { ... } | test_logging.rs:176:42:176:78 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:176:70:176:78 | password2 | test_logging.rs:176:42:176:78 | MacroExpr | provenance | | | test_logging.rs:180:35:180:81 | &... | test_logging.rs:180:35:180:81 | &... | provenance | Sink:MaD:3 | | test_logging.rs:180:35:180:81 | &... [&ref] | test_logging.rs:180:35:180:81 | &... | provenance | Sink:MaD:3 | @@ -148,8 +158,8 @@ edges | test_logging.rs:180:36:180:81 | MacroExpr | test_logging.rs:180:35:180:81 | &... [&ref] | provenance | | | test_logging.rs:180:44:180:80 | ...::format(...) | test_logging.rs:180:44:180:80 | { ... } | provenance | | | test_logging.rs:180:44:180:80 | ...::must_use(...) | test_logging.rs:180:36:180:81 | MacroExpr | provenance | | -| test_logging.rs:180:44:180:80 | MacroExpr | test_logging.rs:180:44:180:80 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:180:44:180:80 | { ... } | test_logging.rs:180:44:180:80 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:180:44:180:80 | MacroExpr | test_logging.rs:180:44:180:80 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:180:44:180:80 | { ... } | test_logging.rs:180:44:180:80 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:180:72:180:80 | password2 | test_logging.rs:180:44:180:80 | MacroExpr | provenance | | | test_logging.rs:183:9:183:19 | err_result2 [Err] | test_logging.rs:184:13:184:23 | err_result2 | provenance | Sink:MaD:4 | | test_logging.rs:183:47:183:68 | Err(...) [Err] | test_logging.rs:183:9:183:19 | err_result2 [Err] | provenance | | @@ -180,40 +190,40 @@ edges | test_logging.rs:226:36:226:59 | ...::Some(...) [Some] | test_logging.rs:226:36:226:59 | ...::Some(...) | provenance | Sink:MaD:9 | | test_logging.rs:226:36:226:59 | MacroExpr | test_logging.rs:226:36:226:59 | ...::Some(...) [Some] | provenance | | | test_logging.rs:226:52:226:59 | password | test_logging.rs:226:36:226:59 | MacroExpr | provenance | | -| test_logging.rs:229:30:229:62 | MacroExpr | test_logging.rs:229:30:229:71 | ... .as_str() [&ref] | provenance | MaD:18 | +| test_logging.rs:229:30:229:62 | MacroExpr | test_logging.rs:229:30:229:71 | ... .as_str() [&ref] | provenance | MaD:19 | | test_logging.rs:229:30:229:71 | ... .as_str() [&ref] | test_logging.rs:229:30:229:71 | ... .as_str() | provenance | Sink:MaD:2 | | test_logging.rs:229:38:229:61 | ...::format(...) | test_logging.rs:229:38:229:61 | { ... } | provenance | | | test_logging.rs:229:38:229:61 | ...::must_use(...) | test_logging.rs:229:30:229:62 | MacroExpr | provenance | | -| test_logging.rs:229:38:229:61 | MacroExpr | test_logging.rs:229:38:229:61 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:229:38:229:61 | { ... } | test_logging.rs:229:38:229:61 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:229:38:229:61 | MacroExpr | test_logging.rs:229:38:229:61 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:229:38:229:61 | { ... } | test_logging.rs:229:38:229:61 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:229:54:229:61 | password | test_logging.rs:229:38:229:61 | MacroExpr | provenance | | -| test_logging.rs:242:16:242:50 | MacroExpr | test_logging.rs:242:16:242:61 | ... .as_bytes() [&ref, element] | provenance | MaD:17 | +| test_logging.rs:242:16:242:50 | MacroExpr | test_logging.rs:242:16:242:61 | ... .as_bytes() [&ref, element] | provenance | MaD:18 | | test_logging.rs:242:16:242:61 | ... .as_bytes() [&ref, element] | test_logging.rs:242:16:242:61 | ... .as_bytes() | provenance | Sink:MaD:7 Sink:MaD:7 | | test_logging.rs:242:24:242:49 | ...::format(...) | test_logging.rs:242:24:242:49 | { ... } | provenance | | | test_logging.rs:242:24:242:49 | ...::must_use(...) | test_logging.rs:242:16:242:50 | MacroExpr | provenance | | -| test_logging.rs:242:24:242:49 | MacroExpr | test_logging.rs:242:24:242:49 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:242:24:242:49 | { ... } | test_logging.rs:242:24:242:49 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:242:24:242:49 | MacroExpr | test_logging.rs:242:24:242:49 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:242:24:242:49 | { ... } | test_logging.rs:242:24:242:49 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:242:42:242:49 | password | test_logging.rs:242:24:242:49 | MacroExpr | provenance | | -| test_logging.rs:245:20:245:54 | MacroExpr | test_logging.rs:245:20:245:65 | ... .as_bytes() [&ref, element] | provenance | MaD:17 | +| test_logging.rs:245:20:245:54 | MacroExpr | test_logging.rs:245:20:245:65 | ... .as_bytes() [&ref, element] | provenance | MaD:18 | | test_logging.rs:245:20:245:65 | ... .as_bytes() [&ref, element] | test_logging.rs:245:20:245:65 | ... .as_bytes() | provenance | Sink:MaD:8 Sink:MaD:8 | | test_logging.rs:245:28:245:53 | ...::format(...) | test_logging.rs:245:28:245:53 | { ... } | provenance | | | test_logging.rs:245:28:245:53 | ...::must_use(...) | test_logging.rs:245:20:245:54 | MacroExpr | provenance | | -| test_logging.rs:245:28:245:53 | MacroExpr | test_logging.rs:245:28:245:53 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:245:28:245:53 | { ... } | test_logging.rs:245:28:245:53 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:245:28:245:53 | MacroExpr | test_logging.rs:245:28:245:53 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:245:28:245:53 | { ... } | test_logging.rs:245:28:245:53 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:245:46:245:53 | password | test_logging.rs:245:28:245:53 | MacroExpr | provenance | | -| test_logging.rs:248:15:248:49 | MacroExpr | test_logging.rs:248:15:248:60 | ... .as_bytes() [&ref, element] | provenance | MaD:17 | +| test_logging.rs:248:15:248:49 | MacroExpr | test_logging.rs:248:15:248:60 | ... .as_bytes() [&ref, element] | provenance | MaD:18 | | test_logging.rs:248:15:248:60 | ... .as_bytes() [&ref, element] | test_logging.rs:248:15:248:60 | ... .as_bytes() | provenance | Sink:MaD:7 Sink:MaD:7 | | test_logging.rs:248:23:248:48 | ...::format(...) | test_logging.rs:248:23:248:48 | { ... } | provenance | | | test_logging.rs:248:23:248:48 | ...::must_use(...) | test_logging.rs:248:15:248:49 | MacroExpr | provenance | | -| test_logging.rs:248:23:248:48 | MacroExpr | test_logging.rs:248:23:248:48 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:248:23:248:48 | { ... } | test_logging.rs:248:23:248:48 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:248:23:248:48 | MacroExpr | test_logging.rs:248:23:248:48 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:248:23:248:48 | { ... } | test_logging.rs:248:23:248:48 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:248:41:248:48 | password | test_logging.rs:248:23:248:48 | MacroExpr | provenance | | -| test_logging.rs:251:15:251:49 | MacroExpr | test_logging.rs:251:15:251:60 | ... .as_bytes() [&ref, element] | provenance | MaD:17 | +| test_logging.rs:251:15:251:49 | MacroExpr | test_logging.rs:251:15:251:60 | ... .as_bytes() [&ref, element] | provenance | MaD:18 | | test_logging.rs:251:15:251:60 | ... .as_bytes() [&ref, element] | test_logging.rs:251:15:251:60 | ... .as_bytes() | provenance | Sink:MaD:6 Sink:MaD:6 | | test_logging.rs:251:23:251:48 | ...::format(...) | test_logging.rs:251:23:251:48 | { ... } | provenance | | | test_logging.rs:251:23:251:48 | ...::must_use(...) | test_logging.rs:251:15:251:49 | MacroExpr | provenance | | -| test_logging.rs:251:23:251:48 | MacroExpr | test_logging.rs:251:23:251:48 | ...::format(...) | provenance | MaD:19 | -| test_logging.rs:251:23:251:48 | { ... } | test_logging.rs:251:23:251:48 | ...::must_use(...) | provenance | MaD:20 | +| test_logging.rs:251:23:251:48 | MacroExpr | test_logging.rs:251:23:251:48 | ...::format(...) | provenance | MaD:20 | +| test_logging.rs:251:23:251:48 | { ... } | test_logging.rs:251:23:251:48 | ...::must_use(...) | provenance | MaD:21 | | test_logging.rs:251:41:251:48 | password | test_logging.rs:251:23:251:48 | MacroExpr | provenance | | models | 1 | Sink: ::log_expect; Argument[0]; log-injection | @@ -231,11 +241,12 @@ models | 13 | Sink: std::io::stdio::_eprint; Argument[0]; log-injection | | 14 | Sink: std::io::stdio::_print; Argument[0]; log-injection | | 15 | Summary: <_ as core::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value | -| 16 | Summary: ::add; Argument[0].Reference; ReturnValue; taint | -| 17 | Summary: ::as_bytes; Argument[self].Reference; ReturnValue.Reference.Element; taint | -| 18 | Summary: ::as_str; Argument[self].Reference; ReturnValue.Reference; taint | -| 19 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint | -| 20 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value | +| 16 | Summary: <_ as core::fmt::Write>::write_fmt; Argument[0]; Argument[self].Reference; taint | +| 17 | Summary: ::add; Argument[0].Reference; ReturnValue; taint | +| 18 | Summary: ::as_bytes; Argument[self].Reference; ReturnValue.Reference.Element; taint | +| 19 | Summary: ::as_str; Argument[self].Reference; ReturnValue.Reference; taint | +| 20 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint | +| 21 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value | nodes | test_logging.rs:42:12:42:35 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:42:28:42:35 | password | semmle.label | password | @@ -326,6 +337,16 @@ nodes | test_logging.rs:99:22:99:45 | { ... } | semmle.label | { ... } | | test_logging.rs:99:38:99:45 | password | semmle.label | password | | test_logging.rs:100:11:100:18 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:103:12:103:18 | [post] &mut m4 [&ref] | semmle.label | [post] &mut m4 [&ref] | +| test_logging.rs:103:17:103:18 | [post] m4 | semmle.label | [post] m4 | +| test_logging.rs:103:21:103:44 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:103:37:103:44 | password | semmle.label | password | +| test_logging.rs:104:11:104:18 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:107:14:107:20 | [post] &mut m5 [&ref] | semmle.label | [post] &mut m5 [&ref] | +| test_logging.rs:107:19:107:20 | [post] m5 | semmle.label | [post] m5 | +| test_logging.rs:107:23:107:46 | MacroExpr | semmle.label | MacroExpr | +| test_logging.rs:107:39:107:46 | password | semmle.label | password | +| test_logging.rs:108:11:108:18 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:118:12:118:41 | MacroExpr | semmle.label | MacroExpr | | test_logging.rs:118:28:118:41 | get_password(...) | semmle.label | get_password(...) | | test_logging.rs:129:9:129:10 | t1 [tuple.1] | semmle.label | t1 [tuple.1] | diff --git a/rust/ql/test/query-tests/security/CWE-312/test_logging.rs b/rust/ql/test/query-tests/security/CWE-312/test_logging.rs index 43bcd8894f3c..d9dc9952086a 100644 --- a/rust/ql/test/query-tests/security/CWE-312/test_logging.rs +++ b/rust/ql/test/query-tests/security/CWE-312/test_logging.rs @@ -100,15 +100,15 @@ fn test_log(harmless: String, password: String, encrypted_password: String) { info!("{}", m3); // $ Alert[rust/cleartext-logging]=m3 let mut m4 = String::new(); - write!(&mut m4, "message = {}", password); // $ MISSING: Source=m4 - info!("{}", m4); // $ MISSING: Alert[rust/cleartext-logging]=m4 + write!(&mut m4, "message = {}", password); // $ Source[rust/cleartext-logging]=m4 + info!("{}", m4); // $ Alert[rust/cleartext-logging]=m4 let mut m5 = String::new(); - writeln!(&mut m5, "message = {}", password); // $ MISSING: Source=m5 - info!("{}", m5); // $ MISSING: Alert[rust/cleartext-logging]=m5 + writeln!(&mut m5, "message = {}", password); // $ Source[rust/cleartext-logging]=m5 + info!("{}", m5); // $ Alert[rust/cleartext-logging]=m5 let mut m6 = Vec::new(); - write!(&mut m6, "message = {}", password); // $ MISSING: Source=m6 + write!(&mut m6, "message = {}", password); // $ MISSING: Source[rust/cleartext-logging]=m6 info!("{}", std::str::from_utf8(&m6).unwrap()); // $ MISSING: Alert[rust/cleartext-logging]=m6 unsafe { info!("{}", std::str::from_utf8_unchecked(&m6)); // $ MISSING: Alert[rust/cleartext-logging]=m6 @@ -135,7 +135,7 @@ fn test_log(harmless: String, password: String, encrypted_password: String) { // logging from a struct let s1 = MyStruct1 { harmless: "foo".to_string(), - password: "123456".to_string(), // $ MISSING: Source=s1 + password: "123456".to_string(), // $ MISSING: Source[rust/cleartext-logging]=s1 }; warn!("message = {}", s1.harmless); warn!("message = {}", s1.password); // $ Alert[rust/cleartext-logging] @@ -145,7 +145,7 @@ fn test_log(harmless: String, password: String, encrypted_password: String) { let s2 = MyStruct2 { harmless: "foo".to_string(), - password: "123456".to_string(), // $ MISSING: Source=s2 + password: "123456".to_string(), // $ MISSING: Source[rust/cleartext-logging]=s2 }; warn!("message = {}", s2.harmless); warn!("message = {}", s2.password); // $ Alert[rust/cleartext-logging]