Closed
Description
When working with a &mut T
sometimes you need to turn it into T
. This can be achieved using mem::replace()
:
fn myfunc (v: &mut Vec<i32>) {
let taken_v = std::mem::replace(&mut v, mem::uninitialized());
let new_v = do_stuff(taken_v);
let uninit = std::mem::replace(&mut v, new_v);
std::mem::forget(uninit);
}
People generally assume that this is safe because the uninitialized memory is never observed. However, this code will drop uninitialized memory if do_stuff()
panics, because mem::forget will never be reached. This is undefined behavior and potentially a security vulnerability. Example of real-world code with this issue: sile/libflate#35
This can be fixed by using the take_mut
crate as described here. AFAIK there is currently no stdlib solution.
Using mem::zeroed()
instead of mem::uninitialized()
is also not valid if the target type is not valid for zeroed bit pattern or in case the type is generic.
cc @RalfJung