Skip to content

Trivial undefined behavior with scratch_arena #426

@comex

Description

@comex

This code in scratch_arena causes undefined behavior if it's called while there's an existing ScratchArena object pointing to the same slot. That's because taking a new mutable borrow invalidates all existing borrows.

let arena = &mut S_SCRATCH[index];
ScratchArena::new(arena)

I'm not sure whether the application itself actually triggers the UB, but the documentation indicates that it's intended for "the same Arena to be borrowed multiple times at once".

This is trivial to fix, though, because ScratchArena::new doesn't need a mutable borrow. Just change &mut to & here.

For completeness, I verified the UB by adding the following test and running cargo miri test arena:

#[test]
fn test_arena() {
    fn recur(n: u32, other: Option<&Arena>) {
        let scratch = scratch_arena(other);
        if n != 0 {
            recur(n - 1, Some(&scratch));
        }

    }
    recur(5, None);
}
test arena::scratch::test_arena ... error: Undefined Behavior: trying to retag from <214510> for SharedReadOnly permission at alloc25[0x28], but that tag does not exist in the borrow stack for this location

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