Skip to content

FFI mode does not support accessing C-allocated memory from Rust #4647

@weiznich

Description

@weiznich
error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got 0x7f9b3e6b5fd0[noalloc] which is a dangling pointer (it has no provenance)
    --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/sqlite_value.rs:98:25
     |
  98 |               let bytes = slice::from_raw_parts(
     |  _________________________^
  99 | |                 ptr,
 100 | |                 len.try_into()
 101 | |                     .expect("Diesel expects to run at least on a 32 bit platform"),
 102 | |             );
     | |_____________^ Undefined Behavior occurred here
     |
     = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
     = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
     = note: BACKTRACE on thread `deserialization`:
     = note: inside `diesel::sqlite::SqliteValue::<'_, '_, '_>::parse_string::<'_, &str, {closure@diesel::sqlite::SqliteValue<'_, '_, '_>::read_text::{closure#0}}>` at /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/sqlite_value.rs:98:25: 102:14
note: inside `diesel::sqlite::SqliteValue::<'_, '_, '_>::read_text`

Relevant diesel code:

https://github.com/diesel-rs/diesel/blob/a641d7cc5f792412ded9ffdab3134fa473a57596/diesel/src/sqlite/connection/sqlite_value.rs#L96-L102

I believe this code is sound as these pointer is returned by libsqlite3 and that's just a common way to return a string (as ptr + lenght)

Now the problem might be that the ptr is allocated and returned from the C code, so miri doesn't know much about it and assumes that it is not aligned because of that?

Full Error
test deserialization::check_deserialize_composite_ptr_types ... warning: sharing memory with a native function called via FFI
   --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/raw.rs:53:13
    |
 53 |             ffi::sqlite3_open_v2(database_url.as_ptr(), &mut conn_pointer, flags, ptr::null())
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function
    |
    = help: when memory is shared with a native function call, Miri stops tracking initialization and provenance for that memory
    = help: in particular, Miri assumes that the native call initializes all memory it has access to
    = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory
    = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free
    = note: BACKTRACE on thread `deserialization`:
    = note: inside `diesel::sqlite::connection::raw::RawConnection::establish` at /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/raw.rs:53:13: 53:95
note: inside `diesel::SqliteConnection::establish_inner`
   --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/mod.rs:602:30
    |
602 |         let raw_connection = RawConnection::establish(database_url)?;
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `<diesel::SqliteConnection as diesel::Connection>::establish`
   --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/mod.rs:225:32
    |
225 |         let establish_result = Self::establish_inner(database_url);
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `schema::backend_specific_connection`
   --> diesel_tests/tests/schema/mod.rs:284:20
    |
284 |     let mut conn = SqliteConnection::establish(":memory:").unwrap();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `schema::connection_without_transaction`
   --> diesel_tests/tests/schema/mod.rs:253:22
    |
253 |     let mut result = backend_specific_connection();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `schema::connection`
   --> diesel_tests/tests/schema/mod.rs:243:22
    |
243 |     let mut result = connection_without_transaction();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `deserialization::check_deserialize_composite_ptr_types`
   --> diesel_tests/tests/deserialization.rs:70:21
    |
 70 |     let conn = &mut connection();
    |                     ^^^^^^^^^^^^
note: inside closure
   --> diesel_tests/tests/deserialization.rs:69:43
    |
 68 | #[diesel_test_helper::test]
    | --------------------------- in this attribute macro expansion
 69 | fn check_deserialize_composite_ptr_types() {
    |                                           ^
    = note: this warning originates in the attribute macro `test` which comes from the expansion of the attribute macro `diesel_test_helper::test` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got 0x7f9b3e6b5fd0[noalloc] which is a dangling pointer (it has no provenance)
    --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/sqlite_value.rs:98:25
     |
  98 |               let bytes = slice::from_raw_parts(
     |  _________________________^
  99 | |                 ptr,
 100 | |                 len.try_into()
 101 | |                     .expect("Diesel expects to run at least on a 32 bit platform"),
 102 | |             );
     | |_____________^ Undefined Behavior occurred here
     |
     = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
     = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
     = note: BACKTRACE on thread `deserialization`:
     = note: inside `diesel::sqlite::SqliteValue::<'_, '_, '_>::parse_string::<'_, &str, {closure@diesel::sqlite::SqliteValue<'_, '_, '_>::read_text::{closure#0}}>` at /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/sqlite_value.rs:98:25: 102:14
note: inside `diesel::sqlite::SqliteValue::<'_, '_, '_>::read_text`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/connection/sqlite_value.rs:120:9
     |
 120 |         self.parse_string(|s| s)
     |         ^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `diesel::sqlite::types::<impl diesel::deserialize::FromSql<diesel::sql_types::Text, diesel::sqlite::Sqlite> for *const str>::from_sql`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/sqlite/types/mod.rs:22:20
     |
  22 |         let text = value.read_text();
     |                    ^^^^^^^^^^^^^^^^^
note: inside `<*const str as diesel::deserialize::FromSql<diesel::sql_types::Text, diesel::sqlite::Sqlite>>::from_nullable_sql`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/deserialize.rs:471:28
     |
 471 |             Some(bytes) => Self::from_sql(bytes),
     |                            ^^^^^^^^^^^^^^^^^^^^^
note: inside `<*const str as diesel::deserialize::FromStaticSqlRow<diesel::sql_types::Text, diesel::sqlite::Sqlite>>::build_from_row::<'_, diesel::row::private::PartialRow<'_, diesel::sqlite::connection::row::SqliteRow<'_, '_>>>`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/deserialize.rs:574:9
     |
 574 |         T::from_nullable_sql(field.value()).map_err(|e| {
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `<*const str as diesel::deserialize::FromSqlRow<diesel::sql_types::Text, diesel::sqlite::Sqlite>>::build_from_row::<'_, diesel::row::private::PartialRow<'_, diesel::sqlite::connection::row::SqliteRow<'_, '_>>>`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/deserialize.rs:559:19
     |
 559 |         let row = <T::Row as FromStaticSqlRow<ST, DB>>::build_from_row(row)?;
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `diesel::type_impls::tuples::<impl diesel::deserialize::FromStaticSqlRow<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite> for (i32, *const str, *const [u8])>::build_from_row::<'_, diesel::sqlite::connection::row::SqliteRow<'_, '_>>`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/type_impls/tuples.rs:603:1
     |
 603 | diesel_derives::__diesel_for_each_tuple!(tuple_impls);
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `<deserialization::User as diesel::deserialize::FromSqlRow<(diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>>::build_from_row::<'_, diesel::sqlite::connection::row::SqliteRow<'_, '_>>`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/deserialize.rs:559:19
     |
 559 |         let row = <T::Row as FromStaticSqlRow<ST, DB>>::build_from_row(row)?;
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `diesel::query_dsl::load_dsl::private::LoadIter::<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>::map_row`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/load_dsl.rs:131:21
     |
 131 |                     U::build_from_row(&row).map_err(crate::result::Error::DeserializationError),
     |                     ^^^^^^^^^^^^^^^^^^^^^^^
note: inside `<diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite> as std::iter::Iterator>::next`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/load_dsl.rs:148:13
     |
 148 |             Self::map_row(self.cursor.next())
     |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     = note: inside `<diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite> as std::iter::Iterator>::try_fold::<(), {closure@<std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>> as std::iter::Iterator>::try_fold<(), {closure@std::iter::Iterator::try_for_each::call<deserialization::User, std::ops::ControlFlow<deserialization::User>, fn(deserialization::User) -> std::ops::ControlFlow<deserialization::User> {std::ops::ControlFlow::<deserialization::User>::Break}>::{closure#0}}, std::ops::ControlFlow<deserialization::User>>::{closure#0}}, std::ops::ControlFlow<std::ops::ControlFlow<deserialization::User>>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2426:29: 2426:40
     = note: inside `<std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>> as std::iter::Iterator>::try_fold::<(), {closure@std::iter::Iterator::try_for_each::call<deserialization::User, std::ops::ControlFlow<deserialization::User>, fn(deserialization::User) -> std::ops::ControlFlow<deserialization::User> {std::ops::ControlFlow::<deserialization::User>::Break}>::{closure#0}}, std::ops::ControlFlow<deserialization::User>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/mod.rs:191:9: 198:15
     = note: inside `<std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>> as std::iter::Iterator>::try_for_each::<fn(deserialization::User) -> std::ops::ControlFlow<deserialization::User> {std::ops::ControlFlow::<deserialization::User>::Break}, std::ops::ControlFlow<deserialization::User>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2488:9: 2488:35
     = note: inside `<std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>> as std::iter::Iterator>::next` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/mod.rs:174:9: 174:46
     = note: inside `<std::vec::Vec<deserialization::User> as std::vec::spec_from_iter_nested::SpecFromIterNested<deserialization::User, std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>>>>::from_iter` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/spec_from_iter_nested.rs:24:32: 24:47
     = note: inside `<std::vec::Vec<deserialization::User> as std::vec::spec_from_iter::SpecFromIter<deserialization::User, std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>>>>::from_iter` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/spec_from_iter.rs:33:9: 33:48
     = note: inside `<std::vec::Vec<deserialization::User> as std::iter::FromIterator<deserialization::User>>::from_iter::<std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3689:9: 3689:76
     = note: inside `<std::iter::adapters::GenericShunt<'_, diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, std::result::Result<std::convert::Infallible, diesel::result::Error>> as std::iter::Iterator>::collect::<std::vec::Vec<deserialization::User>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2028:9: 2028:38
     = note: inside closure at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:2151:49: 2151:60
     = note: inside `std::iter::adapters::try_process::<diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>, deserialization::User, std::result::Result<std::convert::Infallible, diesel::result::Error>, {closure@<std::result::Result<std::vec::Vec<deserialization::User>, diesel::result::Error> as std::iter::FromIterator<std::result::Result<deserialization::User, diesel::result::Error>>>::from_iter<diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>>::{closure#0}}, std::vec::Vec<deserialization::User>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/mod.rs:160:17: 160:25
     = note: inside `<std::result::Result<std::vec::Vec<deserialization::User>, diesel::result::Error> as std::iter::FromIterator<std::result::Result<deserialization::User, diesel::result::Error>>>::from_iter::<diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:2151:9: 2151:61
     = note: inside `<diesel::query_dsl::load_dsl::private::LoadIter<deserialization::User, diesel::sqlite::connection::statement_iterator::StatementIterator<'_, '_>, (diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Binary), diesel::sqlite::Sqlite> as std::iter::Iterator>::collect::<std::result::Result<std::vec::Vec<deserialization::User>, diesel::result::Error>>` at /home/weiznich/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2028:9: 2028:38
note: inside `<diesel::query_builder::select_statement::SelectStatement<diesel::query_builder::from_clause::FromClause<deserialization::my_users::table>, diesel::query_builder::select_clause::SelectClause<diesel::expression::select_by::SelectBy<deserialization::User, diesel::sqlite::Sqlite>>> as diesel::RunQueryDsl<diesel::SqliteConnection>>::load::<'_, deserialization::User>`
    --> /home/weiznich/Documents/rust/diesel/diesel/src/query_dsl/mod.rs:1594:9
     |
1594 |         self.internal_load(conn)?.collect()
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `deserialization::check_deserialize_composite_ptr_types`
    --> diesel_tests/tests/deserialization.rs:101:13
     |
 101 |       let r = my_users::table
     |  _____________^
 102 | |         .select(User::as_select())
 103 | |         .load(conn)
     | |___________________^
note: inside closure
    --> diesel_tests/tests/deserialization.rs:69:43
     |
  68 | #[diesel_test_helper::test]
     | --------------------------- in this attribute macro expansion
  69 | fn check_deserialize_composite_ptr_types() {
     |                                           ^
     = note: this error originates in the macro `impl_from_sql_row` which comes from the expansion of the attribute macro `diesel_test_helper::test` (in Nightly builds, run with -Z macro-backtrace for more info)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-nativeArea: calling native functions via FFIC-enhancementCategory: a PR with an enhancement or an issue tracking an accepted enhancement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions