repr(packed) allows invalid unaligned loads · Issue #27060 · rust-lang/rust (original) (raw)
This is now a tracking issue for RFC 1240, "Taking a reference into a struct marked repr(packed)
should become unsafe
", but originally it was a bug report that led to the development of that RFC. The original miscompilation did not involve references, but it has been fixed; the reference case is the one that remains open. A lot of the discussion is hence outdated; this is the current state.
Original Issue Description
(This code actually works fine on today's nightly.)
#![feature(simd, test)]
extern crate test;
// simd types require high alignment or the CPU faults #[simd] #[derive(Debug, Copy, Clone)] struct f32x4(f32, f32, f32, f32);
#[repr(packed)] #[derive(Copy, Clone)] struct Unalign(T);
struct Breakit { x: u8, y: Unalign }
fn main() { let val = Breakit { x: 0, y: Unalign(f32x4(0.0, 0.0, 0.0, 0.0)) };
test::black_box(&val);
println!("before");
let ok = val.y;
test::black_box(ok.0);
println!("middle");
let bad = val.y.0;
test::black_box(bad);
println!("after");
}
Will print, on playpen:
before
middle
playpen: application terminated abnormally with signal 4 (Illegal instruction)
The assembly for the ok
load is:
movups 49(%rsp), %xmm0
movaps %xmm0, (%rsp)
#APP
#NO_APP
But for the bad
one, it is
movaps 49(%rsp), %xmm0
movaps %xmm0, (%rsp)
#APP
#NO_APP
Specifically, the movups
(unaligned) became a movaps
(aligned), but the pointer isn't actually aligned, hence the CPU faults.