Skip to content

Commit 17b4682

Browse files
authored
Merge pull request #20208 from geoffw0/sqlmodels
Rust: Fill some gaps in our database models.
2 parents 0a67902 + af20d33 commit 17b4682

File tree

8 files changed

+53
-6
lines changed

8 files changed

+53
-6
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* 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`.

rust/ql/lib/codeql/rust/frameworks/postgres.model.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,12 @@ extensions:
1313
- ["<postgres::client::Client>::query_raw", "Argument[0]", "sql-injection", "manual"]
1414
- ["<postgres::client::Client>::query_typed", "Argument[0]", "sql-injection", "manual"]
1515
- ["<postgres::client::Client>::query_typed_raw", "Argument[0]", "sql-injection", "manual"]
16+
- ["<postgres::client::Client>::simple_query", "Argument[0]", "sql-injection", "manual"]
17+
- addsTo:
18+
pack: codeql/rust-all
19+
extensible: sourceModel
20+
data:
21+
- ["<postgres::row::Row>::get", "ReturnValue", "database", "manual"]
22+
- ["<postgres::row::Row>::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"]
23+
- ["<postgres::row::SimpleQueryRow>::get", "ReturnValue.Field[core::option::Option::Some(0)]", "database", "manual"]
24+
- ["<postgres::row::SimpleQueryRow>::try_get", "ReturnValue.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "database", "manual"]

rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ extensions:
55
data:
66
- ["<rusqlite::Connection>::execute", "Argument[0]", "sql-injection", "manual"]
77
- ["<rusqlite::Connection>::execute_batch", "Argument[0]", "sql-injection", "manual"]
8+
- ["<rusqlite::Connection>::prepare_cached", "Argument[0]", "sql-injection", "manual"]
89
- ["<rusqlite::Connection>::prepare", "Argument[0]", "sql-injection", "manual"]
9-
- [<rusqlite::Connection>::prepare_with_flags", "Argument[0]", "sql-injection", "manual"]
10+
- ["<rusqlite::Connection>::prepare_with_flags", "Argument[0]", "sql-injection", "manual"]
1011
- ["<rusqlite::Connection>::query_row", "Argument[0]", "sql-injection", "manual"]
1112
- ["<rusqlite::Connection>::query_row_and_then", "Argument[0]", "sql-injection", "manual"]
13+
- ["<rusqlite::Connection>::query_one", "Argument[0]", "sql-injection", "manual"]
1214
- addsTo:
1315
pack: codeql/rust-all
1416
extensible: sourceModel

rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,11 @@ extensions:
1111
- ["sqlx_core::query_scalar_with::query_scalar_with", "Argument[0]", "sql-injection", "manual"]
1212
- ["sqlx_core::raw_sql::raw_sql", "Argument[0]", "sql-injection", "manual"]
1313
- ["<_ as sqlx_core::executor::Executor>::execute", "Argument[0]", "sql-injection", "manual"]
14+
- addsTo:
15+
pack: codeql/rust-all
16+
extensible: sourceModel
17+
data:
18+
- ["<sqlx_core::row::Row>::get", "ReturnValue", "database", "manual"]
19+
- ["<sqlx_core::row::Row>::get_unchecked", "ReturnValue", "database", "manual"]
20+
- ["<sqlx_core::row::Row>::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"]
21+
- ["<sqlx_core::row::Row>::try_get_unchecked", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"]

rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ extensions:
99
- ["<tokio_postgres::client::Client>::prepare", "Argument[0]", "sql-injection", "manual"]
1010
- ["<tokio_postgres::client::Client>::prepare_typed", "Argument[0]", "sql-injection", "manual"]
1111
- ["<tokio_postgres::client::Client>::query", "Argument[0]", "sql-injection", "manual"]
12+
- ["<tokio_postgres::client::Client>::query_one", "Argument[0]", "sql-injection", "manual"]
1213
- ["<tokio_postgres::client::Client>::query_opt", "Argument[0]", "sql-injection", "manual"]
1314
- ["<tokio_postgres::client::Client>::query_raw", "Argument[0]", "sql-injection", "manual"]
1415
- ["<tokio_postgres::client::Client>::query_typed", "Argument[0]", "sql-injection", "manual"]
@@ -21,3 +22,5 @@ extensions:
2122
data:
2223
- ["<tokio_postgres::row::Row>::get", "ReturnValue", "database", "manual"]
2324
- ["<tokio_postgres::row::Row>::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"]
25+
- ["<tokio_postgres::row::SimpleQueryRow>::get", "ReturnValue.Field[core::option::Option::Some(0)]", "database", "manual"]
26+
- ["<tokio_postgres::row::SimpleQueryRow>::try_get", "ReturnValue.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "database", "manual"]

rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ multipleCallTargets
55
| main.rs:28:16:28:29 | query.as_str() |
66
| main.rs:29:20:29:33 | query.as_str() |
77
| main.rs:30:20:30:33 | query.as_str() |
8+
| main.rs:32:20:32:33 | query.as_str() |
9+
| main.rs:33:22:33:35 | query.as_str() |

rust/ql/test/library-tests/frameworks/postgres/main.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11

2-
32
fn main() -> Result<(), Box<dyn std::error::Error>> {
43
// Get input from CLI
54
let args: Vec<String> = std::env::args().collect();
@@ -18,19 +17,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
1817
)?;
1918

2019
let query = format!("INSERT INTO person (name, age) VALUES ('{}', '{}')", name, age);
20+
let query2 = "INSERT INTO person (id) VALUES ($1)";
2121

2222
conn.execute(query.as_str(), &[])?; // $ sql-sink
2323
conn.batch_execute(query.as_str())?; // $ sql-sink
2424

2525
conn.prepare(query.as_str())?; // $ sql-sink
26-
// conn.prepare_typed(query.as_str(), &[])?;
26+
conn.prepare_typed(query2, &[postgres::types::Type::INT4])?; // $ sql-sink
2727

2828
conn.query(query.as_str(), &[])?; // $ sql-sink
2929
conn.query_one(query.as_str(), &[])?; // $ sql-sink
3030
conn.query_opt(query.as_str(), &[])?; // $ sql-sink
31-
// conn.query_raw(query.as_str(), &[])?;
32-
// conn.query_typed(query.as_str(), &[])?;
33-
// conn.query_typed_raw(query.as_str(), &[])?;
31+
let params: Vec<i32> = vec![0];
32+
conn.query_raw(query.as_str(), params)?; // $ sql-sink
33+
conn.query_typed(query.as_str(), &[])?; // $ sql-sink
34+
let params: Vec<(i32, postgres::types::Type)> = vec![(0, postgres::types::Type::INT4)];
35+
conn.query_typed_raw(query2, params)?; // $ sql-sink
3436

3537
for row in &conn.query("SELECT id, name, age FROM person", &[])? { // $ sql-sink
3638
let id: i32 = row.get("id"); // $ database-read
@@ -39,5 +41,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3941
println!("found person: {} {} {}", id, name, age);
4042
}
4143

44+
for message in &conn.simple_query("SELECT id, name, age FROM person")? { // $ sql-sink
45+
if let postgres::SimpleQueryMessage::Row(row) = message {
46+
let id: i32 = row.get(0).unwrap().parse().unwrap(); // $ database-read
47+
let name: &str = row.get(1).unwrap(); // $ database-read
48+
let age: i32 = row.get(2).unwrap().parse().unwrap(); // $ database-read
49+
println!("found person: {} {} {}", id, name, age);
50+
}
51+
}
52+
4253
Ok(())
4354
}

rust/ql/test/library-tests/frameworks/rusqlite/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
4848
})
4949
})?;
5050

51+
_ = connection.prepare_cached("SELECT id, name, age FROM person")?; // $ sql-sink
52+
_ = connection.prepare_with_flags("SELECT id, name, age FROM person", rusqlite::PrepFlags::empty())?; // $ sql-sink
53+
_ = connection.query_row_and_then("SELECT id, name, age FROM person", [], |row| { // $ sql-sink
54+
let row: &rusqlite::Row<'_> = row;
55+
let result: Result<i32, rusqlite::Error> = Ok(row.get(0)?); // $ database-read
56+
result
57+
})?;
58+
5159
Ok(())
5260
}

0 commit comments

Comments
 (0)