From 4d51cbdff0e0742d081147c7d08be700534041e9 Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Mon, 8 Jul 2024 22:59:04 -0400 Subject: [PATCH] Handle::from_raw() and HandleAlloc::clone_handle()/consume_handle() are all unsafe. Fixes #2164 --- uniffi_core/src/ffi/ffiserialize.rs | 2 +- uniffi_core/src/ffi/handle.rs | 4 ++- uniffi_core/src/ffi_converter_traits.rs | 38 +++++++++++++------------ 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/uniffi_core/src/ffi/ffiserialize.rs b/uniffi_core/src/ffi/ffiserialize.rs index 50ae78840a..edbeb51229 100644 --- a/uniffi_core/src/ffi/ffiserialize.rs +++ b/uniffi_core/src/ffi/ffiserialize.rs @@ -275,7 +275,7 @@ mod test { rust_buffer.len(), rust_buffer.capacity(), ); - let handle = Handle::from_raw(101).unwrap(); + let handle = unsafe { Handle::from_raw(101).unwrap() }; let rust_call_status = RustCallStatus::default(); let rust_call_status_error_buf = &rust_call_status.error_buf; let orig_rust_call_status_buffer_data = ( diff --git a/uniffi_core/src/ffi/handle.rs b/uniffi_core/src/ffi/handle.rs index b56c16d538..8ca66a41de 100644 --- a/uniffi_core/src/ffi/handle.rs +++ b/uniffi_core/src/ffi/handle.rs @@ -28,7 +28,9 @@ impl Handle { self.0 as *const T } - pub fn from_raw(raw: u64) -> Option { + /// # Safety + /// The raw value must be a valid handle as described above. + pub unsafe fn from_raw(raw: u64) -> Option { if raw == 0 { None } else { diff --git a/uniffi_core/src/ffi_converter_traits.rs b/uniffi_core/src/ffi_converter_traits.rs index 86e29e7f50..d796648899 100644 --- a/uniffi_core/src/ffi_converter_traits.rs +++ b/uniffi_core/src/ffi_converter_traits.rs @@ -449,18 +449,24 @@ pub unsafe trait HandleAlloc: Send + Sync { /// This creates a new handle from an existing one. /// It's used when the foreign code wants to pass back an owned handle and still keep a copy /// for themselves. - fn clone_handle(handle: Handle) -> Handle; + /// # Safety + /// The handle must be valid. + unsafe fn clone_handle(handle: Handle) -> Handle; /// Get a clone of the `Arc<>` using a "borrowed" handle. /// - /// Take care that the handle can not be destroyed between when it's passed and when + /// # Safety + /// The handle must be valid. Take care that the handle can + /// not be destroyed between when it's passed and when /// `get_arc()` is called. #1797 is a cautionary tale. - fn get_arc(handle: Handle) -> Arc { + unsafe fn get_arc(handle: Handle) -> Arc { Self::consume_handle(Self::clone_handle(handle)) } /// Consume a handle, getting back the initial `Arc<>` - fn consume_handle(handle: Handle) -> Arc; + /// # Safety + /// The handle must be valid. + unsafe fn consume_handle(handle: Handle) -> Arc; } /// Derive FFI traits @@ -596,19 +602,15 @@ macro_rules! derive_ffi_traits { $crate::Handle::from_pointer(::std::sync::Arc::into_raw(::std::sync::Arc::new(value))) } - fn clone_handle(handle: $crate::Handle) -> $crate::Handle { - unsafe { - ::std::sync::Arc::<::std::sync::Arc>::increment_strong_count(handle.as_pointer::<::std::sync::Arc>()); - } + unsafe fn clone_handle(handle: $crate::Handle) -> $crate::Handle { + ::std::sync::Arc::<::std::sync::Arc>::increment_strong_count(handle.as_pointer::<::std::sync::Arc>()); handle } - fn consume_handle(handle: $crate::Handle) -> ::std::sync::Arc { - unsafe { - ::std::sync::Arc::::clone( - &std::sync::Arc::<::std::sync::Arc::>::from_raw(handle.as_pointer::<::std::sync::Arc>()) - ) - } + unsafe fn consume_handle(handle: $crate::Handle) -> ::std::sync::Arc { + ::std::sync::Arc::::clone( + &std::sync::Arc::<::std::sync::Arc::>::from_raw(handle.as_pointer::<::std::sync::Arc>()) + ) } } }; @@ -626,12 +628,12 @@ unsafe impl HandleAlloc for T { Handle::from_pointer(Arc::into_raw(value)) } - fn clone_handle(handle: Handle) -> Handle { - unsafe { Arc::increment_strong_count(handle.as_pointer::()) }; + unsafe fn clone_handle(handle: Handle) -> Handle { + Arc::increment_strong_count(handle.as_pointer::()); handle } - fn consume_handle(handle: Handle) -> Arc { - unsafe { Arc::from_raw(handle.as_pointer()) } + unsafe fn consume_handle(handle: Handle) -> Arc { + Arc::from_raw(handle.as_pointer()) } }