From 31353e7efc3b6e20d29e0bd8ef13470c40dc54c2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:39:14 +0100 Subject: [PATCH 01/10] Rust: Test more variants of postgres usage. --- .../library-tests/frameworks/postgres/main.rs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/rust/ql/test/library-tests/frameworks/postgres/main.rs b/rust/ql/test/library-tests/frameworks/postgres/main.rs index dd1084b6ee51..38bc09839256 100644 --- a/rust/ql/test/library-tests/frameworks/postgres/main.rs +++ b/rust/ql/test/library-tests/frameworks/postgres/main.rs @@ -1,5 +1,4 @@ - fn main() -> Result<(), Box> { // Get input from CLI let args: Vec = std::env::args().collect(); @@ -18,19 +17,22 @@ fn main() -> Result<(), Box> { )?; let query = format!("INSERT INTO person (name, age) VALUES ('{}', '{}')", name, age); + let query2 = "INSERT INTO person (id) VALUES ($1)"; conn.execute(query.as_str(), &[])?; // $ sql-sink conn.batch_execute(query.as_str())?; // $ sql-sink conn.prepare(query.as_str())?; // $ sql-sink - // conn.prepare_typed(query.as_str(), &[])?; + conn.prepare_typed(query2, &[postgres::types::Type::INT4])?; // $ sql-sink conn.query(query.as_str(), &[])?; // $ sql-sink conn.query_one(query.as_str(), &[])?; // $ sql-sink conn.query_opt(query.as_str(), &[])?; // $ sql-sink - // conn.query_raw(query.as_str(), &[])?; - // conn.query_typed(query.as_str(), &[])?; - // conn.query_typed_raw(query.as_str(), &[])?; + let params: Vec = vec![0]; + conn.query_raw(query.as_str(), params)?; // $ sql-sink + conn.query_typed(query.as_str(), &[])?; // $ sql-sink + let params: Vec<(i32, postgres::types::Type)> = vec![(0, postgres::types::Type::INT4)]; + conn.query_typed_raw(query2, params)?; // $ sql-sink for row in &conn.query("SELECT id, name, age FROM person", &[])? { // $ sql-sink let id: i32 = row.get("id"); // $ database-read @@ -39,5 +41,14 @@ fn main() -> Result<(), Box> { println!("found person: {} {} {}", id, name, age); } + for message in &conn.simple_query("SELECT id, name, age FROM person")? { // $ MISSING: sql-sink + if let postgres::SimpleQueryMessage::Row(row) = message { + let id: i32 = row.get(0).unwrap().parse().unwrap(); // $ MISSING: database-read + let name: &str = row.get(1).unwrap(); // $ MISSING: database-read + let age: i32 = row.get(2).unwrap().parse().unwrap(); // $ MISSING: database-read + println!("found person: {} {} {}", id, name, age); + } + } + Ok(()) } From b31186451f6f1b4f22f02f071596d5cb7e69cf5a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:36:59 +0100 Subject: [PATCH 02/10] Rust: Test more variants of rusqlite usage. --- rust/ql/test/library-tests/frameworks/rusqlite/main.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/ql/test/library-tests/frameworks/rusqlite/main.rs b/rust/ql/test/library-tests/frameworks/rusqlite/main.rs index 324ee5be8fa7..5bd99087a216 100644 --- a/rust/ql/test/library-tests/frameworks/rusqlite/main.rs +++ b/rust/ql/test/library-tests/frameworks/rusqlite/main.rs @@ -48,5 +48,13 @@ fn main() -> Result<(), Box> { }) })?; + _ = connection.prepare_cached("SELECT id, name, age FROM person")?; // $ MISSING: sql-sink + _ = connection.prepare_with_flags("SELECT id, name, age FROM person", rusqlite::PrepFlags::empty())?; // $ MISSING: ql-sink + _ = connection.query_row_and_then("SELECT id, name, age FROM person", [], |row| { // $ sql-sink + let row: &rusqlite::Row<'_> = row; + let result: Result = Ok(row.get(0)?); // $ database-read + result + })?; + Ok(()) } From 17741af88e71157eedc022fbe8d7decccf5818ea Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:33:23 +0100 Subject: [PATCH 03/10] Rust: Fill out a few gaps in the models. --- rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml | 2 ++ rust/ql/test/library-tests/frameworks/rusqlite/main.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml b/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml index 43030de02d5b..66f33192f12a 100644 --- a/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml @@ -5,10 +5,12 @@ extensions: data: - ["::execute", "Argument[0]", "sql-injection", "manual"] - ["::execute_batch", "Argument[0]", "sql-injection", "manual"] + - ["::prepare_cached", "Argument[0]", "sql-injection", "manual"] - ["::prepare", "Argument[0]", "sql-injection", "manual"] - [::prepare_with_flags", "Argument[0]", "sql-injection", "manual"] - ["::query_row", "Argument[0]", "sql-injection", "manual"] - ["::query_row_and_then", "Argument[0]", "sql-injection", "manual"] + - ["::query_one", "Argument[0]", "sql-injection", "manual"] - addsTo: pack: codeql/rust-all extensible: sourceModel diff --git a/rust/ql/test/library-tests/frameworks/rusqlite/main.rs b/rust/ql/test/library-tests/frameworks/rusqlite/main.rs index 5bd99087a216..86066c93c54d 100644 --- a/rust/ql/test/library-tests/frameworks/rusqlite/main.rs +++ b/rust/ql/test/library-tests/frameworks/rusqlite/main.rs @@ -48,7 +48,7 @@ fn main() -> Result<(), Box> { }) })?; - _ = connection.prepare_cached("SELECT id, name, age FROM person")?; // $ MISSING: sql-sink + _ = connection.prepare_cached("SELECT id, name, age FROM person")?; // $ sql-sink _ = connection.prepare_with_flags("SELECT id, name, age FROM person", rusqlite::PrepFlags::empty())?; // $ MISSING: ql-sink _ = connection.query_row_and_then("SELECT id, name, age FROM person", [], |row| { // $ sql-sink let row: &rusqlite::Row<'_> = row; From 5056ebf186b3ec5ad81a72fa8cd79d2ded2f9b18 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:24:34 +0100 Subject: [PATCH 04/10] Rust: Fix typo in one of the models. --- rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml | 2 +- rust/ql/test/library-tests/frameworks/rusqlite/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml b/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml index 66f33192f12a..832d31e661c5 100644 --- a/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml @@ -7,7 +7,7 @@ extensions: - ["::execute_batch", "Argument[0]", "sql-injection", "manual"] - ["::prepare_cached", "Argument[0]", "sql-injection", "manual"] - ["::prepare", "Argument[0]", "sql-injection", "manual"] - - [::prepare_with_flags", "Argument[0]", "sql-injection", "manual"] + - ["::prepare_with_flags", "Argument[0]", "sql-injection", "manual"] - ["::query_row", "Argument[0]", "sql-injection", "manual"] - ["::query_row_and_then", "Argument[0]", "sql-injection", "manual"] - ["::query_one", "Argument[0]", "sql-injection", "manual"] diff --git a/rust/ql/test/library-tests/frameworks/rusqlite/main.rs b/rust/ql/test/library-tests/frameworks/rusqlite/main.rs index 86066c93c54d..441aa35f798b 100644 --- a/rust/ql/test/library-tests/frameworks/rusqlite/main.rs +++ b/rust/ql/test/library-tests/frameworks/rusqlite/main.rs @@ -49,7 +49,7 @@ fn main() -> Result<(), Box> { })?; _ = connection.prepare_cached("SELECT id, name, age FROM person")?; // $ sql-sink - _ = connection.prepare_with_flags("SELECT id, name, age FROM person", rusqlite::PrepFlags::empty())?; // $ MISSING: ql-sink + _ = connection.prepare_with_flags("SELECT id, name, age FROM person", rusqlite::PrepFlags::empty())?; // $ sql-sink _ = connection.query_row_and_then("SELECT id, name, age FROM person", [], |row| { // $ sql-sink let row: &rusqlite::Row<'_> = row; let result: Result = Ok(row.get(0)?); // $ database-read From 35681d0617a7fbba6237d08c5f29c8a45fedbf6c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:44:35 +0100 Subject: [PATCH 05/10] Rust: Add SQLx sources. --- rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml b/rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml index efc6022b0c55..082bde1f9425 100644 --- a/rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml @@ -11,3 +11,11 @@ extensions: - ["sqlx_core::query_scalar_with::query_scalar_with", "Argument[0]", "sql-injection", "manual"] - ["sqlx_core::raw_sql::raw_sql", "Argument[0]", "sql-injection", "manual"] - ["<_ as sqlx_core::executor::Executor>::execute", "Argument[0]", "sql-injection", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + - ["::get", "ReturnValue", "database", "manual"] + - ["::get_unchecked", "ReturnValue", "database", "manual"] + - ["::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] + - ["::try_get_unchecked", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] From 4bbffc56a856fa3903f38a7ab650a4e17e155e80 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:47:13 +0100 Subject: [PATCH 06/10] Rust: Expand tokio-postgres sources. --- rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml | 2 ++ rust/ql/test/library-tests/frameworks/postgres/main.rs | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml index 9cac599357df..dd8f15ff421d 100644 --- a/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml @@ -21,3 +21,5 @@ extensions: data: - ["::get", "ReturnValue", "database", "manual"] - ["::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] + - ["::get", "ReturnValue.Field[core::option::Option::Some(0)]", "database", "manual"] + - ["::try_get", "ReturnValue.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "database", "manual"] diff --git a/rust/ql/test/library-tests/frameworks/postgres/main.rs b/rust/ql/test/library-tests/frameworks/postgres/main.rs index 38bc09839256..f9afb15a0a1a 100644 --- a/rust/ql/test/library-tests/frameworks/postgres/main.rs +++ b/rust/ql/test/library-tests/frameworks/postgres/main.rs @@ -43,9 +43,9 @@ fn main() -> Result<(), Box> { for message in &conn.simple_query("SELECT id, name, age FROM person")? { // $ MISSING: sql-sink if let postgres::SimpleQueryMessage::Row(row) = message { - let id: i32 = row.get(0).unwrap().parse().unwrap(); // $ MISSING: database-read - let name: &str = row.get(1).unwrap(); // $ MISSING: database-read - let age: i32 = row.get(2).unwrap().parse().unwrap(); // $ MISSING: database-read + let id: i32 = row.get(0).unwrap().parse().unwrap(); // $ database-read + let name: &str = row.get(1).unwrap(); // $ database-read + let age: i32 = row.get(2).unwrap().parse().unwrap(); // $ database-read println!("found person: {} {} {}", id, name, age); } } From 0544ea87281acd6048ee209e340518ead690dae0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:00:17 +0100 Subject: [PATCH 07/10] Rust: Add postgres sources. --- rust/ql/lib/codeql/rust/frameworks/postgres.model.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml b/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml index 81877ed17bdf..c1971c2f8cbf 100644 --- a/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml @@ -13,3 +13,11 @@ extensions: - ["::query_raw", "Argument[0]", "sql-injection", "manual"] - ["::query_typed", "Argument[0]", "sql-injection", "manual"] - ["::query_typed_raw", "Argument[0]", "sql-injection", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: sourceModel + data: + - ["::get", "ReturnValue", "database", "manual"] + - ["::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] + - ["::get", "ReturnValue.Field[core::option::Option::Some(0)]", "database", "manual"] + - ["::try_get", "ReturnValue.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "database", "manual"] From 398d2ac930d3dae0f0ed499c0687ca563d9053c1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Aug 2025 19:22:24 +0100 Subject: [PATCH 08/10] Rust: Fix a couple more gaps. --- rust/ql/lib/codeql/rust/frameworks/postgres.model.yml | 1 + rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml | 1 + rust/ql/test/library-tests/frameworks/postgres/main.rs | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml b/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml index c1971c2f8cbf..32dadb2503f6 100644 --- a/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml @@ -13,6 +13,7 @@ extensions: - ["::query_raw", "Argument[0]", "sql-injection", "manual"] - ["::query_typed", "Argument[0]", "sql-injection", "manual"] - ["::query_typed_raw", "Argument[0]", "sql-injection", "manual"] + - ["::simple_query", "Argument[0]", "sql-injection", "manual"] - addsTo: pack: codeql/rust-all extensible: sourceModel diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml index dd8f15ff421d..7e55b1c8bb7d 100644 --- a/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml @@ -9,6 +9,7 @@ extensions: - ["::prepare", "Argument[0]", "sql-injection", "manual"] - ["::prepare_typed", "Argument[0]", "sql-injection", "manual"] - ["::query", "Argument[0]", "sql-injection", "manual"] + - ["::query_one", "Argument[0]", "sql-injection", "manual"] - ["::query_opt", "Argument[0]", "sql-injection", "manual"] - ["::query_raw", "Argument[0]", "sql-injection", "manual"] - ["::query_typed", "Argument[0]", "sql-injection", "manual"] diff --git a/rust/ql/test/library-tests/frameworks/postgres/main.rs b/rust/ql/test/library-tests/frameworks/postgres/main.rs index f9afb15a0a1a..262e22855bf1 100644 --- a/rust/ql/test/library-tests/frameworks/postgres/main.rs +++ b/rust/ql/test/library-tests/frameworks/postgres/main.rs @@ -41,7 +41,7 @@ fn main() -> Result<(), Box> { println!("found person: {} {} {}", id, name, age); } - for message in &conn.simple_query("SELECT id, name, age FROM person")? { // $ MISSING: sql-sink + for message in &conn.simple_query("SELECT id, name, age FROM person")? { // $ sql-sink if let postgres::SimpleQueryMessage::Row(row) = message { let id: i32 = row.get(0).unwrap().parse().unwrap(); // $ database-read let name: &str = row.get(1).unwrap(); // $ database-read From 993f00b6589890cf73aec321dc27117bd9ffb638 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Aug 2025 19:32:13 +0100 Subject: [PATCH 09/10] Rust: Change note. --- rust/ql/lib/change-notes/2025-08-11-database-models.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 rust/ql/lib/change-notes/2025-08-11-database-models.md diff --git a/rust/ql/lib/change-notes/2025-08-11-database-models.md b/rust/ql/lib/change-notes/2025-08-11-database-models.md new file mode 100644 index 000000000000..e8aa6dda7a62 --- /dev/null +++ b/rust/ql/lib/change-notes/2025-08-11-database-models.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added more detail to models of `postgres`, `rusqlite`, `sqlx` and `tokio-postgres`. This may improve query results, particularly for `rust/sql-injection` and `rust/cleartext-storage-database`. From af20d335c8b4df4b62293ad3fbeb051c42779a93 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:25:41 +0100 Subject: [PATCH 10/10] Rust: Accept consistency test changes. --- .../postgres/CONSISTENCY/PathResolutionConsistency.expected | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected index 8c8a9767934d..52ccf4c06dc7 100644 --- a/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected +++ b/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected @@ -5,3 +5,5 @@ multipleCallTargets | main.rs:28:16:28:29 | query.as_str() | | main.rs:29:20:29:33 | query.as_str() | | main.rs:30:20:30:33 | query.as_str() | +| main.rs:32:20:32:33 | query.as_str() | +| main.rs:33:22:33:35 | query.as_str() |