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/17] 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<dyn std::error::Error>> {
 
     // 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<dyn std::error::Error>> {
     Ok(())
 }
 
-use std::fs;
-
-fn test_fs() -> Result<(), Box<dyn std::error::Error>> {
-    {
-        let buffer: Vec<u8> = std::fs::read("file.bin")?; // $ Alert[rust/summary/taint-sources]
-        sink(buffer); // $ hasTaintFlow="file.bin"
-    }
-
-    {
-        let buffer: Vec<u8> = 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::<u8>::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::<u8>::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<dyn std::error::Error>> {
+    {
+        let buffer: Vec<u8> = std::fs::read("file.bin")?; // $ Alert[rust/summary/taint-sources]
+        sink(buffer); // $ hasTaintFlow="file.bin"
+    }
+
+    {
+        let buffer: Vec<u8> = 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::<u8>::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<dyn std::error::Error>> {
     let case = std::env::args().nth(1).unwrap_or(String::from("1")).parse::<i64>().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/17] 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<dyn std::error::Error>> {
+
+    // --- 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::<u8>::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::<u8>::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<dyn std::error::Error>> {
@@ -414,6 +495,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     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/17] 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::<u8>::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<dyn std::error::Error>> {
     let case = std::env::args().nth(1).unwrap_or(String::from("1")).parse::<i64>().unwrap(); // $ Alert[rust/summary/taint-sources]
@@ -515,5 +566,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
         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/17] 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<dyn Error>>
+    // 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<dyn std::error::Error>> {
     let case = std::env::args().nth(1).unwrap_or(String::from("1")).parse::<i64>().unwrap(); // $ Alert[rust/summary/taint-sources]
@@ -572,5 +671,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
         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/17] 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<dyn std::error::Error>> {
         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/17] 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<dyn std::error::Error>> {
     }
 
     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/17] 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<dyn std::error::Error>> {
 
     {
         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<dyn std::error::Error>> {
     {
         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/17] 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<dyn std::error::Error>> {
     Ok(())
 }
 
+async fn test_tokio_fs() -> Result<(), Box<dyn std::error::Error>> {
+    {
+        let buffer: Vec<u8> = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources]
+        sink(buffer); // $ MISSING: hasTaintFlow="file.bin"
+    }
+
+    {
+        let buffer: Vec<u8> = 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<dyn std::error::Error>> {
         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/17] 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", "<crate::io::util::buf_reader::BufReader>::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", "<crate::io::util::buf_reader::BufReader>::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", "<crate::io::util::split::Split>::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", "<crate::io::util::lines::Lines>::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<dyn std::error::Error>> {
     // --- 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::<u8>::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::<u8>::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/17] 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", "<crate::fs::read_dir::DirEntry>::path", "ReturnValue", "file", "manual"]
+      - ["repo:https://github.com/tokio-rs/tokio:tokio", "<crate::fs::read_dir::DirEntry>::file_name", "ReturnValue", "file", "manual"]
+      - ["repo:https://github.com/tokio-rs/tokio:tokio", "<crate::fs::file::File>::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<dyn std::error::Error>> {
 
 async fn test_tokio_fs() -> Result<(), Box<dyn std::error::Error>> {
     {
-        let buffer: Vec<u8> = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources]
-        sink(buffer); // $ MISSING: hasTaintFlow="file.bin"
+        let buffer: Vec<u8> = tokio::fs::read("file.bin").await?; // $ Alert[rust/summary/taint-sources]
+        sink(buffer); // $ hasTaintFlow="file.bin"
     }
 
     {
-        let buffer: Vec<u8> = tokio::fs::read("file.bin").await?; // $ MISSING: Alert[rust/summary/taint-sources]
-        sink(buffer); // $ MISSING: hasTaintFlow="file.bin"
+        let buffer: Vec<u8> = 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::<u8>::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/17] 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", "<crate::response::Response>::text", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
-      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
-      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::bytes", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
-      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::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", "<crate::response::Response>::text", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::bytes", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::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", "<crate::blocking::response::Response>::text", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
       - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::blocking::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
       - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::blocking::response::Response>::bytes", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::async_impl::response::Response>::text", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::async_impl::response::Response>::bytes", "Argument[self]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::async_impl::response::Response>::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/17] 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", "<crate::io::stdio::Stdin>::lock", "Argument[self]", "ReturnValue", "taint", "manual"]
+      - ["lang:std", "<crate::io::Split as crate::iter::traits::iterator::Iterator>::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/17] 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", "<crate::net::tcp::TcpStream>::connect", "ReturnValue.Field[crate::result::Result::Ok(0)]", "remote", "manual"]
+      - ["lang:std", "<crate::net::tcp::TcpStream>::connect_timeout", "ReturnValue.Field[crate::result::Result::Ok(0)]", "remote", "manual"]
+  - addsTo:
+      pack: codeql/rust-all
+      extensible: summaryModel
+    data:
+      - ["lang:std", "<crate::net::tcp::TcpStream>::try_clone", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+      - ["lang:std", "<crate::net::tcp::TcpStream as crate::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
+      - ["lang:std", "<crate::net::tcp::TcpStream as crate::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
+      - ["lang:std", "<crate::net::tcp::TcpStream as crate::io::Read>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
+      - ["lang:std", "<crate::net::tcp::TcpStream as crate::io::Read>::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", "<crate::net::tcp::stream::TcpStream>::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", "<crate::net::tcp::stream::TcpStream>::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", "<crate::net::tcp::stream::TcpStream>::try_read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
+      - ["repo:https://github.com/tokio-rs/tokio:tokio", "<crate::net::tcp::stream::TcpStream>::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<dyn std::error::Error>> {
 
     // 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/17] 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::_::<crate::io::stdio::StdinLock as crate::io::Read>::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read |
 | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_exact |
 | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_to_string |
+| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read |
+| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read_exact |
+| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read_to_end |
+| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::net::tcp::TcpStream as crate::io::Read>::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::_::<crate::net::tcp::stream::TcpStream>::peek | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::net::tcp::stream::TcpStream>::peek |
+| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::net::tcp::stream::TcpStream>::try_read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::net::tcp::stream::TcpStream>::try_read |
+| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::net::tcp::stream::TcpStream>::try_read_buf | &ref | file://:0:0:0:0 | [post] [summary param] 0 in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::net::tcp::stream::TcpStream>::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::_::<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::_::<u32 as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<u32 as crate::bridge::rpc::DecodeMut>::decode |
@@ -913,6 +926,7 @@ storeStep
 | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_while | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:std::_::<crate::sync::poison::condvar::Condvar>::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::_::<crate::diagnostic::Children as crate::iter::traits::iterator::Iterator>::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:proc_macro::_::<crate::diagnostic::Children as crate::iter::traits::iterator::Iterator>::next |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::<crate::io::Split as crate::iter::traits::iterator::Iterator>::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::io::Split as crate::iter::traits::iterator::Iterator>::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::_::<crate::option::Option>::map | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::option::Option>::map |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::<crate::option::Option>::zip | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::option::Option>::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::_::<crate::str::pattern::MatchOnly as crate::str::pattern::TwoWayStrategy>::matching | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::str::pattern::MatchOnly as crate::str::pattern::TwoWayStrategy>::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::_::<crate::result::Result>::transpose | Err | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::result::Result>::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::_::<crate::result::Result>::transpose | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::result::Result>::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::_::<crate::io::Split as crate::iter::traits::iterator::Iterator>::next | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::<crate::io::Split as crate::iter::traits::iterator::Iterator>::next |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Reference in lang:core::_::<crate::option::Option as crate::convert::From>::from | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::option::Option as crate::convert::From>::from |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Reference in lang:core::_::<crate::option::Option>::as_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::option::Option>::as_mut |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Reference in lang:core::_::<crate::option::Option>::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<crate::option::Option>::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::_::<str>::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<str>::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::_::<crate::io::buffered::bufreader::BufReader as crate::io::BufRead>::fill_buf | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::io::buffered::bufreader::BufReader as crate::io::BufRead>::fill_buf |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::net::tcp::TcpStream>::try_clone | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::net::tcp::TcpStream>::try_clone |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::path::Path>::canonicalize | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::path::Path>::canonicalize |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::sync::poison::condvar::Condvar>::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::_::<crate::blocking::response::Response>::bytes | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::blocking::response::Response>::bytes |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::blocking::response::Response>::text | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::blocking::response::Response>::text |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::blocking::response::Response>::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::blocking::response::Response>::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::_::<crate::response::Response>::bytes | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::bytes |
-| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::chunk | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::chunk |
-| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text |
-| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::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::_::<crate::Url>::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/servo/rust-url:url::_::<crate::Url>::parse |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:alloc::_::<crate::collections::btree::node::NodeRef>::search_tree_for_bifurcation | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::<crate::collections::btree::node::NodeRef>::search_tree_for_bifurcation |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:core::_::<crate::alloc::layout::Layout>::extend | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::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::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_ms | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_ms |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_while | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::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::_::<crate::option::Option>::transpose | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::option::Option>::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::_::<crate::response::Response>::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::_::<crate::response::Response>::chunk |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::<crate::cell::once::OnceCell>::try_insert | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::cell::once::OnceCell>::try_insert |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::<crate::result::Result>::as_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::result::Result>::as_mut |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::<crate::result::Result>::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::result::Result>::as_ref |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::bytes | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::bytes |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::chunk | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::chunk |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::text | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::text |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::bytes | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::bytes |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::chunk | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::chunk |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text_with_charset | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text_with_charset |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::io::util::lines::Lines>::next_line | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::io::util::lines::Lines>::next_line |
+| file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::io::util::split::Split>::next_segment | future | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::io::util::split::Split>::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::_::<crate::async_impl::response::Response>::bytes | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::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::_::<crate::async_impl::response::Response>::chunk | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::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::_::<crate::async_impl::response::Response>::text | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::async_impl::response::Response>::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::_::<crate::response::Response>::bytes | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::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::_::<crate::response::Response>::chunk | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::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::_::<crate::response::Response>::text | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::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::_::<crate::response::Response>::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::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::_::<crate::io::util::lines::Lines>::next_line | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::io::util::lines::Lines>::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::_::<crate::io::util::split::Split>::next_segment | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue.Future in repo:https://github.com/tokio-rs/tokio:tokio::_::<crate::io::util::split::Split>::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::_::<crate::async_impl::response::Response>::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::_::<crate::async_impl::response::Response>::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::_::<crate::response::Response>::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::_::<crate::response::Response>::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::_::<crate::io::util::lines::Lines>::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::_::<crate::io::util::lines::Lines>::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::_::<crate::io::util::split::Split>::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::_::<crate::io::util::split::Split>::next_segment |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::<crate::borrow::Cow as crate::borrow::Borrow>::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::borrow::Cow as crate::borrow::Borrow>::borrow |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::<crate::boxed::Box as crate::borrow::Borrow>::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::boxed::Box as crate::borrow::Borrow>::borrow |
 | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::<crate::boxed::Box as crate::borrow::BorrowMut>::borrow_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::boxed::Box as crate::borrow::BorrowMut>::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<dyn Error>>
+async fn test_std_tcpstream(case: i64) -> std::io::Result<()> {
     // using std::net to fetch a web page
     let address = "example.com:80";
 

From d20a602aabe947867f6d26d5f63149558a232def Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 19 May 2025 11:07:37 +0100
Subject: [PATCH 15/17] Rust: Accept consistency check failures.

---
 .../sources/CONSISTENCY/ExtractionConsistency.expected         | 2 ++
 .../sources/CONSISTENCY/PathResolutionConsistency.expected     | 3 +++
 2 files changed, 5 insertions(+)
 create mode 100644 rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected
 create mode 100644 rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected

diff --git a/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected
new file mode 100644
index 000000000000..9b32055d17f4
--- /dev/null
+++ b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected
@@ -0,0 +1,2 @@
+extractionWarning
+| target/debug/build/typenum-a2c428dcba158190/out/tests.rs:1:1:1:1 | semantic analyzer unavailable (not included in files loaded from manifest) |
diff --git a/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected
new file mode 100644
index 000000000000..0819f6080243
--- /dev/null
+++ b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected
@@ -0,0 +1,3 @@
+multipleMethodCallTargets
+| test.rs:618:25:618:49 | address.to_socket_addrs() | file://:0:0:0:0 | fn to_socket_addrs |
+| test.rs:618:25:618:49 | address.to_socket_addrs() | file://:0:0:0:0 | fn to_socket_addrs |

From 204260e244aac11fbd336362dfd847ece70fd408 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 20 May 2025 10:59:23 +0100
Subject: [PATCH 16/17] Rust: Uncomment calls to test functions.

---
 rust/ql/test/library-tests/dataflow/sources/test.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs
index e2cea47b95b3..370f3d4c9b66 100644
--- a/rust/ql/test/library-tests/dataflow/sources/test.rs
+++ b/rust/ql/test/library-tests/dataflow/sources/test.rs
@@ -777,17 +777,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     println!("test_env_vars...");
     test_env_vars();
 
-    /*println!("test_env_args...");
-    test_env_args();*/
+    println!("test_env_args...");
+    test_env_args();
 
     println!("test_env_dirs...");
     test_env_dirs();
 
-    /*println!("test_reqwest...");
+    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)) {
@@ -795,7 +795,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
         Err(e) => println!("error: {}", e),
     }
 
-    /*println!("test_io_stdin...");
+    println!("test_io_stdin...");
     match test_io_stdin() {
         Ok(_) => println!("complete"),
         Err(e) => println!("error: {}", e),
@@ -805,7 +805,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     match futures::executor::block_on(test_tokio_stdin()) {
         Ok(_) => println!("complete"),
         Err(e) => println!("error: {}", e),
-    }*/
+    }
 
     println!("test_fs...");
     match test_fs() {

From 053da5530fda1379fe793775932f042eb0374123 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 21 May 2025 10:17:14 +0100
Subject: [PATCH 17/17] Rust: Accept test changes after merge with main.

---
 .../sources/CONSISTENCY/ExtractionConsistency.expected         | 2 --
 .../sources/CONSISTENCY/PathResolutionConsistency.expected     | 3 ---
 .../test/library-tests/dataflow/sources/TaintSources.expected  | 2 ++
 3 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected
index 9b32055d17f4..e69de29bb2d1 100644
--- a/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected
+++ b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/ExtractionConsistency.expected
@@ -1,2 +0,0 @@
-extractionWarning
-| target/debug/build/typenum-a2c428dcba158190/out/tests.rs:1:1:1:1 | semantic analyzer unavailable (not included in files loaded from manifest) |
diff --git a/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected
index 0819f6080243..e69de29bb2d1 100644
--- a/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected
+++ b/rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected
@@ -1,3 +0,0 @@
-multipleMethodCallTargets
-| test.rs:618:25:618:49 | address.to_socket_addrs() | file://:0:0:0:0 | fn to_socket_addrs |
-| test.rs:618:25:618:49 | address.to_socket_addrs() | file://:0:0:0:0 | fn to_socket_addrs |
diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected
index 300773377323..da3b69eb0507 100644
--- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected
+++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected
@@ -59,6 +59,8 @@
 | 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: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: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). |