Merge pull request #18577 from GeekMasher/rust-rusqlite

Rust: Add initial RuSQLite support
This commit is contained in:
Geoffrey White
2025-02-12 17:14:15 +00:00
committed by GitHub
6 changed files with 114 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::Connection>::execute", "Argument[0]", "sql-injection", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::Connection>::execute_batch", "Argument[0]", "sql-injection", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::Connection>::prepare", "Argument[0]", "sql-injection", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::Connection>::prepare_with_flags", "Argument[0]", "sql-injection", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::Connection>::query_row", "Argument[0]", "sql-injection", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::Connection>::query_row_and_then", "Argument[0]", "sql-injection", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: sourceModel
data:
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::row::Row>::get", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "database", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::row::Row>::get_unwrap", "ReturnValue", "database", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::row::Row>::get_ref", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "database", "manual"]
- ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "<crate::row::Row>::get_ref_unwrap", "ReturnValue", "database", "manual"]

View File

@@ -0,0 +1,28 @@
import rust
import codeql.rust.security.SqlInjectionExtensions
import codeql.rust.Concepts
import utils.test.InlineExpectationsTest
module RusqliteTest implements TestSig {
string getARelevantTag() { result = ["sql-sink", "database-read"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(SqlInjection::Sink sink |
location = sink.getLocation() and
location.getFile().getBaseName() != "" and
element = sink.toString() and
tag = "sql-sink" and
value = ""
)
or
exists(ModeledDatabaseSource sink |
location = sink.getLocation() and
location.getFile().getBaseName() != "" and
element = sink.toString() and
tag = "database-read" and
value = ""
)
}
}
import MakeTest<RusqliteTest>

View File

@@ -0,0 +1,13 @@
[workspace]
[package]
name = "rusqlite-test"
version = "0.1.0"
edition = "2021"
[dependencies]
rusqlite = { version = "0.33", features = ["bundled"] }
[[bin]]
name = "rusqlite"
path = "./main.rs"

View File

@@ -0,0 +1,50 @@
use rusqlite::Connection;
#[derive(Debug)]
struct Person {
id: i32,
name: String,
age: i32,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get input from CLI
let args: Vec<String> = std::env::args().collect();
let name = &args[1];
let age = &args[2];
let connection = Connection::open_in_memory()?;
connection.execute( // $ sql-sink
"CREATE TABLE person (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR NOT NULL,
age INT NOT NULL
)",
(),
)?;
let query = format!("INSERT INTO person (name, age) VALUES ('{}', '{}')", name, age);
connection.execute(&query, ())?; // $ sql-sink
let person = connection.query_row(&query, (), |row| { // $ sql-sink
Ok(Person {
id: row.get(0)?, // $ database-read
name: row.get(1)?, // $ database-read
age: row.get(2)?, // $ database-read
})
})?;
let mut stmt = connection.prepare("SELECT id, name, age FROM person")?; // $ sql-sink
let people = stmt.query_map([], |row| {
Ok(Person {
id: row.get_unwrap(0), // $ database-read
name: row.get_unwrap(1), // $ database-read
age: row.get_unwrap(2), // $ database-read
})
})?;
Ok(())
}

View File

@@ -0,0 +1,3 @@
qltest_cargo_check: true
qltest_dependencies:
- rusqlite = { version = "0.33", features = ["bundled"] }