-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
fn main() {
let mut buf = magic_buffer::MagicBuffer::new(4096).unwrap();
let a = buf[0..4096][0];
buf[1..4097][4095] = 1;
let b = buf[0..4096][0];
println!("a = {a}");
println!("b = {b}");
let c = buf[0..4096][0];
println!("c = {c}");
}Output in debug mode:
a = 0
b = 1
c = 1
Output in release mode:
a = 0
b = 0
c = 1
The key here is that we're violating LLVM's memory model (and from what I understand from @RalfJung, probably gcc's memory model as well) by aliasing the physical memory in virtual memory. Seen post-optimisation, we're basically doing this:
let a = *buf.ptr;
*buf.ptr.add(4096) = 1;
let b = *buf.ptr;As far as LLVM is concerned, *buf.ptr and *buf.ptr.add(4096) don't alias, so this code is equivalent:
let a = *buf.ptr;
*buf.ptr.add(4096) = 1;
let b = a;(and as for why c shows up correctly: print is heavy enough to clobber all the registers, so LLVM chooses to reload)
Metadata
Metadata
Assignees
Labels
No labels