Lokathor/bytemuck

Soundness issue: `TransparentWrapper::wrap` and `<_>::peel` cause a double drop

CAD97 opened this issue · 0 comments

CAD97 commented

If you only use TransparentWrapper for Copy types, this is completely fine, and will not cause issues

[playground]

use bytemuck::TransparentWrapper; // 1.7.0

#[derive(TransparentWrapper)]
#[repr(transparent)]
struct UhOh(Box<usize>);

fn main() {
    let b = Box::new(5);
    UhOh::wrap(b);
}
     Running `target/debug/playground`
free(): double free detected in tcache 2
timeout: the monitored command dumped core

The issue is in the definition of wrap/peel:

/// Convert the inner type into the wrapper type.
#[inline]
fn wrap(s: Inner) -> Self
where
Self: Sized,
Inner: Sized,
{
// SAFETY: The unsafe contract requires that `Self` and `Inner` have
// identical representations.
unsafe { transmute_copy(&s) }
}

This uses transmute_copy to create a copy of the input value without forgetting it, causing the value to be dropped and then a duplicate returned to the caller. The fix is to forget the input value by wrapping it in ManuallyDrop.