Skip to content

Provenance GC causes dead_alloc_map ICE when a protector is the last mention of an AllocId #3228

@saethlin

Description

@saethlin

This program will crash Miri:

extern "Rust" {
    pub fn miri_run_provenance_gc();
}

fn oof(mut b: Box<u8>) {
    drop(b);
    b = Box::new(0u8);
    unsafe { miri_run_provenance_gc() };
}

fn main() {
    oof(Box::new(0u8));
}

We create a Box, and immediately pass it to a function which makes it weakly protected.
This function argument is the only memory with the relevant AllocId.
Then we deallocate the Box, and at the same time overwrite the function argument.
One GC run later

We return from the function and execute this code to check if the allocation is still alive and 💥

// Just because the tag is protected doesn't guarantee that
// the allocation still exists (weak protectors allow deallocations)
// so we must check that the allocation exists.
// If it does exist, then we have the guarantee that the
// pointer is readable, and the implicit read access inserted
// will never cause UB on the pointer itself.
let (_, _, kind) = this.get_alloc_info(*alloc_id);

I'm not entirely sure what the best way to fix this is. The obvious way would be to visit the AllocIds in borrow_tracker::FrameExtra in the GC. But the comments we left around there seemed pretty confident that wouldn't be required, so I'm not totally sure there isn't another sort of design flaw here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions