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.