From dcc488cb0587614fb0960e20b165bbf1a35b0888 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 17 Apr 2025 20:03:37 +0100 Subject: [PATCH 01/14] Rust: Clean up the sources test. --- .../dataflow/sources/TaintSources.expected | 52 ++--- .../library-tests/dataflow/sources/test.rs | 204 ++++++++++-------- 2 files changed, 146 insertions(+), 110 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index ba7eeae00081..47bdf01faf1e 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -20,30 +20,30 @@ | 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). | -| test.rs:112:35:112:46 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:112:31:112:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:119:31:119:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:205:31:205:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:210:31:210:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:215:22:215:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:221:22:221:25 | path | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:222:27:222:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:228:22:228:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:243:22:243:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:249:22:249:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:255:22:255:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:261:9:261:22 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:265:17:265:30 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:271:20:271:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:304:50:304:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:310:50:310:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:317:50:317:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:324:50:324:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:331:56:331:69 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:338:50:338:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:345:50:345:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:351:50:351:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:360:25:360:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:361:25:361:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:369:25:369:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:377:22:377:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:386:16:386:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:209:22:209:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:215:22:215:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:221:22:221:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:227:22:227:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:233:9:233:22 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:237:17:237:30 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:244:50:244:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:250:46:250:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:257:50:257:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:264:50:264:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:271:56:271:69 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:278:46:278:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:285:46:285:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:291:46:291:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:303:31:303:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:308:31:308:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:313:22:313:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:319:22:319:25 | path | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:320:27:320:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:326:22:326:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:336:20:336:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:370:21:370:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:371:21:371:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:379:21:379:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:390:16:390:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 2ec0b8964ca2..8ffa464a0b44 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -106,10 +106,10 @@ async fn test_hyper_http(case: i64) -> Result<(), Box> { // make the request println!("sending request..."); - if (case == 0) { + if case == 0 { // simple flow case let request = http::Request::builder().uri(url).body(String::from(""))?; - let mut response = sender.send_request(request).await?; // $ Alert[rust/summary/taint-sources] + let response = sender.send_request(request).await?; // $ Alert[rust/summary/taint-sources] sink(&response); // $ hasTaintFlow=request sink(response); // $ hasTaintFlow=request return Ok(()) @@ -198,44 +198,10 @@ async fn test_hyper_http(case: i64) -> Result<(), Box> { Ok(()) } -use std::fs; - -fn test_fs() -> Result<(), Box> { - { - let buffer: Vec = std::fs::read("file.bin")?; // $ Alert[rust/summary/taint-sources] - sink(buffer); // $ hasTaintFlow="file.bin" - } - - { - let buffer: Vec = fs::read("file.bin")?; // $ Alert[rust/summary/taint-sources] - sink(buffer); // $ hasTaintFlow="file.bin" - } - - { - let buffer = fs::read_to_string("file.txt")?; // $ Alert[rust/summary/taint-sources] - sink(buffer); // $ hasTaintFlow="file.txt" - } - - for entry in fs::read_dir("directory")? { - let e = entry?; - let path = e.path(); // $ Alert[rust/summary/taint-sources] - let file_name = e.file_name(); // $ Alert[rust/summary/taint-sources] - sink(path); // $ hasTaintFlow - sink(file_name); // $ hasTaintFlow - } - - { - let target = fs::read_link("symlink.txt")?; // $ Alert[rust/summary/taint-sources] - sink(target); // $ hasTaintFlow="symlink.txt" - } - - Ok(()) -} - use std::io::Read; use std::io::BufRead; -fn test_io_fs() -> std::io::Result<()> { +fn test_io_stdin() -> std::io::Result<()> { // --- stdin --- { @@ -256,46 +222,20 @@ fn test_io_fs() -> std::io::Result<()> { sink(&buffer); // $ hasTaintFlow } - { - let mut buffer = [0; 100]; - std::io::stdin().read_exact(&mut buffer)?; // $ Alert[rust/summary/taint-sources] - sink(&buffer); // $ hasTaintFlow - } - - for byte in std::io::stdin().bytes() { // $ Alert[rust/summary/taint-sources] - sink(byte); // $ hasTaintFlow - } - - // --- file --- - - let mut file = std::fs::File::open("file.txt")?; // $ Alert[rust/summary/taint-sources] - - { - let mut buffer = [0u8; 100]; - let _bytes = file.read(&mut buffer)?; - sink(&buffer); // $ hasTaintFlow="file.txt" - } - - { - let mut buffer = Vec::::new(); - let _bytes = file.read_to_end(&mut buffer)?; - sink(&buffer); // $ hasTaintFlow="file.txt" - } - { let mut buffer = String::new(); - let _bytes = file.read_to_string(&mut buffer)?; - sink(&buffer); // $ hasTaintFlow="file.txt" + let _bytes = std::io::stdin().lock().read_to_string(&mut buffer)?; // $ Alert[rust/summary/taint-sources] + sink(&buffer); // $ hasTaintFlow } { let mut buffer = [0; 100]; - file.read_exact(&mut buffer)?; - sink(&buffer); // $ hasTaintFlow="file.txt" + std::io::stdin().read_exact(&mut buffer)?; // $ Alert[rust/summary/taint-sources] + sink(&buffer); // $ hasTaintFlow } - for byte in file.bytes() { - sink(byte); // $ hasTaintFlow="file.txt" + for byte in std::io::stdin().bytes() { // $ Alert[rust/summary/taint-sources] + sink(byte); // $ hasTaintFlow } // --- BufReader --- @@ -307,7 +247,7 @@ fn test_io_fs() -> std::io::Result<()> { } { - let mut reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] + let reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] let data = reader.buffer(); sink(&data); // $ hasTaintFlow } @@ -324,10 +264,10 @@ fn test_io_fs() -> std::io::Result<()> { let mut reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] reader.read_until(b',', &mut buffer)?; sink(&buffer); // $ hasTaintFlow + sink(buffer[0]); // $ hasTaintFlow } { - let mut buffer = Vec::::new(); let mut reader_split = std::io::BufReader::new(std::io::stdin()).split(b','); // $ Alert[rust/summary/taint-sources] while let Some(chunk) = reader_split.next() { sink(chunk.unwrap()); // $ MISSING: hasTaintFlow @@ -335,30 +275,100 @@ fn test_io_fs() -> std::io::Result<()> { } { - let mut reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] + let reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] for line in reader.lines() { sink(line); // $ hasTaintFlow } } { - let mut reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] + let reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] let line = reader.lines().nth(1).unwrap(); sink(line.unwrap().clone()); // $ MISSING: hasTaintFlow } { - let mut reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] + let reader = std::io::BufReader::new(std::io::stdin()); // $ Alert[rust/summary/taint-sources] let lines: Vec<_> = reader.lines().collect(); sink(lines[1].as_ref().unwrap().clone()); // $ MISSING: hasTaintFlow } + Ok(()) +} + +use std::fs; + +fn test_fs() -> Result<(), Box> { + { + let buffer: Vec = std::fs::read("file.bin")?; // $ Alert[rust/summary/taint-sources] + sink(buffer); // $ hasTaintFlow="file.bin" + } + + { + let buffer: Vec = fs::read("file.bin")?; // $ Alert[rust/summary/taint-sources] + sink(buffer); // $ hasTaintFlow="file.bin" + } + + { + let buffer = fs::read_to_string("file.txt")?; // $ Alert[rust/summary/taint-sources] + sink(buffer); // $ hasTaintFlow="file.txt" + } + + for entry in fs::read_dir("directory")? { + let e = entry?; + let path = e.path(); // $ Alert[rust/summary/taint-sources] + let file_name = e.file_name(); // $ Alert[rust/summary/taint-sources] + sink(path); // $ hasTaintFlow + sink(file_name); // $ hasTaintFlow + } + + { + let target = fs::read_link("symlink.txt")?; // $ Alert[rust/summary/taint-sources] + sink(target); // $ hasTaintFlow="symlink.txt" + } + + Ok(()) +} + +fn test_io_file() -> std::io::Result<()> { + // --- file --- + + let mut file = std::fs::File::open("file.txt")?; // $ Alert[rust/summary/taint-sources] + + { + let mut buffer = [0u8; 100]; + let _bytes = file.read(&mut buffer)?; + sink(&buffer); // $ hasTaintFlow="file.txt" + } + + { + let mut buffer = Vec::::new(); + let _bytes = file.read_to_end(&mut buffer)?; + sink(&buffer); // $ hasTaintFlow="file.txt" + } + + { + let mut buffer = String::new(); + let _bytes = file.read_to_string(&mut buffer)?; + sink(&buffer); // $ hasTaintFlow="file.txt" + } + + { + let mut buffer = [0; 100]; + file.read_exact(&mut buffer)?; + sink(&buffer); // $ hasTaintFlow="file.txt" + } + + for byte in file.bytes() { + sink(byte); // $ hasTaintFlow="file.txt" + } + // --- misc operations --- { let mut buffer = String::new(); - let mut file1 = std::fs::File::open("file.txt")?; // $ Alert[rust/summary/taint-sources] - let mut file2 = std::fs::File::open("another_file.txt")?; // $ Alert[rust/summary/taint-sources] + let file1 = std::fs::File::open("file.txt")?; // $ Alert[rust/summary/taint-sources] + let file2 = std::fs::File::open("another_file.txt")?; // $ Alert[rust/summary/taint-sources] let mut reader = file1.chain(file2); reader.read_to_string(&mut buffer)?; sink(&buffer); // $ hasTaintFlow="file.txt" hasTaintFlow="another_file.txt" @@ -366,18 +376,12 @@ fn test_io_fs() -> std::io::Result<()> { { let mut buffer = String::new(); - let mut file1 = std::fs::File::open("file.txt")?; // $ Alert[rust/summary/taint-sources] + let file1 = std::fs::File::open("file.txt")?; // $ Alert[rust/summary/taint-sources] let mut reader = file1.take(100); reader.read_to_string(&mut buffer)?; sink(&buffer); // $ hasTaintFlow="file.txt" } - { - let mut buffer = String::new(); - let _bytes = std::io::stdin().lock().read_to_string(&mut buffer)?; // $ Alert[rust/summary/taint-sources] - sink(&buffer); // $ hasTaintFlow - } - Ok(()) } @@ -385,12 +389,44 @@ fn test_io_fs() -> std::io::Result<()> { async fn main() -> Result<(), Box> { let case = std::env::args().nth(1).unwrap_or(String::from("1")).parse::().unwrap(); // $ Alert[rust/summary/taint-sources] + println!("test_env_vars..."); + test_env_vars(); + + /*println!("test_env_args..."); + test_env_args();*/ + + println!("test_env_dirs..."); + test_env_dirs(); + + /*println!("test_reqwest..."); + match futures::executor::block_on(test_reqwest()) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + }*/ + println!("test_hyper_http..."); match futures::executor::block_on(test_hyper_http(case)) { Ok(_) => println!("complete"), Err(e) => println!("error: {}", e), } - println!(""); + + /*println!("test_io_stdin..."); + match test_io_stdin() { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + }*/ + + println!("test_fs..."); + match test_fs() { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } + + println!("test_io_file..."); + match test_io_file() { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } Ok(()) } From 307424e87e4803fb0daa2b1702c1119ec2b3937f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 10:53:36 +0100 Subject: [PATCH 02/14] Rust: Add source tests for tokio (stdin). --- .../dataflow/sources/TaintSources.expected | 22 ++--- .../library-tests/dataflow/sources/test.rs | 87 +++++++++++++++++++ 2 files changed, 98 insertions(+), 11 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 47bdf01faf1e..616195e5f311 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -36,14 +36,14 @@ | test.rs:278:46:278:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:285:46:285:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:291:46:291:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:303:31:303:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:308:31:308:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:313:22:313:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:319:22:319:25 | path | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:320:27:320:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:326:22:326:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:336:20:336:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:370:21:370:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:371:21:371:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:379:21:379:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:390:16:390:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:384:31:384:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:389:31:389:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:394:22:394:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:400:22:400:25 | path | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:401:27:401:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:407:22:407:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:417:20:417:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:451:21:451:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:452:21:452:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:460:21:460:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:471:16:471:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 8ffa464a0b44..084df8bb13f2 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -296,6 +296,87 @@ fn test_io_stdin() -> std::io::Result<()> { Ok(()) } +use tokio::io::{AsyncReadExt, AsyncBufReadExt}; + +async fn test_tokio_stdin() -> Result<(), Box> { + + // --- async reading from stdin --- + + { + let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut buffer = [0u8; 100]; + let _bytes = stdin.read(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + + { + let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut buffer = Vec::::new(); + let _bytes = stdin.read_to_end(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + + { + let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut buffer = String::new(); + let _bytes = stdin.read_to_string(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + + { + let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut buffer = [0; 100]; + stdin.read_exact(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + + // --- async reading from stdin (BufReader) --- + + { + let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let data = reader.fill_buf().await?; + sink(&data); // $ MISSING: hasTaintFlow + } + + { + let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let data = reader.buffer(); + sink(&data); // $ MISSING: hasTaintFlow + } + + { + let mut buffer = String::new(); + let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + reader.read_line(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + + { + let mut buffer = Vec::::new(); + let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + reader.read_until(b',', &mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + sink(buffer[0]); // $ MISSING: hasTaintFlow + } + + { + let mut reader_split = tokio::io::BufReader::new(tokio::io::stdin()).split(b','); // $ MISSING: Alert[rust/summary/taint-sources] + while let Some(chunk) = reader_split.next_segment().await? { + sink(chunk); // $ MISSING: hasTaintFlow + } + } + + { + let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let mut lines = reader.lines(); + while let Some(line) = lines.next_line().await? { + sink(line); // $ hasTai + } + } + + Ok(()) +} + use std::fs; fn test_fs() -> Result<(), Box> { @@ -414,6 +495,12 @@ async fn main() -> Result<(), Box> { match test_io_stdin() { Ok(_) => println!("complete"), Err(e) => println!("error: {}", e), + } + + println!("test_tokio_stdin..."); + match futures::executor::block_on(test_tokio_stdin()) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), }*/ println!("test_fs..."); From 809dd20f9d3772c420a16ab18fddb25893b76e2e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 10:56:47 +0100 Subject: [PATCH 03/14] Rust: Add source tests for tokio (file). --- .../dataflow/sources/TaintSources.expected | 2 +- .../library-tests/dataflow/sources/test.rs | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 616195e5f311..6ce7eea13be6 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -46,4 +46,4 @@ | test.rs:451:21:451:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:452:21:452:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:460:21:460:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:471:16:471:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:522:16:522:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 084df8bb13f2..9347642820f0 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -466,6 +466,57 @@ fn test_io_file() -> std::io::Result<()> { Ok(()) } +async fn test_tokio_file() -> std::io::Result<()> { + // --- file --- + + let mut file = tokio::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + + { + let mut buffer = [0u8; 100]; + let _bytes = file.read(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + } + + { + let mut buffer = Vec::::new(); + let _bytes = file.read_to_end(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + } + + { + let mut buffer = String::new(); + let _bytes = file.read_to_string(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + } + + { + let mut buffer = [0; 100]; + file.read_exact(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + } + + // --- misc operations --- + + { + let mut buffer = String::new(); + let file1 = tokio::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + let file2 = tokio::fs::File::open("another_file.txt").await?; // $ MISSING: [rust/summary/taint-sources] + let mut reader = file1.chain(file2); + reader.read_to_string(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" hasTaintFlow="another_file.txt" + } + + { + let mut buffer = String::new(); + let file1 = tokio::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + let mut reader = file1.take(100); + reader.read_to_string(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + } + + Ok(()) +} + #[tokio::main] async fn main() -> Result<(), Box> { let case = std::env::args().nth(1).unwrap_or(String::from("1")).parse::().unwrap(); // $ Alert[rust/summary/taint-sources] @@ -515,5 +566,11 @@ async fn main() -> Result<(), Box> { Err(e) => println!("error: {}", e), } + println!("test_tokio_file..."); + match futures::executor::block_on(test_tokio_file()) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } + Ok(()) } From b57375aa91d66c08b193d33742e720fd529651cd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:25:36 +0100 Subject: [PATCH 04/14] Rust: Add source tests for tcp (std and tokio). --- .../dataflow/sources/TaintSources.expected | 2 +- .../library-tests/dataflow/sources/test.rs | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 6ce7eea13be6..e34f7bbcd249 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -46,4 +46,4 @@ | test.rs:451:21:451:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:452:21:452:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:460:21:460:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:522:16:522:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:621:16:621:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 9347642820f0..1dc573c5e3ac 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -517,6 +517,105 @@ async fn test_tokio_file() -> std::io::Result<()> { Ok(()) } +use std::net::ToSocketAddrs; + +async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // Result<(), Box> + // using std::net to fetch a web page + let address = "example.com:80"; + + if case == 1 { + // create the connection + let mut stream = std::net::TcpStream::connect(address)?; + + // send request + let _ = stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n"); + + // read response + let mut buffer = vec![0; 32 * 1024]; + let _ = stream.read(&mut buffer); // $ MISSING: Alert[rust/summary/taint-sources] + + println!("data = {:?}", buffer); + sink(&buffer); // $ MISSING: hasTaintFlow + sink(buffer[0]); // $ MISSING: hasTaintFlow + + let buffer_string = String::from_utf8_lossy(&buffer); + println!("string = {}", buffer_string); + sink(buffer_string); // $ MISSING: hasTaintFlow + } else { + // create the connection + let sock_addr = address.to_socket_addrs().unwrap().next().unwrap(); + let mut stream = std::net::TcpStream::connect_timeout(&sock_addr, std::time::Duration::new(1, 0))?; + + // send request + let _ = stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n"); + + // read response + match case { + 2 => { + let mut reader = std::io::BufReader::new(stream).take(256); + let mut line = String::new(); + loop { + match reader.read_line(&mut line) { // $ MISSING: Alert[rust/summary/taint-sources] + Ok(0) => { + println!("end"); + break; + } + Ok(_n) => { + println!("line = {}", line); + sink(&line); // $ MISSING: hasTaintFlow + line.clear(); + } + Err(e) => { + println!("error: {}", e); + break; + } + } + } + } + 3 => { + let reader = std::io::BufReader::new(stream.try_clone()?).take(256); + for line in reader.lines() { // $ MISSING: Alert[rust/summary/taint-sources] + if let Ok(string) = line { + println!("line = {}", string); + sink(string); // $ MISSING: hasTaintFlow + } + } + } + _ => {} + } + } + + Ok(()) +} + +use tokio::io::AsyncWriteExt; + +async fn test_tokio_tcpstream() -> std::io::Result<()> { + // using tokio::io to fetch a web page + let address = "example.com:80"; + + // create the connection + println!("connecting to {}...", address); + let mut tokio_stream = tokio::net::TcpStream::connect(address).await?; + + // send request + tokio_stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n").await?; + + // read response + let mut buffer = vec![0; 32 * 1024]; + let n = tokio_stream.read(&mut buffer).await?; // $ MISSING: Alert[rust/summary/taint-sources] + + println!("data = {:?}", buffer); + sink(&buffer); // $ MISSING: hasTaintFlow + sink(buffer[0]); // $ MISSING: hasTaintFlow + + let buffer_string = String::from_utf8_lossy(&buffer[..n]); + println!("string = {}", buffer_string); + sink(buffer_string); // $ MISSING: hasTaintFlow + + Ok(()) +} + #[tokio::main] async fn main() -> Result<(), Box> { let case = std::env::args().nth(1).unwrap_or(String::from("1")).parse::().unwrap(); // $ Alert[rust/summary/taint-sources] @@ -572,5 +671,17 @@ async fn main() -> Result<(), Box> { Err(e) => println!("error: {}", e), } + println!("test_std_tcpstream..."); + match futures::executor::block_on(test_std_tcpstream(case)) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } + + println!("test_tokio_tcpstream..."); + match futures::executor::block_on(test_tokio_tcpstream()) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } + Ok(()) } From 38397195a258208b819e2a4f313decf9745a3be5 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:36:00 +0100 Subject: [PATCH 05/14] Rust: Add further source test cases for tokio. --- .../dataflow/sources/TaintSources.expected | 22 ++++++------ .../dataflow/sources/options.yml | 1 + .../library-tests/dataflow/sources/test.rs | 36 +++++++++++++++++++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index e34f7bbcd249..5ae527c9ff74 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -36,14 +36,14 @@ | test.rs:278:46:278:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:285:46:285:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:291:46:291:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:384:31:384:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:389:31:389:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:394:22:394:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:400:22:400:25 | path | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:401:27:401:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:407:22:407:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:417:20:417:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:451:21:451:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:452:21:452:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:460:21:460:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:621:16:621:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:403:31:403:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:408:31:408:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:413:22:413:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:419:22:419:25 | path | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:420:27:420:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:426:22:426:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:436:20:436:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:470:21:470:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:471:21:471:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:479:21:479:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:657:16:657:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/options.yml b/rust/ql/test/library-tests/dataflow/sources/options.yml index 9b4565f1e1ad..b48be615eb5f 100644 --- a/rust/ql/test/library-tests/dataflow/sources/options.yml +++ b/rust/ql/test/library-tests/dataflow/sources/options.yml @@ -7,3 +7,4 @@ qltest_dependencies: - http = { version = "1.2.0" } - tokio = { version = "1.43.0", features = ["full"] } - futures = { version = "0.3" } + - bytes = { version = "1.10.1" } diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 1dc573c5e3ac..71643f750ade 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -330,6 +330,25 @@ async fn test_tokio_stdin() -> Result<(), Box> { sink(&buffer); // $ MISSING: hasTaintFlow } + { + let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let v1 = stdin.read_u8().await?; + let v2 = stdin.read_i16().await?; + let v3 = stdin.read_f32().await?; + let v4 = stdin.read_i64_le().await?; + sink(v1); // $ MISSING: hasTaintFlow + sink(v2); // $ MISSING: hasTaintFlow + sink(v3); // $ MISSING: hasTaintFlow + sink(v4); // $ MISSING: hasTaintFlow + } + + { + let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut buffer = bytes::BytesMut::new(); + stdin.read_buf(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + // --- async reading from stdin (BufReader) --- { @@ -495,6 +514,23 @@ async fn test_tokio_file() -> std::io::Result<()> { sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" } + { + let v1 = file.read_u8().await?; + let v2 = file.read_i16().await?; + let v3 = file.read_f32().await?; + let v4 = file.read_i64_le().await?; + sink(v1); // $ MISSING: hasTaintFlow + sink(v2); // $ MISSING: hasTaintFlow + sink(v3); // $ MISSING: hasTaintFlow + sink(v4); // $ MISSING: hasTaintFlow + } + + { + let mut buffer = bytes::BytesMut::new(); + file.read_buf(&mut buffer).await?; + sink(&buffer); // $ MISSING: hasTaintFlow + } + // --- misc operations --- { From 950812b463bcc7dae9af5f0bceb4cbc6c22acd90 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:44:24 +0100 Subject: [PATCH 06/14] Rust: Add further source tests for tcp streams. --- .../dataflow/sources/TaintSources.expected | 2 +- .../library-tests/dataflow/sources/test.rs | 102 ++++++++++++++++-- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 5ae527c9ff74..ce929fd29f0f 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -46,4 +46,4 @@ | test.rs:470:21:470:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:471:21:471:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:479:21:479:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:657:16:657:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:739:16:739:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 71643f750ade..5a292c999d90 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -626,7 +626,7 @@ async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // Result<(), Bo use tokio::io::AsyncWriteExt; -async fn test_tokio_tcpstream() -> std::io::Result<()> { +async fn test_tokio_tcpstream(case: i64) -> std::io::Result<()> { // using tokio::io to fetch a web page let address = "example.com:80"; @@ -637,18 +637,100 @@ async fn test_tokio_tcpstream() -> std::io::Result<()> { // send request tokio_stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n").await?; + if case == 1 { + // peek response + let mut buffer1 = vec![0; 2 * 1024]; + let _ = tokio_stream.peek(&mut buffer1).await?; // $ MISSING: Alert[rust/summary/taint-sources] + + // read response + let mut buffer2 = vec![0; 2 * 1024]; + let n2 = tokio_stream.read(&mut buffer2).await?; // $ MISSING: Alert[rust/summary/taint-sources] + + println!("buffer1 = {:?}", buffer1); + sink(&buffer1); // $ MISSING: hasTaintFlow + sink(buffer1[0]); // $ MISSING: hasTaintFlow + + println!("buffer2 = {:?}", buffer2); + sink(&buffer2); // $ MISSING: hasTaintFlow + sink(buffer2[0]); // $ MISSING: hasTaintFlow + + let buffer_string = String::from_utf8_lossy(&buffer2[..n2]); + println!("string = {}", buffer_string); + sink(buffer_string); // $ MISSING: hasTaintFlow + } else if case == 2 { + let mut buffer = [0; 2 * 1024]; + loop { + match tokio_stream.try_read(&mut buffer) { + Ok(0) => { + println!("end"); + break; + } + Ok(_n) => { + println!("buffer = {:?}", buffer); + sink(&buffer); // $ MISSING: hasTaintFlow + break; // (or we could wait for more data) + } + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { + // wait... + continue; + } + Err(e) => { + println!("error: {}", e); + break; + } + } + } + } else { + let mut buffer = Vec::new(); + loop { + match tokio_stream.try_read_buf(&mut buffer) { + Ok(0) => { + println!("end"); + break; + } + Ok(_n) => { + println!("buffer = {:?}", buffer); + sink(&buffer); // $ MISSING: hasTaintFlow + break; // (or we could wait for more data) + } + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { + // wait... + continue; + } + Err(e) => { + println!("error: {}", e); + break; + } + } + } + } + + Ok(()) +} + +async fn test_std_to_tokio_tcpstream() -> std::io::Result<()> { + // using tokio::io to fetch a web page + let address = "example.com:80"; + + // create the connection + println!("connecting to {}...", address); + let std_stream = std::net::TcpStream::connect(address)?; + + // convert to tokio stream + std_stream.set_nonblocking(true)?; + let mut tokio_stream = tokio::net::TcpStream::from_std(std_stream)?; + + // send request + tokio_stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n").await?; + // read response let mut buffer = vec![0; 32 * 1024]; - let n = tokio_stream.read(&mut buffer).await?; // $ MISSING: Alert[rust/summary/taint-sources] + let _n = tokio_stream.read(&mut buffer).await?; // $ MISSING: Alert[rust/summary/taint-sources] println!("data = {:?}", buffer); sink(&buffer); // $ MISSING: hasTaintFlow sink(buffer[0]); // $ MISSING: hasTaintFlow - let buffer_string = String::from_utf8_lossy(&buffer[..n]); - println!("string = {}", buffer_string); - sink(buffer_string); // $ MISSING: hasTaintFlow - Ok(()) } @@ -714,7 +796,13 @@ async fn main() -> Result<(), Box> { } println!("test_tokio_tcpstream..."); - match futures::executor::block_on(test_tokio_tcpstream()) { + match futures::executor::block_on(test_tokio_tcpstream(case)) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } + + println!("test_std_to_tokio_tcpstream..."); + match futures::executor::block_on(test_std_to_tokio_tcpstream()) { Ok(_) => println!("complete"), Err(e) => println!("error: {}", e), } From b2339ef0d90550df936188dbceaad3a97414bc37 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:25:21 +0100 Subject: [PATCH 07/14] Rust: Add some alternative sinks. --- .../dataflow/sources/TaintSources.expected | 54 +++++++++---------- .../library-tests/dataflow/sources/test.rs | 6 ++- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index ce929fd29f0f..05ae13cb2ceb 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -20,30 +20,30 @@ | 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). | -| test.rs:112:31:112:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:119:31:119:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | -| test.rs:209:22:209:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:215:22:215:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:221:22:221:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:227:22:227:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:233:9:233:22 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:237:17:237:30 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:244:50:244:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:250:46:250:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:257:50:257:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:264:50:264:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:271:56:271:69 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:278:46:278:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:285:46:285:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:291:46:291:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | -| test.rs:403:31:403:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:408:31:408:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:413:22:413:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:419:22:419:25 | path | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:420:27:420:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:426:22:426:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:436:20:436:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:470:21:470:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:471:21:471:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:479:21:479:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:739:16:739:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:113:31:113:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:120:31:120:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:210:22:210:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:216:22:216:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:222:22:222:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:228:22:228:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:234:9:234:22 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:238:17:238:30 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:245:50:245:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:251:46:251:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:258:50:258:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:265:50:265:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:272:56:272:69 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:280:46:280:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:287:46:287:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:293:46:293:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:407:31:407:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:412:31:412:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:417:22:417:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:423:22:423:25 | path | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:424:27:424:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:430:22:430:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:440:20:440:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:474:21:474:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:475:21:475:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:483:21:483:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:743:16:743:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 5a292c999d90..0345871a8e30 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -78,6 +78,7 @@ async fn test_reqwest() -> Result<(), reqwest::Error> { sink(remote_string6); // $ MISSING: hasTaintFlow let mut request1 = reqwest::get("example.com").await?; // $ Alert[rust/summary/taint-sources] + sink(request1.chunk().await?.unwrap()); // $ MISSING: hasTaintFlow while let Some(chunk) = request1.chunk().await? { sink(chunk); // $ MISSING: hasTaintFlow } @@ -269,6 +270,7 @@ fn test_io_stdin() -> std::io::Result<()> { { let mut reader_split = std::io::BufReader::new(std::io::stdin()).split(b','); // $ Alert[rust/summary/taint-sources] + sink(reader_split.next().unwrap().unwrap()); // $ MISSING: hasTaintFlow while let Some(chunk) = reader_split.next() { sink(chunk.unwrap()); // $ MISSING: hasTaintFlow } @@ -380,6 +382,7 @@ async fn test_tokio_stdin() -> Result<(), Box> { { let mut reader_split = tokio::io::BufReader::new(tokio::io::stdin()).split(b','); // $ MISSING: Alert[rust/summary/taint-sources] + sink(reader_split.next_segment().await?.unwrap()); // $ MISSING: hasTaintFlow while let Some(chunk) = reader_split.next_segment().await? { sink(chunk); // $ MISSING: hasTaintFlow } @@ -388,8 +391,9 @@ async fn test_tokio_stdin() -> Result<(), Box> { { let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] let mut lines = reader.lines(); + sink(lines.next_line().await?.unwrap()); // $ MISSING: hasTaintFlow while let Some(line) = lines.next_line().await? { - sink(line); // $ hasTai + sink(line); // $ MISSING: hasTaintFlow } } From 627496df094bcc2d36b01cbdb7bd1b8bab3ed15c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:46:13 +0100 Subject: [PATCH 08/14] Rust: Add source tests for tokio (fs). --- .../dataflow/sources/TaintSources.expected | 10 ++--- .../library-tests/dataflow/sources/test.rs | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 05ae13cb2ceb..c64e6a369a5b 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -42,8 +42,8 @@ | test.rs:423:22:423:25 | path | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:424:27:424:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:430:22:430:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:440:20:440:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:474:21:474:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:475:21:475:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:483:21:483:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | -| test.rs:743:16:743:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test.rs:472:20:472:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:506:21:506:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:507:21:507:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:515:21:515:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:775:16:775:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 0345871a8e30..e8d8d65a3a79 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -434,6 +434,38 @@ fn test_fs() -> Result<(), Box> { Ok(()) } +async fn test_tokio_fs() -> Result<(), Box> { + { + let buffer: Vec = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources] + sink(buffer); // $ MISSING: hasTaintFlow="file.bin" + } + + { + let buffer: Vec = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources] + sink(buffer); // $ MISSING: hasTaintFlow="file.bin" + } + + { + let buffer = tokio::fs::read_to_string("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + sink(buffer); // $ MISSING: hasTaintFlow="file.txt" + } + + let mut read_dir = tokio::fs::read_dir("directory").await?; + for entry in read_dir.next_entry().await? { + let path = entry.path(); // $ MISSING: Alert[rust/summary/taint-sources] + let file_name = entry.file_name(); // $ MISSING: Alert[rust/summary/taint-sources] + sink(path); // $ MISSING: hasTaintFlow + sink(file_name); // $ MISSING: hasTaintFlow + } + + { + let target = tokio::fs::read_link("symlink.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + sink(target); // $ MISSING: hasTaintFlow="symlink.txt" + } + + Ok(()) +} + fn test_io_file() -> std::io::Result<()> { // --- file --- @@ -781,6 +813,12 @@ async fn main() -> Result<(), Box> { Err(e) => println!("error: {}", e), } + println!("test_tokio_fs..."); + match futures::executor::block_on(test_tokio_fs()) { + Ok(_) => println!("complete"), + Err(e) => println!("error: {}", e), + } + println!("test_io_file..."); match test_io_file() { Ok(_) => println!("complete"), From 7439b0c50486ccee104b97e7efefc29c4c383de9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:52:10 +0100 Subject: [PATCH 09/14] Rust: Add models for tokio (io). --- .../codeql/rust/frameworks/tokio/io.model.yml | 48 ++++++++++++++++ .../dataflow/sources/TaintSources.expected | 12 ++++ .../library-tests/dataflow/sources/test.rs | 56 +++++++++---------- 3 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml new file mode 100644 index 000000000000..ab0e88a9d610 --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml @@ -0,0 +1,48 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::stdin::stdin", "ReturnValue", "stdin", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: summaryModel + data: + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::new", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::fill_buf", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::buffer", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::split", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::next_segment", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::lines", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::next_line", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_buf", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u8", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u8_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u16", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u16_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u32", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u32_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u64", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u64_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u128", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u128_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i8", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i8_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i16", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i16_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i32", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i32_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i64", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i64_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i128", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i128_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f32", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f32_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f64", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f64_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index c64e6a369a5b..1f7357f7e03e 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -36,6 +36,18 @@ | test.rs:280:46:280:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:287:46:287:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:293:46:293:59 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:308:25:308:40 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:315:25:315:40 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:322:25:322:40 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:329:25:329:40 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:336:25:336:40 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:348:25:348:40 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:357:52:357:67 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:363:48:363:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:370:52:370:67 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:377:52:377:67 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:384:58:384:73 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | +| test.rs:392:48:392:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:407:31:407:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:412:31:412:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:417:22:417:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index e8d8d65a3a79..2c87a05a4744 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -305,93 +305,93 @@ async fn test_tokio_stdin() -> Result<(), Box> { // --- async reading from stdin --- { - let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources] let mut buffer = [0u8; 100]; let _bytes = stdin.read(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { - let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources] let mut buffer = Vec::::new(); let _bytes = stdin.read_to_end(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { - let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources] let mut buffer = String::new(); let _bytes = stdin.read_to_string(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { - let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources] let mut buffer = [0; 100]; stdin.read_exact(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { - let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources] let v1 = stdin.read_u8().await?; let v2 = stdin.read_i16().await?; let v3 = stdin.read_f32().await?; let v4 = stdin.read_i64_le().await?; - sink(v1); // $ MISSING: hasTaintFlow - sink(v2); // $ MISSING: hasTaintFlow - sink(v3); // $ MISSING: hasTaintFlow - sink(v4); // $ MISSING: hasTaintFlow + sink(v1); // $ hasTaintFlow + sink(v2); // $ hasTaintFlow + sink(v3); // $ hasTaintFlow + sink(v4); // $ hasTaintFlow } { - let mut stdin = tokio::io::stdin(); // $ MISSING: Alert[rust/summary/taint-sources] + let mut stdin = tokio::io::stdin(); // $ Alert[rust/summary/taint-sources] let mut buffer = bytes::BytesMut::new(); stdin.read_buf(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } // --- async reading from stdin (BufReader) --- { - let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources] let data = reader.fill_buf().await?; - sink(&data); // $ MISSING: hasTaintFlow + sink(&data); // $ hasTaintFlow } { - let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources] let data = reader.buffer(); - sink(&data); // $ MISSING: hasTaintFlow + sink(&data); // $ hasTaintFlow } { let mut buffer = String::new(); - let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources] reader.read_line(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { let mut buffer = Vec::::new(); - let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let mut reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources] reader.read_until(b',', &mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow - sink(buffer[0]); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow + sink(buffer[0]); // $ hasTaintFlow } { - let mut reader_split = tokio::io::BufReader::new(tokio::io::stdin()).split(b','); // $ MISSING: Alert[rust/summary/taint-sources] - sink(reader_split.next_segment().await?.unwrap()); // $ MISSING: hasTaintFlow + let mut reader_split = tokio::io::BufReader::new(tokio::io::stdin()).split(b','); // $ Alert[rust/summary/taint-sources] + sink(reader_split.next_segment().await?.unwrap()); // $ hasTaintFlow while let Some(chunk) = reader_split.next_segment().await? { sink(chunk); // $ MISSING: hasTaintFlow } } { - let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ MISSING: Alert[rust/summary/taint-sources] + let reader = tokio::io::BufReader::new(tokio::io::stdin()); // $ Alert[rust/summary/taint-sources] let mut lines = reader.lines(); - sink(lines.next_line().await?.unwrap()); // $ MISSING: hasTaintFlow + sink(lines.next_line().await?.unwrap()); // $ hasTaintFlow while let Some(line) = lines.next_line().await? { sink(line); // $ MISSING: hasTaintFlow } From f4ae2110190b472f7fb631317707fc8b14197a2b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:54:59 +0100 Subject: [PATCH 10/14] Rust: Add models for tokio (fs). --- .../codeql/rust/frameworks/tokio/fs.model.yml | 11 ++++ .../codeql/rust/frameworks/tokio/io.model.yml | 3 ++ .../dataflow/sources/TaintSources.expected | 10 ++++ .../library-tests/dataflow/sources/test.rs | 54 +++++++++---------- 4 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/frameworks/tokio/fs.model.yml diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio/fs.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio/fs.model.yml new file mode 100644 index 000000000000..caa108de2b59 --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/tokio/fs.model.yml @@ -0,0 +1,11 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::fs::read::read", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "file", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::fs::read_to_string::read_to_string", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "file", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::fs::read_link::read_link", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "file", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::path", "ReturnValue", "file", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::file_name", "ReturnValue", "file", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::open", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "file", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml index ab0e88a9d610..ecfcb1b241b2 100644 --- a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml @@ -46,3 +46,6 @@ extensions: - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f32_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f64", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f64_le", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::chain", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::chain", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::take", "Argument[self]", "ReturnValue", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 1f7357f7e03e..88377ddf8237 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -54,8 +54,18 @@ | test.rs:423:22:423:25 | path | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:424:27:424:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:430:22:430:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:439:31:439:45 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:444:31:444:45 | ...::read | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:449:22:449:46 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:455:26:455:29 | path | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:456:31:456:39 | file_name | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:462:22:462:41 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:472:20:472:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:506:21:506:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:507:21:507:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:515:21:515:39 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:527:20:527:40 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:574:21:574:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:575:21:575:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:583:21:583:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:775:16:775:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 2c87a05a4744..3d511531c3bb 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -436,31 +436,31 @@ fn test_fs() -> Result<(), Box> { async fn test_tokio_fs() -> Result<(), Box> { { - let buffer: Vec = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources] - sink(buffer); // $ MISSING: hasTaintFlow="file.bin" + let buffer: Vec = tokio::fs::read("file.bin").await?; // $ Alert[rust/summary/taint-sources] + sink(buffer); // $ hasTaintFlow="file.bin" } { - let buffer: Vec = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources] - sink(buffer); // $ MISSING: hasTaintFlow="file.bin" + let buffer: Vec = tokio::fs::read("file.bin").await?; // $ Alert[rust/summary/taint-sources] + sink(buffer); // $ hasTaintFlow="file.bin" } { - let buffer = tokio::fs::read_to_string("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] - sink(buffer); // $ MISSING: hasTaintFlow="file.txt" + let buffer = tokio::fs::read_to_string("file.txt").await?; // $ Alert[rust/summary/taint-sources] + sink(buffer); // $ hasTaintFlow="file.txt" } let mut read_dir = tokio::fs::read_dir("directory").await?; for entry in read_dir.next_entry().await? { - let path = entry.path(); // $ MISSING: Alert[rust/summary/taint-sources] - let file_name = entry.file_name(); // $ MISSING: Alert[rust/summary/taint-sources] - sink(path); // $ MISSING: hasTaintFlow - sink(file_name); // $ MISSING: hasTaintFlow + let path = entry.path(); // $ Alert[rust/summary/taint-sources] + let file_name = entry.file_name(); // $ Alert[rust/summary/taint-sources] + sink(path); // $ hasTaintFlow + sink(file_name); // $ hasTaintFlow } { - let target = tokio::fs::read_link("symlink.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] - sink(target); // $ MISSING: hasTaintFlow="symlink.txt" + let target = tokio::fs::read_link("symlink.txt").await?; // $ Alert[rust/summary/taint-sources] + sink(target); // $ hasTaintFlow="symlink.txt" } Ok(()) @@ -524,30 +524,30 @@ fn test_io_file() -> std::io::Result<()> { async fn test_tokio_file() -> std::io::Result<()> { // --- file --- - let mut file = tokio::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + let mut file = tokio::fs::File::open("file.txt").await?; // $ Alert[rust/summary/taint-sources] { let mut buffer = [0u8; 100]; let _bytes = file.read(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + sink(&buffer); // $ hasTaintFlow="file.txt" } { let mut buffer = Vec::::new(); let _bytes = file.read_to_end(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + sink(&buffer); // $ hasTaintFlow="file.txt" } { let mut buffer = String::new(); let _bytes = file.read_to_string(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + sink(&buffer); // $ hasTaintFlow="file.txt" } { let mut buffer = [0; 100]; file.read_exact(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + sink(&buffer); // $ hasTaintFlow="file.txt" } { @@ -555,35 +555,35 @@ async fn test_tokio_file() -> std::io::Result<()> { let v2 = file.read_i16().await?; let v3 = file.read_f32().await?; let v4 = file.read_i64_le().await?; - sink(v1); // $ MISSING: hasTaintFlow - sink(v2); // $ MISSING: hasTaintFlow - sink(v3); // $ MISSING: hasTaintFlow - sink(v4); // $ MISSING: hasTaintFlow + sink(v1); // $ hasTaintFlow="file.txt" + sink(v2); // $ hasTaintFlow="file.txt" + sink(v3); // $ hasTaintFlow="file.txt" + sink(v4); // $ hasTaintFlow="file.txt" } { let mut buffer = bytes::BytesMut::new(); file.read_buf(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow="file.txt" } // --- misc operations --- { let mut buffer = String::new(); - let file1 = tokio::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] - let file2 = tokio::fs::File::open("another_file.txt").await?; // $ MISSING: [rust/summary/taint-sources] + let file1 = tokio::fs::File::open("file.txt").await?; // $ Alert[rust/summary/taint-sources] + let file2 = tokio::fs::File::open("another_file.txt").await?; // $ Alert[rust/summary/taint-sources] let mut reader = file1.chain(file2); reader.read_to_string(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" hasTaintFlow="another_file.txt" + sink(&buffer); // $ hasTaintFlow="file.txt" hasTaintFlow="another_file.txt" } { let mut buffer = String::new(); - let file1 = tokio::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources] + let file1 = tokio::fs::File::open("file.txt").await?; // $ Alert[rust/summary/taint-sources] let mut reader = file1.take(100); reader.read_to_string(&mut buffer).await?; - sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" + sink(&buffer); // $ hasTaintFlow="file.txt" } Ok(()) From 3104dba09e1bb2cabdc74ad2fd82c105c4652961 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:23:42 +0100 Subject: [PATCH 11/14] Rust: Fix some shortcomings in our models of Reqwest. --- .../ql/lib/codeql/rust/frameworks/reqwest.model.yml | 13 ++++++++----- rust/ql/test/library-tests/dataflow/sources/test.rs | 8 ++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml b/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml index 3be832c8e7fb..f954d4ce7cce 100644 --- a/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml @@ -3,7 +3,7 @@ extensions: pack: codeql/rust-all extensible: sourceModel data: - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::get", "ReturnValue.Field[crate::result::Result::Ok(0)]", "remote", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::get", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "remote", "manual"] - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::blocking::get", "ReturnValue.Field[crate::result::Result::Ok(0)]", "remote", "manual"] - addsTo: pack: codeql/rust-all @@ -15,10 +15,13 @@ extensions: pack: codeql/rust-all extensible: summaryModel data: - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text_with_charset", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::chunk", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text_with_charset", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::chunk", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]", "taint", "manual"] - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text_with_charset", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::chunk", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)]", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 3d511531c3bb..8e87cf8e5cca 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -72,15 +72,15 @@ async fn test_reqwest() -> Result<(), reqwest::Error> { sink(remote_string4); // $ hasTaintFlow="example.com" let remote_string5 = reqwest::get("example.com").await?.text().await?; // $ Alert[rust/summary/taint-sources] - sink(remote_string5); // $ MISSING: hasTaintFlow + sink(remote_string5); // $ hasTaintFlow="example.com" let remote_string6 = reqwest::get("example.com").await?.bytes().await?; // $ Alert[rust/summary/taint-sources] - sink(remote_string6); // $ MISSING: hasTaintFlow + sink(remote_string6); // $ hasTaintFlow="example.com" let mut request1 = reqwest::get("example.com").await?; // $ Alert[rust/summary/taint-sources] - sink(request1.chunk().await?.unwrap()); // $ MISSING: hasTaintFlow + sink(request1.chunk().await?.unwrap()); // $ hasTaintFlow="example.com" while let Some(chunk) = request1.chunk().await? { - sink(chunk); // $ MISSING: hasTaintFlow + sink(chunk); // $ MISSING: hasTaintFlow="example.com" } Ok(()) From 038b8b5344fc9303071b9160c47a61e4ab677781 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:30:25 +0100 Subject: [PATCH 12/14] Rust: Add a missing model for std::io. --- rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml | 1 + rust/ql/test/library-tests/dataflow/sources/test.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml index 3cdbb911b5b8..e6b75aeb8d32 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml @@ -36,3 +36,4 @@ extensions: - ["lang:std", "crate::io::Read::chain", "Argument[0]", "ReturnValue", "taint", "manual"] - ["lang:std", "crate::io::Read::take", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:std", "::lock", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["lang:std", "::next", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::result::Result::Ok(0)]", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 8e87cf8e5cca..8c4808605b45 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -270,7 +270,7 @@ fn test_io_stdin() -> std::io::Result<()> { { let mut reader_split = std::io::BufReader::new(std::io::stdin()).split(b','); // $ Alert[rust/summary/taint-sources] - sink(reader_split.next().unwrap().unwrap()); // $ MISSING: hasTaintFlow + sink(reader_split.next().unwrap().unwrap()); // $ hasTaintFlow while let Some(chunk) = reader_split.next() { sink(chunk.unwrap()); // $ MISSING: hasTaintFlow } From e26311645296f2f0b8d0800a9386961380adffa4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:58:21 +0100 Subject: [PATCH 13/14] Rust: Model std::net and tokio::net. --- .../rust/frameworks/stdlib/net.model.yml | 16 +++++++++ .../rust/frameworks/tokio/net.model.yml | 14 ++++++++ .../dataflow/sources/TaintSources.expected | 5 +++ .../library-tests/dataflow/sources/test.rs | 36 +++++++++---------- 4 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml create mode 100644 rust/ql/lib/codeql/rust/frameworks/tokio/net.model.yml diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml new file mode 100644 index 000000000000..c088c11e7b6c --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + - ["lang:std", "::connect", "ReturnValue.Field[crate::result::Result::Ok(0)]", "remote", "manual"] + - ["lang:std", "::connect_timeout", "ReturnValue.Field[crate::result::Result::Ok(0)]", "remote", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: summaryModel + data: + - ["lang:std", "::try_clone", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] + - ["lang:std", "::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["lang:std", "::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio/net.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio/net.model.yml new file mode 100644 index 000000000000..8c9d278818bb --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/tokio/net.model.yml @@ -0,0 +1,14 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::connect", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "remote", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: summaryModel + data: + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::peek", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::try_read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["repo:https://github.com/tokio-rs/tokio:tokio", "::try_read_buf", "Argument[self]", "Argument[0].Reference", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 88377ddf8237..1fd8944790a8 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -20,6 +20,7 @@ | 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). | +| test.rs:99:18:99:47 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:113:31:113:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:120:31:120:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:210:22:210:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | @@ -68,4 +69,8 @@ | test.rs:574:21:574:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:575:21:575:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:583:21:583:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | +| test.rs:600:26:600:53 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:619:26:619:61 | ...::connect_timeout | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:671:28:671:57 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:753:22:753:49 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:775:16:775:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 8c4808605b45..066f83a64748 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -96,7 +96,7 @@ async fn test_hyper_http(case: i64) -> Result<(), Box> { // create the connection println!("connecting to {}...", address); - let stream = tokio::net::TcpStream::connect(address).await?; + let stream = tokio::net::TcpStream::connect(address).await?; // $ Alert[rust/summary/taint-sources] let io = hyper_util::rt::TokioIo::new(stream); let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?; @@ -597,18 +597,18 @@ async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // Result<(), Bo if case == 1 { // create the connection - let mut stream = std::net::TcpStream::connect(address)?; + let mut stream = std::net::TcpStream::connect(address)?; // $ Alert[rust/summary/taint-sources] // send request let _ = stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n"); // read response let mut buffer = vec![0; 32 * 1024]; - let _ = stream.read(&mut buffer); // $ MISSING: Alert[rust/summary/taint-sources] + let _ = stream.read(&mut buffer); println!("data = {:?}", buffer); - sink(&buffer); // $ MISSING: hasTaintFlow - sink(buffer[0]); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow=address + sink(buffer[0]); // $ hasTaintFlow=address let buffer_string = String::from_utf8_lossy(&buffer); println!("string = {}", buffer_string); @@ -616,7 +616,7 @@ async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // Result<(), Bo } else { // create the connection let sock_addr = address.to_socket_addrs().unwrap().next().unwrap(); - let mut stream = std::net::TcpStream::connect_timeout(&sock_addr, std::time::Duration::new(1, 0))?; + let mut stream = std::net::TcpStream::connect_timeout(&sock_addr, std::time::Duration::new(1, 0))?; // $ Alert[rust/summary/taint-sources] // send request let _ = stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n"); @@ -627,14 +627,14 @@ async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // Result<(), Bo let mut reader = std::io::BufReader::new(stream).take(256); let mut line = String::new(); loop { - match reader.read_line(&mut line) { // $ MISSING: Alert[rust/summary/taint-sources] + match reader.read_line(&mut line) { Ok(0) => { println!("end"); break; } Ok(_n) => { println!("line = {}", line); - sink(&line); // $ MISSING: hasTaintFlow + sink(&line); // $ hasTaintFlow=&sock_addr line.clear(); } Err(e) => { @@ -668,7 +668,7 @@ async fn test_tokio_tcpstream(case: i64) -> std::io::Result<()> { // create the connection println!("connecting to {}...", address); - let mut tokio_stream = tokio::net::TcpStream::connect(address).await?; + let mut tokio_stream = tokio::net::TcpStream::connect(address).await?; // $ Alert[rust/summary/taint-sources] // send request tokio_stream.write_all(b"GET / HTTP/1.1\nHost:example.com\n\n").await?; @@ -676,19 +676,19 @@ async fn test_tokio_tcpstream(case: i64) -> std::io::Result<()> { if case == 1 { // peek response let mut buffer1 = vec![0; 2 * 1024]; - let _ = tokio_stream.peek(&mut buffer1).await?; // $ MISSING: Alert[rust/summary/taint-sources] + let _ = tokio_stream.peek(&mut buffer1).await?; // read response let mut buffer2 = vec![0; 2 * 1024]; - let n2 = tokio_stream.read(&mut buffer2).await?; // $ MISSING: Alert[rust/summary/taint-sources] + let n2 = tokio_stream.read(&mut buffer2).await?; println!("buffer1 = {:?}", buffer1); - sink(&buffer1); // $ MISSING: hasTaintFlow - sink(buffer1[0]); // $ MISSING: hasTaintFlow + sink(&buffer1); // $ hasTaintFlow=address + sink(buffer1[0]); // $ hasTaintFlow=address println!("buffer2 = {:?}", buffer2); - sink(&buffer2); // $ MISSING: hasTaintFlow - sink(buffer2[0]); // $ MISSING: hasTaintFlow + sink(&buffer2); // $ hasTaintFlow=address + sink(buffer2[0]); // $ hasTaintFlow=address let buffer_string = String::from_utf8_lossy(&buffer2[..n2]); println!("string = {}", buffer_string); @@ -703,7 +703,7 @@ async fn test_tokio_tcpstream(case: i64) -> std::io::Result<()> { } Ok(_n) => { println!("buffer = {:?}", buffer); - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow=address break; // (or we could wait for more data) } Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { @@ -726,7 +726,7 @@ async fn test_tokio_tcpstream(case: i64) -> std::io::Result<()> { } Ok(_n) => { println!("buffer = {:?}", buffer); - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow=address break; // (or we could wait for more data) } Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { @@ -750,7 +750,7 @@ async fn test_std_to_tokio_tcpstream() -> std::io::Result<()> { // create the connection println!("connecting to {}...", address); - let std_stream = std::net::TcpStream::connect(address)?; + let std_stream = std::net::TcpStream::connect(address)?; // $ Alert[rust/summary/taint-sources] // convert to tokio stream std_stream.set_nonblocking(true)?; From 3789c46791d3e1db484ca2fb5a2b6f38d42630ba Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 May 2025 15:40:32 +0100 Subject: [PATCH 14/14] Rust: Remove stray comment, accept changes to another test. --- .../dataflow/local/DataFlowStep.expected | 94 ++++++++++++++++++- .../library-tests/dataflow/sources/test.rs | 2 +- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index d9f17dbf4c4d..a28d5f7c20cc 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -892,11 +892,24 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read_exact | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read_to_string | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read_exact | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read_to_end | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::::read_to_string | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::BufRead::read_line | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::BufRead::read_line | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read_exact | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read_to_end | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read_to_string | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::::peek | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::::peek | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::::try_read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::::try_read | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::::try_read_buf | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::::try_read_buf | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_line | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_line | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_buf | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_buf | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_exact | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_to_end | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_to_string | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference.Reference in lang:proc_macro::_::<&[u8] as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<&[u8] as crate::bridge::rpc::DecodeMut>::decode | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference.Reference in lang:proc_macro::_::::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::::decode | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference.Reference in lang:proc_macro::_::::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::::decode | @@ -913,6 +926,7 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:std::_::::wait_while | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:std::_::::wait_while | | file://:0:0:0:0 | [summary] to write: Argument[1].Reference in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | &ref | file://:0:0:0:0 | [post] [summary param] 1 in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | | file://:0:0:0:0 | [summary] to write: Argument[1].Reference in lang:std::_::crate::io::BufRead::read_until | &ref | file://:0:0:0:0 | [post] [summary param] 1 in lang:std::_::crate::io::BufRead::read_until | +| file://:0:0:0:0 | [summary] to write: Argument[1].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_until | &ref | file://:0:0:0:0 | [post] [summary param] 1 in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_until | | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::max_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::max_by | | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::max_by_key | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::max_by_key | | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::min_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::min_by | @@ -1051,6 +1065,7 @@ storeStep | 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)] in lang:proc_macro::_::::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:proc_macro::_::::next | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::next | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::map | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::map | | 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 | @@ -1060,6 +1075,7 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[1] in lang:core::_::::matching | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::matching | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::result::Result::Err(0)] in lang:core::_::::transpose | Err | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::result::Result::Ok(0)] in lang:std::_::::next | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::::next | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Reference in lang:core::_::::from | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::from | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Reference in lang:core::_::::as_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::as_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Reference in lang:core::_::::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::as_ref | @@ -1143,6 +1159,7 @@ storeStep | 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 lang:std::_::<&[u8] as crate::io::BufRead>::fill_buf | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<&[u8] as crate::io::BufRead>::fill_buf | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::fill_buf | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::fill_buf | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::try_clone | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::try_clone | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::canonicalize | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::canonicalize | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::wait | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::wait_timeout | @@ -1154,10 +1171,6 @@ storeStep | 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 | -| 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::_::::chunk | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | -| 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 | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/servo/rust-url:url::_::::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/servo/rust-url:url::_::::parse | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:alloc::_::::search_tree_for_bifurcation | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::search_tree_for_bifurcation | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:core::_::::extend | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::extend | @@ -1166,10 +1179,81 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::::wait_timeout_ms | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout_ms | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::::wait_timeout_while | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout_while | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | -| 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 | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::try_insert | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_insert | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::as_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::as_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::as_ref | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | future | 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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | future | 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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | future | 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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | future | 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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_line | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_line | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_segment | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_segment | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::fill_buf | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::fill_buf | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128 | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128_le | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::bytes | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.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.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::text_with_charset | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_line | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_line | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_segment | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_segment | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::fill_buf | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_buf_read_ext::AsyncBufReadExt::fill_buf | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f32_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_f64_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i8_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i16_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i32_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i64_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_i128_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u8_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u16_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u32_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u64_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128 | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128 | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128_le | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::crate::io::util::async_read_ext::AsyncReadExt::read_u128_le | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_line | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_line | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_segment | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Future.Field[crate::result::Result::Ok(0)] in repo:https://github.com/tokio-rs/tokio:tokio::_::::next_segment | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::borrow_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::borrow_mut | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 066f83a64748..e2cea47b95b3 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -591,7 +591,7 @@ async fn test_tokio_file() -> std::io::Result<()> { use std::net::ToSocketAddrs; -async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // Result<(), Box> +async fn test_std_tcpstream(case: i64) -> std::io::Result<()> { // using std::net to fetch a web page let address = "example.com:80";