comprehensive-rust icon indicating copy to clipboard operation
comprehensive-rust copied to clipboard

Fix raw pointer example which has UB

Open mgeisler opened this issue 2 years ago • 6 comments

The raw pointer example looks safe, but Miri flags it as having undefined behavior. This is a followup to the discussion in #177.

mgeisler avatar Jan 31 '23 19:01 mgeisler

If triggers undefined behaviour then we shouldn't have it as an example, but I'm not clear on why it is UB.

qwandor avatar Feb 02 '23 11:02 qwandor

The two-phase borrows mechanic means that r1 is considered inactive until it's used to write through, and that write pops r2 off the borrow stack.

riking avatar Feb 23 '23 00:02 riking

The two-phase borrows mechanic means that r1 is considered inactive until it's used to write through, and that write pops r2 off the borrow stack.

Thanks @riking!

@qwandor, I would like to merge this so we can warn people against the example. The other examples in this section are similarly full of things not to do, so it fits into the theme.

mgeisler avatar Mar 01 '23 14:03 mgeisler

Hi @gendx, I think you've played a lot with unsafe... can you review this? Thanks :smile:

mgeisler avatar Mar 07 '23 14:03 mgeisler

We should write an example that is valid instead.

How about something like this:

fn main() {
    let mut array = [5, 6];
    let r1 = &mut array[0] as *mut i32;
    let r2 = &array[1] as *const i32;
    unsafe {
        println!("r1 is: {}", *r1);
        *r1 = 10;
        println!("r1 is: {}", *r1);
        println!("r2 is: {}", *r2);
    }
    println!("array is: {array:?}");
}

Miri looks happy about it.

gendx avatar Mar 07 '23 14:03 gendx

Bonus code to modify if you want to get to Miri:

fn main() {
    let mut array = [5, 6];
    let r1 = &mut array[0] as *mut i32;
    let r2 = &array[1] as *const i32;
    unsafe {
        println!("r1 is: {}", *r1);
        *r1 = 10;
        println!("r1 is: {}", *r1);
        // Undefined behavior because this breaks the aliasing rules, as
        // r1.offset(1) and r2 are aliasing the same memory.
        //*r1.offset(1) = 20;
        println!("r2 is: {}", *r2);
    }
    println!("array is: {array:?}");
}

gendx avatar Mar 07 '23 14:03 gendx

How about #486 instead?

qwandor avatar Mar 08 '23 17:03 qwandor