-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Document that casting &mut T to &mut MaybeUninit<T> is not safe #66699
Comments
In the example you are already required to wrap the code in |
@jannickj if you try to write a safe wrapper around FWIW, there's at least one crate in the wild that is unsound because of this mistake. Hey @danielhenrymantilla you probably want to fix it. I wrote you an e-mail regarding other stuff, no reply yet. |
@Kixunil yes, thanks for the e-mail, I've been quite busy lately so I have not had much time to address this (or answer the e-mail 😉), but I'll try to have it fixed by tomorrow, with the previous versions being yanked (and the repo being published). So, to summarize the issue, it turns out that Which, when |
Yes, I believe that's sound. Since I didn't get the answer to the e-mail I started creating a new crate from scratch that's addressing my needs. :) It's not published yet, but has bunch of other cool stuff. (Solves the same problem for slices, has tons of helper methods, iterator, safe cursor...) We can still cooperate if you want. |
FYI, here's the crate: https://crates.io/crates/possibly_uninit I hope it will help prevent these kinds of bugs. |
Interestingly |
How hard would it be to add some basic abstractions into |
To me this looks like someone mistakenly assumed But, sure, if someone has a good suggestions for where in the |
@Kixunil Having a user-defined
See #63569. However, what you are asking for is not "something for slices and mutable references to |
Thanks for recommendation, good point, I will change it (that's why I called it "preview" :)). Is the name |
However, note that there is AFAIK no way to implement safe |
OK, I will rename it to Yes, the lack of enforcing is something I noticed. It's the primary reason I added It is totally true that " |
…om_init` Well, that's weird. I've had a safety comment: ```rust // `MaybeUninit<T>` is guaranteed to have the same ABI as `T`, so // it's safe to cast `&mut [T]` to `&mut [MaybeUninit<T>]` ``` But it's wrong. `&mut T` and `T` isn't the same thing. While it's true that `T => MaybeUninit<T>` or the same for an owned container (array, box, etc) should be fine, for an unique borrowed container (`&mut _`, `&mut [_]`) it is definitely **not fine**, because the original owned value remains `T`. Example of such a UB in safe code: ```rust let mut a = ["string"]; <_>::from_init_mut(&mut a[..])[0] = MaybeUninit::uninit(); println!("{}", a); // segfault ``` You can also think of `MaybeUninit<T>` as a supertype of `T` and then note that `&mut T` is invariant over `T`: https://doc.rust-lang.org/nomicon/subtyping.html#variance The weirdest part of all of this is that I haven't tested those functions. There aren't any tests. There aren't any test for safe function with unsafe in it! I am ashamed... A related issue in `rust-lang` repo, about documenting unsoundness of `&mut T => &mut MaybeUninit<T>`: rust-lang/rust#66699
By the way, this issue is related to another interesting one: for |
When I first saw the title, I was expecting that casting is |
Is |
It's not always unsound, just sometimes. The usual way of describing this is unsafe. |
Something cannot be sometimes unsound -- it is either unsound or not. Unsafe does not imply unsound or sound. |
It's unsound if you write MaybeUninit::uninit to it, or expose it to safe code you don't control (that can do this trivially). It's sound otherwise. |
That means it is unsound. It doesn't matter that sometimes there may not be code triggering the UB. |
So the title should be "Document that casting &mut T to &mut MaybeUninit and exposing it to safe code is not sound" |
As discussed on Reddit, it turns out that casting
&mut T
to&mut MaybeUninit<T>
is not a safe operation, since it allows UB in safe code.Playground example demonstrating the UB: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=93dd41cf851bfc0de2233e0a83b4b778
It is probably a good idea to explicitly point that out in MaybeUninit docs.
The text was updated successfully, but these errors were encountered: