-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
std::ptr::write_bytes
should clearly explain safety and validity invariants
#84184
Comments
From the Reference:
This does indeed seem to be canonical UB! The documentation should either explain that this first |
The docs on
However the example after proceeds to do exactly that and is breaking both the safety invariants of the function and causes UB. |
I think this code is technically fine under our current UB rules since the "bad" The following would be definite UB: use std::ptr;
let mut v = Box::new(0i32);
unsafe {
// Leaks the previously held value by overwriting the `Box<T>` with
// a null pointer.
ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
}
let v2 = v; // UB! We are doing a typed copy of a `Box` that does not satisfy its validity invariant. This is an instance of rust-lang/unsafe-code-guidelines#84. |
I suppose that's true, but even if the example isn't UB it breaks the safety requirements of the function and probably is not a good example. |
🤔 I see, I misunderstood. It seems that describing the situation more accurately in the reference is also desirable, though that should perhaps be logged as an issue against the reference. Roughly it seems like the actual UB is "Permitting an invalid value to be observed, or interacting with a memory location that contains an invalid value in any way other than assigning a new value to it". The reference already mentions it is non-exhaustive (and also non-normative) so it's fine if this doesn't include all the possible cases. It seems these kinds of considerations about "validity invariants" and "safety invariants" should be discussed, briefly, at the top of |
That "validity" is actually orthogonal to the one in that reference page... the But yes, this issue of validity invariants is cross-cutting. Another good place to put this (and to link to from everywhere else) could be in the
We should probably use some more-or-less arbitrary but specific term ("construct" seems okay to me) but then have a dedicated paragraph defining what exactly that means. |
std::ptr::write_bytes
documentation example is UBstd::ptr::write_bytes
should clearly explain safety and validity invariants
I just came upon this independently because I had reason to be reading over the docs for I don't understand what exactly "safety and validity invariants" mentioned in the title of this issue are, but I would prefer to see the docs here touched up a little bit. As a non-expert in the UCG I do not understand how Therefore, I think it would be a significant improvement to the docs if they acknowledged that this pattern is subtle but valid. The comment /// unsafe {
/// // This `&mut v` does not count as a use of `v`, but lets us write a valid value over the invalid `Box`
/// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
/// }
///
/// // Because we've re-established the invariants of the Box before using it, we can now do whatever we want in safe code.
/// assert_eq!(*v, 42); |
I think it should be valid, but I don't think we have an RFC or a lang-team decision saying that it is valid. So we can't really recommend using it in the docs currently. |
But there's an example in the docs that uses this pattern, isn't that equivalent to a recommendation? Should this pattern be eliminated from the docs for now? |
Hm, good point... |
This is an example code snippet for
std::ptr::write_bytes
:This example writes a null pointer to a box, which (verbatim!) "is invalid according to basic type layout invariants". Then it incorrectly states that this is fine as long as we do not "touch" the box, while really this is already UB. This looks like a documentation bug to me.
As a side note: why is
Unique<T>
not intended to be stabilized? The strong aliasing guarantees could be useful in someone's unsafe code.The text was updated successfully, but these errors were encountered: