From 00d50199a2d7b32ee6a4343bbf7ad6ccf83d566c Mon Sep 17 00:00:00 2001 From: gwenn Date: Mon, 26 Aug 2019 20:21:23 +0200 Subject: [PATCH] Check SQL query passed to `execute` When `extra_check` feature is activated: Fail when query has a column count > 0 Or when query is readonly. --- .travis.yml | 2 +- Cargo.toml | 5 +++-- src/collation.rs | 4 +++- src/lib.rs | 3 ++- src/statement.rs | 25 +++++++++++++++++++++++++ 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 00e02c0..4f51f65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: - cargo build --features sqlcipher - cargo build --features "bundled sqlcipher" - cargo test - - cargo test --features "backup blob" + - cargo test --features "backup blob extra_check" - cargo test --features "collation functions" - cargo test --features "hooks limits" - cargo test --features load_extension diff --git a/Cargo.toml b/Cargo.toml index cd4a96d..a4fcb13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,12 +48,13 @@ csvtab = ["csv", "vtab"] # pointer passing interfaces: 3.20.0 array = ["vtab"] # session extension: 3.13.0 -session = ["libsqlite3-sys/session", "hooks"] +#session = ["libsqlite3-sys/session", "hooks"] # window functions: 3.25.0 window = ["functions"] # 3.9.0 series = ["vtab"] - +# check for invalid query. +extra_check = [] [dependencies] time = "0.1.0" diff --git a/src/collation.rs b/src/collation.rs index 00c1cd1..1ca2b33 100644 --- a/src/collation.rs +++ b/src/collation.rs @@ -125,7 +125,9 @@ impl InnerConnection { str::from_utf8_unchecked(c_slice) }; callback(&conn, collation_name) - }).is_err() { + }) + .is_err() + { return; // FIXME How ? } } diff --git a/src/lib.rs b/src/lib.rs index 654a548..7bbdb24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -890,7 +890,8 @@ mod test { ) .expect("create temp db"); - let mut db1 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_WRITE).unwrap(); + let mut db1 = + Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_WRITE).unwrap(); let mut db2 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap(); db1.busy_timeout(Duration::from_millis(0)).unwrap(); diff --git a/src/statement.rs b/src/statement.rs index e8d3fb4..683ba9a 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -511,6 +511,7 @@ impl Statement<'_> { } fn execute_with_bound_parameters(&mut self) -> Result { + self.check_update()?; let r = self.stmt.step(); self.stmt.reset(); match r { @@ -547,6 +548,30 @@ impl Statement<'_> { Ok(()) } + #[cfg(all(feature = "bundled", feature = "extra_check"))] + #[inline] + fn check_update(&self) -> Result<()> { + if self.column_count() > 0 || self.stmt.readonly() { + return Err(Error::ExecuteReturnedResults); + } + Ok(()) + } + + #[cfg(all(not(feature = "bundled"), feature = "extra_check"))] + #[inline] + fn check_update(&self) -> Result<()> { + if self.column_count() > 0 { + return Err(Error::ExecuteReturnedResults); + } + Ok(()) + } + + #[cfg(not(feature = "extra_check"))] + #[inline] + fn check_update(&self) -> Result<()> { + Ok(()) + } + /// Returns a string containing the SQL text of prepared statement with /// bound parameters expanded. #[cfg(feature = "bundled")]