- 
                Notifications
    
You must be signed in to change notification settings  - Fork 13.9k
 
Labels
A-codegenArea: Code generationArea: Code generationA-mir-optArea: MIR optimizationsArea: MIR optimizationsA-mir-opt-GVNArea: MIR opt Global Value Numbering (GVN)Area: MIR opt Global Value Numbering (GVN)I-miscompileIssue: Correct Rust code lowers to incorrect machine codeIssue: Correct Rust code lowers to incorrect machine codeI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.WG-mir-optWorking group: MIR optimizationsWorking group: MIR optimizations
Description
I tried this code:
unsafe fn src(x: &&u8) -> bool {
    let y = **x;
    unknown();
    **x == y
}
static mut SUSSY: *mut u8 = core::ptr::null_mut();
#[inline(never)]
unsafe fn unknown() {
    *SUSSY = 1;
}
fn main() {
    let mut s = 0;
    unsafe {
        SUSSY = core::ptr::addr_of_mut!(s);
        println!("{}", src(&*core::ptr::addr_of!(SUSSY).cast::<&u8>()));
    }
}I expected to see this happen:
This should print false, as I believe this is DB under both Stacked and Tree borrows(according to MIRI).
Instead, this happened:
It returns false in Debug mode, and the GVN MIR pass makes src() unconditionally return true in Release mode.
$ cargo miri run
Compiling sus v0.1.0 (/Users/jwong3/test/sus)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
     Running `/Users/jwong3/.rustup/toolchains/nightly-aarch64-apple-darwin/bin/cargo-miri runner target/miri/aarch64-apple-darwin/debug/sus`
false$ cargo run -r
   Compiling sus v0.1.0 (/Users/jwong3/test/sus)
    Finished `release` profile [optimized] target(s) in 0.31s
     Running `target/release/sus`
trueMeta
Here's the MIR before the GVN pass:
// MIR for `src` before GVN
fn src(_1: &&u8) -> bool {
    debug x => _1;
    let mut _0: bool;
    let _2: u8;
    let _3: ();
    let mut _4: u8;
    let mut _5: u8;
    let mut _6: &u8;
    let mut _7: &u8;
    scope 1 {
        debug y => _2;
    }
    bb0: {
        StorageLive(_2);
        _6 = deref_copy (*_1);
        _2 = copy (*_6);
        _3 = unknown() -> [return: bb1, unwind continue];
    }
    bb1: {
        StorageLive(_4);
        _7 = deref_copy (*_1);
        _4 = copy (*_7);
        StorageLive(_5);
        _5 = copy _2;
        _0 = Eq(move _4, move _5);
        StorageDead(_5);
        StorageDead(_4);
        StorageDead(_2);
        return;
    }
}After
// MIR for `src` after GVN
fn src(_1: &&u8) -> bool {
    debug x => _1;
    let mut _0: bool;
    let _2: u8;
    let _3: ();
    let mut _4: u8;
    let mut _5: u8;
    let mut _6: &u8;
    let mut _7: &u8;
    scope 1 {
        debug y => _2;
    }
    bb0: {
        nop;
        _6 = copy (*_1);
        _2 = copy (*_6);
        _3 = unknown() -> [return: bb1, unwind continue];
    }
    bb1: {
        StorageLive(_4);
        _7 = copy _6;
        _4 = copy _2;
        StorageLive(_5);
        _5 = copy _2;
        _0 = const true;
        StorageDead(_5);
        StorageDead(_4);
        nop;
        return;
    }
}It would be justified to make src() return true if _6 was dereferenced again in bb1, however, the write in unknown() shouldn't invalidate the actual pointer stored in _1 if my understanding of Stacked Borrows is correct.
This is present in both Stable and Nightly.
Metadata
Metadata
Assignees
Labels
A-codegenArea: Code generationArea: Code generationA-mir-optArea: MIR optimizationsArea: MIR optimizationsA-mir-opt-GVNArea: MIR opt Global Value Numbering (GVN)Area: MIR opt Global Value Numbering (GVN)I-miscompileIssue: Correct Rust code lowers to incorrect machine codeIssue: Correct Rust code lowers to incorrect machine codeI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.WG-mir-optWorking group: MIR optimizationsWorking group: MIR optimizations