Skip to content

Commit 7578429

Browse files
authored
Merge pull request #2676 from weiznich/bug/fix_potential_use_after_free
Bug/fix potential use after free
2 parents ccfc42a + 6c511d0 commit 7578429

File tree

5 files changed

+141
-84
lines changed

5 files changed

+141
-84
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,14 @@ Key points:
245245

246246
[2-0-migration]: FIXME write a migration guide
247247

248+
## [1.4.6] - 2021-03-05
249+
250+
### Fixed
251+
252+
* Fixed a use-after-free issue in the `QueryableByName` implementation
253+
of our `Sqlite` backend
254+
* Updated several dependencies
255+
248256
## [1.4.5] - 2020-06-09
249257

250258
### Fixed
@@ -1882,3 +1890,5 @@ Key points:
18821890
[1.4.2]: https://github.com/diesel-rs/diesel/compare/v1.4.1...v1.4.2
18831891
[1.4.3]: https://github.com/diesel-rs/diesel/compare/v1.4.2...v1.4.3
18841892
[1.4.4]: https://github.com/diesel-rs/diesel/compare/v1.4.3...v1.4.4
1893+
[1.4.5]: https://github.com/diesel-rs/diesel/compare/v1.4.4...v1.4.5
1894+
[1.4.6]: https://github.com/diesel-rs/diesel/compare/v1.4.5...v1.4.6

diesel/src/sqlite/connection/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl Connection for SqliteConnection {
8989
Self::Backend: QueryMetadata<T::SqlType>,
9090
{
9191
let mut statement = self.prepare_query(&source.as_query())?;
92-
let statement_use = StatementUse::new(&mut statement);
92+
let statement_use = StatementUse::new(&mut statement, true);
9393
let iter = StatementIterator::new(statement_use);
9494
iter.collect()
9595
}
@@ -100,7 +100,7 @@ impl Connection for SqliteConnection {
100100
T: QueryFragment<Self::Backend> + QueryId,
101101
{
102102
let mut statement = self.prepare_query(source)?;
103-
let mut statement_use = StatementUse::new(&mut statement);
103+
let mut statement_use = StatementUse::new(&mut statement, false);
104104
statement_use.run()?;
105105
Ok(self.raw_connection.rows_affected_by_last_query())
106106
}

diesel/src/sqlite/connection/sqlite_value.rs

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
extern crate libsqlite3_sys as ffi;
22

33
use std::marker::PhantomData;
4-
use std::os::raw as libc;
54
use std::ptr::NonNull;
65
use std::{slice, str};
76

87
use crate::row::*;
98
use crate::sqlite::{Sqlite, SqliteType};
109

10+
use super::stmt::StatementUse;
11+
1112
/// Raw sqlite value as received from the database
1213
///
1314
/// Use existing `FromSql` implementations to convert this into
@@ -18,11 +19,8 @@ pub struct SqliteValue<'a> {
1819
p: PhantomData<&'a ()>,
1920
}
2021

21-
#[derive(Clone)]
22-
pub struct SqliteRow<'a> {
23-
stmt: NonNull<ffi::sqlite3_stmt>,
24-
next_col_index: libc::c_int,
25-
p: PhantomData<&'a ()>,
22+
pub struct SqliteRow<'a: 'b, 'b: 'c, 'c> {
23+
stmt: &'c StatementUse<'a, 'b>,
2624
}
2725

2826
impl<'a> SqliteValue<'a> {
@@ -92,22 +90,20 @@ impl<'a> SqliteValue<'a> {
9290
}
9391
}
9492

95-
impl<'a> SqliteRow<'a> {
96-
pub(crate) unsafe fn new(inner_statement: NonNull<ffi::sqlite3_stmt>) -> Self {
93+
impl<'a: 'b, 'b: 'c, 'c> SqliteRow<'a, 'b, 'c> {
94+
pub(crate) fn new(inner_statement: &'c StatementUse<'a, 'b>) -> Self {
9795
SqliteRow {
9896
stmt: inner_statement,
99-
next_col_index: 0,
100-
p: PhantomData,
10197
}
10298
}
10399
}
104100

105-
impl<'a> Row<'a, Sqlite> for SqliteRow<'a> {
106-
type Field = SqliteField<'a>;
101+
impl<'a: 'b, 'b: 'c, 'c> Row<'c, Sqlite> for SqliteRow<'a, 'b, 'c> {
102+
type Field = SqliteField<'a, 'b, 'c>;
107103
type InnerPartialRow = Self;
108104

109105
fn field_count(&self) -> usize {
110-
column_count(self.stmt) as usize
106+
self.stmt.column_count() as usize
111107
}
112108

113109
fn get<I>(&self, idx: I) -> Option<Self::Field>
@@ -116,9 +112,8 @@ impl<'a> Row<'a, Sqlite> for SqliteRow<'a> {
116112
{
117113
let idx = self.idx(idx)?;
118114
Some(SqliteField {
119-
stmt: self.stmt,
115+
stmt: &self.stmt,
120116
col_idx: idx as i32,
121-
p: PhantomData,
122117
})
123118
}
124119

@@ -127,63 +122,37 @@ impl<'a> Row<'a, Sqlite> for SqliteRow<'a> {
127122
}
128123
}
129124

130-
impl<'a> RowIndex<usize> for SqliteRow<'a> {
125+
impl<'a: 'b, 'b: 'c, 'c> RowIndex<usize> for SqliteRow<'a, 'b, 'c> {
131126
fn idx(&self, idx: usize) -> Option<usize> {
132-
if idx < self.field_count() {
127+
if idx < self.stmt.column_count() as usize {
133128
Some(idx)
134129
} else {
135130
None
136131
}
137132
}
138133
}
139134

140-
impl<'a, 'b> RowIndex<&'a str> for SqliteRow<'b> {
141-
fn idx(&self, field_name: &'a str) -> Option<usize> {
142-
(0..column_count(self.stmt))
143-
.find(|idx| column_name(self.stmt, *idx) == Some(field_name))
144-
.map(|a| a as usize)
135+
impl<'a: 'b, 'b: 'c, 'c, 'd> RowIndex<&'d str> for SqliteRow<'a, 'b, 'c> {
136+
fn idx(&self, field_name: &'d str) -> Option<usize> {
137+
self.stmt.index_for_column_name(field_name)
145138
}
146139
}
147140

148-
pub struct SqliteField<'a> {
149-
stmt: NonNull<ffi::sqlite3_stmt>,
141+
pub struct SqliteField<'a: 'b, 'b: 'c, 'c> {
142+
stmt: &'c StatementUse<'a, 'b>,
150143
col_idx: i32,
151-
p: PhantomData<&'a ()>,
152144
}
153145

154-
impl<'a> Field<'a, Sqlite> for SqliteField<'a> {
155-
fn field_name(&self) -> Option<&'a str> {
156-
column_name(self.stmt, self.col_idx)
146+
impl<'a: 'b, 'b: 'c, 'c> Field<'c, Sqlite> for SqliteField<'a, 'b, 'c> {
147+
fn field_name(&self) -> Option<&'c str> {
148+
self.stmt.field_name(self.col_idx)
157149
}
158150

159151
fn is_null(&self) -> bool {
160152
self.value().is_none()
161153
}
162154

163-
fn value(&self) -> Option<crate::backend::RawValue<'a, Sqlite>> {
164-
unsafe {
165-
let ptr = ffi::sqlite3_column_value(self.stmt.as_ptr(), self.col_idx);
166-
SqliteValue::new(ptr)
167-
}
155+
fn value(&self) -> Option<crate::backend::RawValue<'c, Sqlite>> {
156+
self.stmt.value(self.col_idx)
168157
}
169158
}
170-
171-
fn column_name<'a>(stmt: NonNull<ffi::sqlite3_stmt>, field_number: i32) -> Option<&'a str> {
172-
unsafe {
173-
let ptr = ffi::sqlite3_column_name(stmt.as_ptr(), field_number);
174-
if ptr.is_null() {
175-
None
176-
} else {
177-
Some(std::ffi::CStr::from_ptr(ptr).to_str().expect(
178-
"The Sqlite documentation states that this is UTF8. \
179-
If you see this error message something has gone \
180-
horribliy wrong. Please open an issue at the \
181-
diesel repository.",
182-
))
183-
}
184-
}
185-
}
186-
187-
fn column_count(stmt: NonNull<ffi::sqlite3_stmt>) -> i32 {
188-
unsafe { ffi::sqlite3_column_count(stmt.as_ptr()) }
189-
}

diesel/src/sqlite/connection/statement_iterator.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ use crate::result::Error::DeserializationError;
66
use crate::result::QueryResult;
77
use crate::sqlite::Sqlite;
88

9-
pub struct StatementIterator<'a, ST, T> {
10-
stmt: StatementUse<'a>,
9+
pub struct StatementIterator<'a: 'b, 'b, ST, T> {
10+
stmt: StatementUse<'a, 'b>,
1111
_marker: PhantomData<(ST, T)>,
1212
}
1313

14-
impl<'a, ST, T> StatementIterator<'a, ST, T> {
15-
pub fn new(stmt: StatementUse<'a>) -> Self {
14+
impl<'a: 'b, 'b, ST, T> StatementIterator<'a, 'b, ST, T> {
15+
pub fn new(stmt: StatementUse<'a, 'b>) -> Self {
1616
StatementIterator {
17-
stmt: stmt,
17+
stmt,
1818
_marker: PhantomData,
1919
}
2020
}
2121
}
2222

23-
impl<'a, ST, T> Iterator for StatementIterator<'a, ST, T>
23+
impl<'a: 'b, 'b, ST, T> Iterator for StatementIterator<'a, 'b, ST, T>
2424
where
2525
T: FromSqlRow<ST, Sqlite>,
2626
{

diesel/src/sqlite/connection/stmt.rs

Lines changed: 101 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::ptr::{self, NonNull};
88
use super::raw::RawConnection;
99
use super::serialized_value::SerializedValue;
1010
use super::sqlite_value::SqliteRow;
11+
use super::SqliteValue;
1112
use crate::result::Error::DatabaseError;
1213
use crate::result::*;
1314
use crate::sqlite::SqliteType;
@@ -39,10 +40,6 @@ impl Statement {
3940
})
4041
}
4142

42-
fn run(&mut self) -> QueryResult<()> {
43-
self.step().map(|_| ())
44-
}
45-
4643
pub fn bind(&mut self, tpe: SqliteType, value: Option<Vec<u8>>) -> QueryResult<()> {
4744
self.bind_index += 1;
4845
let value = SerializedValue {
@@ -54,16 +51,6 @@ impl Statement {
5451
ensure_sqlite_ok(result, self.raw_connection())
5552
}
5653

57-
fn step(&mut self) -> QueryResult<Option<SqliteRow>> {
58-
unsafe {
59-
match ffi::sqlite3_step(self.inner_statement.as_ptr()) {
60-
ffi::SQLITE_DONE => Ok(None),
61-
ffi::SQLITE_ROW => Ok(Some(SqliteRow::new(self.inner_statement))),
62-
_ => Err(last_error(self.raw_connection())),
63-
}
64-
}
65-
}
66-
6754
fn reset(&mut self) {
6855
self.bind_index = 0;
6956
unsafe { ffi::sqlite3_reset(self.inner_statement.as_ptr()) };
@@ -127,27 +114,118 @@ impl Drop for Statement {
127114
}
128115
}
129116

130-
pub struct StatementUse<'a> {
117+
pub struct StatementUse<'a: 'b, 'b> {
131118
statement: &'a mut Statement,
119+
column_names: Vec<&'b str>,
120+
should_init_column_names: bool,
132121
}
133122

134-
impl<'a> StatementUse<'a> {
135-
pub fn new(statement: &'a mut Statement) -> Self {
123+
impl<'a, 'b> StatementUse<'a, 'b> {
124+
pub(in crate::sqlite::connection) fn new(
125+
statement: &'a mut Statement,
126+
should_init_column_names: bool,
127+
) -> Self {
136128
StatementUse {
137-
statement: statement,
129+
statement,
130+
// Init with empty vector because column names
131+
// can change till the first call to `step()`
132+
column_names: Vec::new(),
133+
should_init_column_names,
134+
}
135+
}
136+
137+
pub(in crate::sqlite::connection) fn run(&mut self) -> QueryResult<()> {
138+
self.step().map(|_| ())
139+
}
140+
141+
pub(in crate::sqlite::connection) fn step<'c>(
142+
&'c mut self,
143+
) -> QueryResult<Option<SqliteRow<'a, 'b, 'c>>>
144+
where
145+
'b: 'c,
146+
{
147+
let res = unsafe {
148+
match ffi::sqlite3_step(self.statement.inner_statement.as_ptr()) {
149+
ffi::SQLITE_DONE => Ok(None),
150+
ffi::SQLITE_ROW => Ok(Some(())),
151+
_ => Err(last_error(self.statement.raw_connection())),
152+
}
153+
}?;
154+
if self.should_init_column_names {
155+
self.column_names = (0..self.column_count())
156+
.map(|idx| unsafe { self.column_name(idx) })
157+
.collect();
158+
self.should_init_column_names = false;
138159
}
160+
Ok(res.map(move |()| SqliteRow::new(self)))
161+
}
162+
163+
// The returned string pointer is valid until either the prepared statement is
164+
// destroyed by sqlite3_finalize() or until the statement is automatically
165+
// reprepared by the first call to sqlite3_step() for a particular run or
166+
// until the next call to sqlite3_column_name() or sqlite3_column_name16()
167+
// on the same column.
168+
//
169+
// https://sqlite.org/c3ref/column_name.html
170+
//
171+
// As result of this requirements: Never use that function outside of `ColumnInformation`
172+
// and never use `ColumnInformation` outside of `StatementUse`
173+
unsafe fn column_name(&mut self, idx: i32) -> &'b str {
174+
let name = {
175+
let column_name =
176+
ffi::sqlite3_column_name(self.statement.inner_statement.as_ptr(), idx);
177+
assert!(
178+
!column_name.is_null(),
179+
"The Sqlite documentation states that it only returns a \
180+
null pointer here if we are in a OOM condition."
181+
);
182+
CStr::from_ptr(column_name)
183+
};
184+
name.to_str().expect(
185+
"The Sqlite documentation states that this is UTF8. \
186+
If you see this error message something has gone \
187+
horribliy wrong. Please open an issue at the \
188+
diesel repository.",
189+
)
139190
}
140191

141-
pub fn run(&mut self) -> QueryResult<()> {
142-
self.statement.run()
192+
pub(in crate::sqlite::connection) fn column_count(&self) -> i32 {
193+
unsafe { ffi::sqlite3_column_count(self.statement.inner_statement.as_ptr()) }
143194
}
144195

145-
pub fn step(&mut self) -> QueryResult<Option<SqliteRow>> {
146-
self.statement.step()
196+
pub(in crate::sqlite::connection) fn index_for_column_name(
197+
&self,
198+
field_name: &str,
199+
) -> Option<usize> {
200+
self.column_names
201+
.iter()
202+
.enumerate()
203+
.find(|(_, name)| name == &&field_name)
204+
.map(|(idx, _)| idx)
205+
}
206+
207+
pub(in crate::sqlite::connection) fn field_name<'c>(&'c self, idx: i32) -> Option<&'c str>
208+
where
209+
'b: 'c,
210+
{
211+
self.column_names.get(idx as usize).copied()
212+
}
213+
214+
pub(in crate::sqlite::connection) fn value<'c>(
215+
&'c self,
216+
idx: i32,
217+
) -> Option<super::SqliteValue<'c>>
218+
where
219+
'b: 'c,
220+
{
221+
unsafe {
222+
let ptr = ffi::sqlite3_column_value(self.statement.inner_statement.as_ptr(), idx);
223+
SqliteValue::new(ptr)
224+
}
147225
}
148226
}
149227

150-
impl<'a> Drop for StatementUse<'a> {
228+
impl<'a, 'b> Drop for StatementUse<'a, 'b> {
151229
fn drop(&mut self) {
152230
self.statement.reset();
153231
}

0 commit comments

Comments
 (0)