feat(rust:) Add initial rusqlite support

This commit is contained in:
Mathew Payne
2025-01-23 13:09:25 +00:00
parent 5bfd22e60a
commit e205a6811f
6 changed files with 97 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
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"]

View File

@@ -0,0 +1,20 @@
import rust
import codeql.rust.security.SqlInjectionExtensions
import codeql.rust.Concepts
import utils.test.InlineExpectationsTest
module RusqliteTest implements TestSig {
string getARelevantTag() { result = ["sql-sink"] }
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 = ""
)
}
}
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 SERIAL PRIMARY KEY,
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)?,
name: row.get(1)?,
age: row.get(2)?,
})
})?;
let mut stmt = connection.prepare("SELECT id, name, age FROM person")?; // $ sql-sink
let people = stmt.query_map([], |row| {
Ok(Person {
id: row.get(0)?,
name: row.get(1)?,
age: row.get(2)?,
})
})?;
Ok(())
}

View File

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