From 87d81cd46bee11ed6a82e4b87ddff94c9a3e09f1 Mon Sep 17 00:00:00 2001 From: gwenn Date: Sat, 25 Nov 2023 10:13:55 +0100 Subject: [PATCH 1/3] Check sqlite3_reset result https://sqlite.org/c3ref/reset.html > Therefore, it is important that applications check the return code from sqlite3_reset(S) even if no prior call to sqlite3_step(S) indicated a problem. --- src/row.rs | 13 ++++++++----- src/statement.rs | 16 +++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/row.rs b/src/row.rs index 2d25900..e206f9e 100644 --- a/src/row.rs +++ b/src/row.rs @@ -14,9 +14,11 @@ pub struct Rows<'stmt> { impl<'stmt> Rows<'stmt> { #[inline] - fn reset(&mut self) { + fn reset(&mut self) -> Result<()> { if let Some(stmt) = self.stmt.take() { - stmt.reset(); + stmt.reset() + } else { + Ok(()) } } @@ -105,6 +107,7 @@ impl<'stmt> Rows<'stmt> { } impl Drop for Rows<'_> { + #[allow(unused_must_use)] #[inline] fn drop(&mut self) { self.reset(); @@ -217,12 +220,12 @@ impl<'stmt> FallibleStreamingIterator for Rows<'stmt> { Ok(()) } Ok(false) => { - self.reset(); + let r = self.reset(); self.row = None; - Ok(()) + r } Err(e) => { - self.reset(); + let _ = self.reset(); // prevents infinite loop on error self.row = None; Err(e) } diff --git a/src/statement.rs b/src/statement.rs index d39cc1f..edc1870 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -650,9 +650,12 @@ impl Statement<'_> { fn execute_with_bound_parameters(&mut self) -> Result { self.check_update()?; let r = self.stmt.step(); - self.stmt.reset(); + let rr = self.stmt.reset(); match r { - ffi::SQLITE_DONE => Ok(self.conn.changes() as usize), + ffi::SQLITE_DONE => match rr { + ffi::SQLITE_OK => Ok(self.conn.changes() as usize), + _ => Err(self.conn.decode_result(rr).unwrap_err()), + }, ffi::SQLITE_ROW => Err(Error::ExecuteReturnedResults), _ => Err(self.conn.decode_result(r).unwrap_err()), } @@ -847,8 +850,11 @@ impl Statement<'_> { } #[inline] - pub(super) fn reset(&self) -> c_int { - self.stmt.reset() + pub(super) fn reset(&self) -> Result<()> { + match self.stmt.reset() { + ffi::SQLITE_OK => Ok(()), + code => Err(self.conn.decode_result(code).unwrap_err()), + } } } @@ -1274,7 +1280,7 @@ mod test { assert_eq!(0, stmt.column_count()); stmt.parameter_index("test").unwrap(); stmt.step().unwrap_err(); - stmt.reset(); + stmt.reset().unwrap(); // SQLITE_OMIT_AUTORESET = false stmt.execute([]).unwrap_err(); Ok(()) } From 8675e453f319c4be472380291e552dee9f4fec8f Mon Sep 17 00:00:00 2001 From: gwenn Date: Sat, 25 Nov 2023 10:36:07 +0100 Subject: [PATCH 2/3] Add unrelated test just to keep code coverage the same --- src/lib.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index cb4b14b..cebe4f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1494,7 +1494,7 @@ mod test { #[test] #[cfg(feature = "extra_check")] - fn test_execute_select() { + fn test_execute_select_with_no_row() { let db = checked_memory_handle(); let err = db.execute("SELECT 1 WHERE 1 < ?1", [1i32]).unwrap_err(); assert_eq!( @@ -1504,6 +1504,17 @@ mod test { ); } + #[test] + fn test_execute_select_with_row() { + let db = checked_memory_handle(); + let err = db.execute("SELECT 1", []).unwrap_err(); + assert_eq!( + err, + Error::ExecuteReturnedResults, + "Unexpected error: {err}" + ); + } + #[test] #[cfg(feature = "extra_check")] fn test_execute_multiple() { From 9ebca71317a7f665f4a2ef7e49ca70f754662aa5 Mon Sep 17 00:00:00 2001 From: gwenn Date: Sat, 25 Nov 2023 10:47:38 +0100 Subject: [PATCH 3/3] Misc --- src/lib.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cebe4f7..2e1aeb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1508,11 +1508,7 @@ mod test { fn test_execute_select_with_row() { let db = checked_memory_handle(); let err = db.execute("SELECT 1", []).unwrap_err(); - assert_eq!( - err, - Error::ExecuteReturnedResults, - "Unexpected error: {err}" - ); + assert_eq!(err, Error::ExecuteReturnedResults); } #[test]