Skip to content

False positive when int-to-ptr "confuses" which allocation (provenance) to use for new ptr #1866

@niluxv

Description

@niluxv

Miri accepts dereferencing a (fat) pointer to a slice of ZSTs, except when the pointer to the slice lies in a previously freed allocation.

Example 1 (fresh dangling pointer, succeeds):

fn main() {
    // create fresh dangling ptr `ptr`
    let ptr: *const () = std::ptr::NonNull::<()>::dangling().as_ptr();
    let slice_ptr: *const [()] = std::ptr::slice_from_raw_parts(ptr, 1);
    let slice_ref: &[()] = unsafe { &*slice_ptr } ;
}

playground

Example 2 (pointer to freed allocation, errors):

fn main() {
    let vec: Vec<u8> = vec![1, 2, 3];
    let vec_ptr: *const u8 = vec.as_ptr();
    drop(vec);
    // now `vec_ptr` is dangling, and we create a dangling `ptr` from it
    let ptr: *const () = vec_ptr as *const ();
    let slice_ptr: *const [()] = std::ptr::slice_from_raw_parts(ptr, 1);
    let slice_ref: &[()] = unsafe { &*slice_ptr } ; // ERROR
    // error: Undefined Behavior: pointer to alloc1414 was dereferenced after this allocation got freed
}

playground

But soundness of code does not depend on previous allocations (I hope); in both cases ptr is 'just' a *const () dangling non-null pointer. Therefore either both examples are unsound/UB, or both are sound.

(I think both examples are sound, so that this is a false positive. At least the entire bitvec crate seems to be build around the idea that this is sound. Issue #135 in bitvec an example of this issue in the wild.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-intptrcastArea: affects int2ptr and ptr2int castsC-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions