-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Add std::mem::zero #2291
RFC: Add std::mem::zero #2291
Conversation
Note that |
This is added functionality that I think complements |
Seems an opportunity for lots of UB |
text/0000-mem-zero.md
Outdated
pub unsafe fn zero<T: ?Sized>(val: &mut T) { | ||
let len = mem::size_of_val(val); | ||
let ptr = val as *mut T as *mut u8; | ||
intrinsics::write_bytes(ptr, 0, len); |
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.
@nvzqz It'd be nice to at least change this to ptr::write_bytes
.
@iitalics in the cases of mem::zeroed and mem::unitialized UB is quite possible thus the functions are marked as unsafe and the documentation with them describes how to use it without causing UB. Adding another function like this really isn't a problem in that sense as long as it is marked as unsafe and it is documented on how to use it safely. These functions have a place when doing things with FFI or other low level operations. This is just an extension of that. |
Is this intended as a good thing? I might be wrong, but it seems like zeroing a trait object is always undefined behavior, right? Why would you want to zero a vtable? |
The vtable pointer isn't in the trait object data though, it's in the fat pointer, next to the data pointer. |
So zeroing a trait object does not mean this? let x: &mut Any;
unsafe { mem::zero(x) }; |
@mark-i-m that's distinct from |
Can a post-monomorphization lint check if Being able to do that seems like a good reason to include in in the standard library. Because that seems super easy to get wrong. |
Even if this can be expressed outside of the stdlib, one of the primary features of the stdlib is to give some assurance that unsafe functions have been considered and vetted. When it comes to unsafe utility functions I am very much in favor of stdlib maximalism--as long as someone finds it useful, that is. That said, this function as proposed doesn't actually guarantee that the data is zeroed, correct? If not, then cryptography implementations will find this function lacking. Is that worth supporting? |
We could have a |
I'm not convinced by that for |
If the function is already |
The Or you could create an auto trait... auto trait MaybeZeroSafe {}
impl<T: Zeroable> !MaybeZeroSafe for NonZero<T> {}
impl<T: ?Sized> !MaybeZeroSafe for &T {}
impl<T: ?Sized> !MaybeZeroSafe for &mut T {}
impl !MaybeZeroSafe for /*** all kinds of function pointers ***/ {}
unsafe fn zero<T: ?Sized + MaybeZeroSafe>(x: &mut T) {} ... this feels extremely heavy-handed though. |
@scottmcm I consider these the same concern though: unsafe code is unsafe code. The difference is just that a safe API has zero invariants that callers must uphold, and an unsafe API has one or more invariants that callers must uphold; if the unsafe code inside an unsafe function is incorrectly implemented, there may secretly exist undocumented invariants that can result in surprising cases of memory unsafety. Just because a function is marked as |
While this is true, unsafe code should still try to be as safe as possible. In this case, making it take *mut T stops it from violating the guarantee that &mut T must point to valid data for a type. |
The libs team discussed this today and we felt that this is too niche to be part of the standard library: @rfcbot fcp close Especially given that:
With manual inlining, the example in the RFC simplifies to one line: fn clear_bytes(slice: &mut [u8]) {
unsafe { slice.as_mut_ptr().write_bytes(0, slice.len()) }
} |
Team member @SimonSapin has proposed to close this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Personally, I want this. I found myself causing a stack overflow with *ptr = mem::zeroed::<VeryLargeT>(); Naturally, I next looked for |
@Restioson with ptr.write_bytes(0u8, 1); |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@dtolnay I did settle for that in the end, but it feels like something that "you shouldn't have to define yourself" although you can. |
The final comment period, with a disposition to close, as per the review above, is now complete. By the power vested in me by Rust, I hereby close this RFC. |
Rendered
This is a functionality that's already possible in stable Rust, but I think it's well worth adding to libcore and transitively to libstd.
I would also like to be the one to implement this feature.