Skip to content

miri accepts when embedded UnsafeCell in mutable Pin reference is changed #1860

@godmar

Description

@godmar

It's my understanding that changing a memory location through a pointer that is an alias of a mutable reference is disallowed in Rust, and that miri could/should help detecting such scenarios.

Consider this playground reproduced here:

use std::ptr;
use std::pin::Pin;
use std::cell::UnsafeCell;

struct A {
    x:  UnsafeCell<isize>,
    ptr_x: *mut isize,
}

impl A {
    fn new(x: isize) -> Pin<Box<A>> {
        let mut a = Box::pin(A { x: UnsafeCell::new(x), 
                             ptr_x: ptr::null_mut() 
        });
        a.ptr_x = a.x.get_mut();
        a
    }

    fn change_x(self: &mut Pin<Box<A>>) {
        unsafe {
            self.ptr_x.write(0);
        }
    }

    #[inline(never)]
    fn wait_for_x(self: &mut Pin<Box<A>>) {
        while unsafe { *self.x.get() == 42 } {
            self.change_x();
        }
    }
}

fn main()
{
    let mut a = Box::new(A::new(42));
    println!("waiting for Godot");
    a.wait_for_x(); 
    println!("done");
}

Should miri flag UB in this code?

ps: compare to this similar playground that does not use Pin. Here, miri flags UB and the release/nightly compiler correctly exploits the UB by emitting an infinite loop.

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