-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider having transmute also complain if the pointed-to objects are of different sizes #21590
Comments
It wasn't actually memory corruption; it was the presence of NonNull (via the Box) within one of the types contained in the Option that was the target of the transmute. This caused the enum layout optimization code to deduce that it could use the NonNull value as the discriminant for the transmuted Option, which is what caused us to see Some values where the pre-transmute value was None. |
For clarity, this is essentially what we had: struct PreTransmute {
ptr: *const (),
}
struct PostTransmute {
ptr: Box<Something>,
}
let some_value: RefCell<Option<PreTransmute>> = RefCell::new(None);
let tmp = some_value.borrow();
let some_other_value: Ref<Option<PostTransmute>> = unsafe { mem::transmute(tmp) }; and some_other_value would now be classified as Some. |
This seems like a generalization of |
Since struct layout is undefined, transmuting one type to another is probably a bad idea in the general case, unless they're both |
Triage: no change that I'm aware of. |
Triage: no changes I'm aware of |
This cannot be made an error specifically with raw pointers because it may be okay. The following code is valid (though odd): let arr: [u8; 4] = [1, 2, 3, 4];
let arr_ptr: *const u8 = arr.as_ptr();
unsafe {
let u32_ptr: *const u32 = core::mem::transmute::<_, *const u32>(arr_ptr);
let u32_val = u32_ptr.read_unaligned();
assert_eq!(u32_val.to_ne_bytes(), arr);
} Of course, transmuting between pointers should not be done, in favor of |
As @asquared31415 noted this cannot be made an error (breaks backcompat, churns too much code) and is a duplicate otherwise with issues like #34249 which recommend linting against transmutes of pointers in a more general fashion. |
Today,
cast::transmute
will complain if the subjects of the transmute are different sizes. However, if those objects are pointers and the pointed-to objects are different sizes, it will not complain.This was an issue in Servo because we had two structs that were identical before a Rust upgrade, but after a Rust upgrade some smart pointer-related optimizations changed the layout of one of the structs, resulting in a silent memory corruption. The solution was to add a
NonZero
wrapper to one of the raw pointers within the structs to disable the compiler optimization (servo/servo@f400d79), but this feels fragile.The text was updated successfully, but these errors were encountered: