-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Document MaybeUninit bit validity #140463
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
base: master
Are you sure you want to change the base?
Conversation
/// If `T` contains initialized bytes at byte offsets where `U` contains padding bytes, these | ||
/// may not be preserved in `MaybeUninit<U>`, and so `transmute(u)` may produce a `T` with | ||
/// uninitialized bytes in these positions. This is an active area of discussion, and this code | ||
/// may become sound in the future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RalfJung I'd like some advice on this. I'm confident that this is correct as written, but could we perhaps make a stronger statement?
In particular, what happens if we round-trip a value which is invalid for U
but where U
nonetheless contains initialized bytes? For example, is 3u8 -> MaybeUninit<bool> -> u8
guaranteed to produce 3u8
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per rust-lang/unsafe-code-guidelines#555 (comment), I've updated to the following text. Does that look good?
/// Note that, so long as every byte position which is initialized in `T` is also initialized
/// in `U`, then the preceding `identity` example *is* sound.
@@ -252,6 +252,33 @@ use crate::{fmt, intrinsics, ptr, slice}; | |||
/// std::process::exit(*code); // UB! Accessing uninitialized memory. | |||
/// } | |||
/// ``` | |||
/// | |||
/// # Validity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving this discussion here:
The
MaybeUninit
docs probably make sense for this. We now do have a definition of "byte" in the reference that this can link to.Okay, awesome. And what wording would you recommend? Would it be accurate to say something like the following?
The value of a
[MaybeUninit<u8>; N]
may contain pointer provenance, and sop: P -> [MaybeUninit<u8>; N] -> P
preserves the value ofp
, including provenance
@RalfJung would you like me to add language like this to this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: I've added the following as a more concrete and fleshed out draft. I can edit or remove as preferred.
/// # Provenance
///
/// `MaybeUninit` values may contain [pointer provenance][provenance]. Concretely, for any
/// pointer type, `P`, which contains provenance, transmuting `p: P` to
/// `MaybeUninit<[u8; size_of::<P>]>` and then back to `P` will produce a value identical to
/// `p`, including provenance.
///
/// [provenance]: ../ptr/index.html#provenance
Partially addresses rust-lang/unsafe-code-guidelines#555 by clarifying that it is sound to write any byte values (initialized or uninitialized) to any
MaybeUninit<T>
regardless ofT
.r? @RalfJung