Repository: bevyengine/bevy
File: crates/bevy_ptr/src/lib.rs (Rust)

Code before:
/// [`assign_to`]: MovingPtr::assign_to
#[macro_export]
macro_rules! deconstruct_moving_ptr {
    ({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
        let mut ptr: $crate::MovingPtr<_, _> = $ptr;
        let _ = || {
            let value = &mut *ptr;
            // Ensure that each field index exists and is mentioned only once
            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
            let _ = ($(&mut value.$field_index),*);
            // Ensure that `ptr` is a tuple and not something that derefs to it
            // Ensure that the number of patterns matches the number of fields
            fn unreachable<T>(_index: usize) -> T {
                unreachable!()
            }
            *value = ($(unreachable($field_index)),*);
        };
        // SAFETY:
        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
        // - `mem::forget` is called on `self` immediately after these calls
        // - Each field is distinct, since otherwise the block of code above would fail compilation
        $(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
        core::mem::forget(ptr);
    };
    ({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
        let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;
        let _ = || {
            // SAFETY: This closure is never called
            let value = unsafe { ptr.assume_init_mut() };
            // Ensure that each field index exists and is mentioned only once
            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
            let _ = ($(&mut value.$field_index),*);
            // Ensure that `ptr` is a tuple and not something that derefs to it
            // Ensure that the number of patterns matches the number of fields
            fn unreachable<T>(_index: usize) -> T {
                unreachable!()
            }
            *value = ($(unreachable($field_index)),*);
        };
        // SAFETY:
        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
        // - `mem::forget` is called on `self` immediately after these calls
        // - Each field is distinct, since otherwise the block of code above would fail compilation
        $(let $pattern = unsafe { ptr.move_maybe_uninit_field(|f| &raw mut (*f).$field_index) };)*
        core::mem::forget(ptr);
    };
    ({ let $struct_name:ident { $($field_index:tt$(: $pattern:pat)?),* $(,)? } = $ptr:expr ;}) => {

Review comment (security):
This seems to still be vulnerable to the deref issue since there's nothing checking that `MovingPtr` points to a tuple nor that `$field_index` is actually a tuple index.

Code after:
///   assert_eq!(target_c.assume_init().0, 33);
/// }
/// ```
///
/// [`assign_to`]: MovingPtr::assign_to
#[macro_export]
macro_rules! deconstruct_moving_ptr {
    ({ let tuple { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
        let mut ptr: $crate::MovingPtr<_, _> = $ptr;
        let _ = || {
            let value = &mut *ptr;
            // Ensure that each field index exists and is mentioned only once
            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
            core::hint::black_box(($(&mut value.$field_index,)*));
            // Ensure that `ptr` is a tuple and not something that derefs to it
            // Ensure that the number of patterns matches the number of fields
            fn unreachable<T>(_index: usize) -> T {
                unreachable!()
            }
            *value = ($(unreachable($field_index),)*);
        };
        // SAFETY:
        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
        // - `mem::forget` is called on `self` immediately after these calls
        // - Each field is distinct, since otherwise the block of code above would fail compilation
        $(let $pattern = unsafe { ptr.move_field(|f| &raw mut (*f).$field_index) };)*
        core::mem::forget(ptr);
    };
    ({ let MaybeUninit::<tuple> { $($field_index:tt: $pattern:pat),* $(,)? } = $ptr:expr ;}) => {
        // Specify the type to make sure the `mem::forget` doesn't forget a mere `&mut MovingPtr`
        let mut ptr: $crate::MovingPtr<core::mem::MaybeUninit<_>, _> = $ptr;
        let _ = || {
            // SAFETY: This closure is never called
            let value = unsafe { ptr.assume_init_mut() };
            // Ensure that each field index exists and is mentioned only once
            // Ensure that the struct is not `repr(packed)` and that we may take references to fields
            core::hint::black_box(($(&mut value.$field_index,)*));
            // Ensure that `ptr` is a tuple and not something that derefs to it
            // Ensure that the number of patterns matches the number of fields
            fn unreachable<T>(_index: usize) -> T {
                unreachable!()
            }
            *value = ($(unreachable($field_index),)*);
        };
        // SAFETY:
        // - `f` does a raw pointer offset, which always returns a non-null pointer to a field inside `T`
        // - The struct is not `repr(packed)`, since otherwise the block of code above would fail compilation
        // - `mem::forget` is called on `self` immediately after these calls
        // - Each field is distinct, since otherwise the block of code above would fail compilation