-
Notifications
You must be signed in to change notification settings - Fork 59
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
When using std::ptr::copy
and similar methods, does the memory need to be valid for T?
#330
Comments
It's not UB necessarily, but it is semantically different. The implementation is permitted to not copy padding bytes and/or make them uninit in the destination if you copy a u32 as a Relevant discussion: rust-lang/rust#63159 . The resolution of that issue will determine whether |
About the UB issue, AFAIU the whole point of raw pointers operations (ie let src: MaybeUninit<i32> = MaybeUninit::uninit();
let mut dst: MaybeUninit<i32> = MaybeUninit::uninit();
let src_ptr: *const i32 = src.as_ptr();
let dest_ptr: *mut i32 = dest.as_mut_ptr();
unsafe {ptr::copy(src_ptr, dest_ptr, 1);} because we never created a reference to but as @digama0 said, the type is used for more than just size+align, I read this code as "Copy the values like you would with *ptr = value; without asserting the validity of the value", so when you copy a bool it could just copy a single bit and ignore the rest, just like with a regular bool write. |
@elichai That's not my impression, although you might be right in the specific case of Edit: Miri will currently report UB if you use |
Well, to use |
As was already noted, this is basically the same as rust-lang/rust#63159: do these operations do a typed copy (like a For backwards compatibility, we probably have to go with the latter here. |
With
👍 |
Looks like (swap/copy) overlapping/non-overlapping were all documented as being untyped in rust-lang/rust#97712. So the answer is "no", for all but write_bytes. Which says
Which I'm not sure if that's saying "of course you can't use a fn main() {
let mut x: u8 = 0;
unsafe {
std::ptr::write_bytes::<bool>(&mut x as *mut u8 as *mut bool, 42, 1);
}
} By the strictest reading of the docs, this is UB. Miri doesn't complain on this. |
Oh, good catch. Yes as far as I am concerned that was always meant to just mean "of course you can't use a [42_u8] as a bool". |
clarify how write_bytes can lead to UB due to invalid values Fixes rust-lang/unsafe-code-guidelines#330 Cc `@5225225`
clarify how write_bytes can lead to UB due to invalid values Fixes rust-lang/unsafe-code-guidelines#330 Cc ``@5225225``
Looks like this is done! The answer for all ptr methods that don't take/return a T by value (swap, copy, write_bytes) is "no. Only the size and align is used". Now if that's actually respected is another story, see rust-lang/rust#99604. But I think at least the docs say that won't happen, so that's an implementation bug that can be tracked there. |
clarify how write_bytes can lead to UB due to invalid values Fixes rust-lang/unsafe-code-guidelines#330 Cc ``@5225225``
Plenty of methods in std::ptr take a generic T and use
*mut/const T
, but does this mean that the following code is UB?What about copying a
u32
as a(u16, u8)
, or a(u16, u8, !)
, that doesn't uninit any padding, right?Same question applies to
copy_nonoverlapping
,swap
(_nonoverlapping
),write_bytes
. I don't see any other methods that this would apply to.What about copying a pointer with an integer type, that preserves provenance?
I'd be inclined to say "no, it's not UB, the generic parameter is only used for its size and alignment, no other property of the type matters", but if that's the case, we should make that clear. It definitely seems to be implied.
The text was updated successfully, but these errors were encountered: