Skip to content

New lint: mem::replace(mem::uninitialized) is dangerous #4485

Closed
@Shnatsel

Description

@Shnatsel

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lintsL-correctnessLint: Belongs in the correctness lint group

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions