mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 10:31:37 +08:00
Merge pull request #549 from gwenn/non-utf-8
Do not assume `sqlite3_column_text` is valid UTF-8.
This commit is contained in:
commit
1d8c2a6ac6
@ -216,7 +216,7 @@ impl InnerConnection {
|
|||||||
|
|
||||||
pub fn prepare<'a>(&mut self, conn: &'a Connection, sql: &str) -> Result<Statement<'a>> {
|
pub fn prepare<'a>(&mut self, conn: &'a Connection, sql: &str) -> Result<Statement<'a>> {
|
||||||
let mut c_stmt = MaybeUninit::uninit();
|
let mut c_stmt = MaybeUninit::uninit();
|
||||||
let (c_sql, len, _) = str_for_sqlite(sql)?;
|
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
||||||
let r = unsafe {
|
let r = unsafe {
|
||||||
if cfg!(feature = "unlock_notify") {
|
if cfg!(feature = "unlock_notify") {
|
||||||
let mut rc;
|
let mut rc;
|
||||||
|
@ -248,9 +248,9 @@ fn str_to_cstring(s: &str) -> Result<CString> {
|
|||||||
/// The `sqlite3_destructor_type` item is always `SQLITE_TRANSIENT` unless
|
/// The `sqlite3_destructor_type` item is always `SQLITE_TRANSIENT` unless
|
||||||
/// the string was empty (in which case it's `SQLITE_STATIC`, and the ptr is
|
/// the string was empty (in which case it's `SQLITE_STATIC`, and the ptr is
|
||||||
/// static).
|
/// static).
|
||||||
fn str_for_sqlite(s: &str) -> Result<(*const c_char, c_int, ffi::sqlite3_destructor_type)> {
|
fn str_for_sqlite(s: &[u8]) -> Result<(*const c_char, c_int, ffi::sqlite3_destructor_type)> {
|
||||||
let len = len_as_c_int(s.len())?;
|
let len = len_as_c_int(s.len())?;
|
||||||
if memchr::memchr(0, s.as_bytes()).is_none() {
|
if memchr::memchr(0, s).is_none() {
|
||||||
let (ptr, dtor_info) = if len != 0 {
|
let (ptr, dtor_info) = if len != 0 {
|
||||||
(s.as_ptr() as *const c_char, ffi::SQLITE_TRANSIENT())
|
(s.as_ptr() as *const c_char, ffi::SQLITE_TRANSIENT())
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,6 +86,7 @@ impl Sql {
|
|||||||
self.push_real(r);
|
self.push_real(r);
|
||||||
}
|
}
|
||||||
ValueRef::Text(s) => {
|
ValueRef::Text(s) => {
|
||||||
|
let s = std::str::from_utf8(s)?;
|
||||||
self.push_string_literal(s);
|
self.push_string_literal(s);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -622,10 +622,7 @@ impl Statement<'_> {
|
|||||||
CStr::from_ptr(text as *const c_char)
|
CStr::from_ptr(text as *const c_char)
|
||||||
};
|
};
|
||||||
|
|
||||||
// sqlite3_column_text returns UTF8 data, so our unwrap here should be fine.
|
let s = s.to_bytes();
|
||||||
let s = s
|
|
||||||
.to_str()
|
|
||||||
.expect("sqlite3_column_text returned invalid UTF-8");
|
|
||||||
ValueRef::Text(s)
|
ValueRef::Text(s)
|
||||||
}
|
}
|
||||||
ffi::SQLITE_BLOB => {
|
ffi::SQLITE_BLOB => {
|
||||||
|
@ -17,7 +17,7 @@ impl ToSql for Value {
|
|||||||
impl FromSql for Value {
|
impl FromSql for Value {
|
||||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||||
match value {
|
match value {
|
||||||
ValueRef::Text(s) => serde_json::from_str(s),
|
ValueRef::Text(s) => serde_json::from_slice(s),
|
||||||
ValueRef::Blob(b) => serde_json::from_slice(b),
|
ValueRef::Blob(b) => serde_json::from_slice(b),
|
||||||
_ => return Err(FromSqlError::InvalidType),
|
_ => return Err(FromSqlError::InvalidType),
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,12 @@ impl ToSql for Url {
|
|||||||
impl FromSql for Url {
|
impl FromSql for Url {
|
||||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||||
match value {
|
match value {
|
||||||
ValueRef::Text(s) => Url::parse(s),
|
ValueRef::Text(s) => {
|
||||||
_ => return Err(FromSqlError::InvalidType),
|
let s = std::str::from_utf8(s).map_err(|e| FromSqlError::Other(Box::new(e)))?;
|
||||||
|
Url::parse(s).map_err(|e| FromSqlError::Other(Box::new(e)))
|
||||||
|
}
|
||||||
|
_ => Err(FromSqlError::InvalidType),
|
||||||
}
|
}
|
||||||
.map_err(|err| FromSqlError::Other(Box::new(err)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ pub enum ValueRef<'a> {
|
|||||||
/// The value is a floating point number.
|
/// The value is a floating point number.
|
||||||
Real(f64),
|
Real(f64),
|
||||||
/// The value is a text string.
|
/// The value is a text string.
|
||||||
Text(&'a str),
|
Text(&'a [u8]),
|
||||||
/// The value is a blob of data
|
/// The value is a blob of data
|
||||||
Blob(&'a [u8]),
|
Blob(&'a [u8]),
|
||||||
}
|
}
|
||||||
@ -54,7 +54,9 @@ impl<'a> ValueRef<'a> {
|
|||||||
/// `Err(Error::InvalidColumnType)`.
|
/// `Err(Error::InvalidColumnType)`.
|
||||||
pub fn as_str(&self) -> FromSqlResult<&'a str> {
|
pub fn as_str(&self) -> FromSqlResult<&'a str> {
|
||||||
match *self {
|
match *self {
|
||||||
ValueRef::Text(t) => Ok(t),
|
ValueRef::Text(t) => {
|
||||||
|
std::str::from_utf8(t).map_err(|e| FromSqlError::Other(Box::new(e)))
|
||||||
|
}
|
||||||
_ => Err(FromSqlError::InvalidType),
|
_ => Err(FromSqlError::InvalidType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +77,10 @@ impl From<ValueRef<'_>> for Value {
|
|||||||
ValueRef::Null => Value::Null,
|
ValueRef::Null => Value::Null,
|
||||||
ValueRef::Integer(i) => Value::Integer(i),
|
ValueRef::Integer(i) => Value::Integer(i),
|
||||||
ValueRef::Real(r) => Value::Real(r),
|
ValueRef::Real(r) => Value::Real(r),
|
||||||
ValueRef::Text(s) => Value::Text(s.to_string()),
|
ValueRef::Text(s) => {
|
||||||
|
let s = std::str::from_utf8(s).expect("invalid UTF-8");
|
||||||
|
Value::Text(s.to_string())
|
||||||
|
}
|
||||||
ValueRef::Blob(b) => Value::Blob(b.to_vec()),
|
ValueRef::Blob(b) => Value::Blob(b.to_vec()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,7 +88,7 @@ impl From<ValueRef<'_>> for Value {
|
|||||||
|
|
||||||
impl<'a> From<&'a str> for ValueRef<'a> {
|
impl<'a> From<&'a str> for ValueRef<'a> {
|
||||||
fn from(s: &str) -> ValueRef<'_> {
|
fn from(s: &str) -> ValueRef<'_> {
|
||||||
ValueRef::Text(s)
|
ValueRef::Text(s.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +104,7 @@ impl<'a> From<&'a Value> for ValueRef<'a> {
|
|||||||
Value::Null => ValueRef::Null,
|
Value::Null => ValueRef::Null,
|
||||||
Value::Integer(i) => ValueRef::Integer(i),
|
Value::Integer(i) => ValueRef::Integer(i),
|
||||||
Value::Real(r) => ValueRef::Real(r),
|
Value::Real(r) => ValueRef::Real(r),
|
||||||
Value::Text(ref s) => ValueRef::Text(s),
|
Value::Text(ref s) => ValueRef::Text(s.as_bytes()),
|
||||||
Value::Blob(ref b) => ValueRef::Blob(b),
|
Value::Blob(ref b) => ValueRef::Blob(b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,10 +130,7 @@ impl<'a> ValueRef<'a> {
|
|||||||
);
|
);
|
||||||
let s = CStr::from_ptr(text as *const c_char);
|
let s = CStr::from_ptr(text as *const c_char);
|
||||||
|
|
||||||
// sqlite3_value_text returns UTF8 data, so our unwrap here should be fine.
|
let s = s.to_bytes();
|
||||||
let s = s
|
|
||||||
.to_str()
|
|
||||||
.expect("sqlite3_value_text returned invalid UTF-8");
|
|
||||||
ValueRef::Text(s)
|
ValueRef::Text(s)
|
||||||
}
|
}
|
||||||
ffi::SQLITE_BLOB => {
|
ffi::SQLITE_BLOB => {
|
||||||
|
Loading…
Reference in New Issue
Block a user