From ef15a8182ba0b6b7b5d6abb9d00eeb93f7cf0247 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 2 Dec 2023 14:24:17 +0100 Subject: codegen, miri: fix computing the offset of an unsized field in a packed struct --- .../pass/issues/issue-3200-packed-field-offset.rs | 35 ++++++++++++++++++++ .../pass/issues/issue-3200-packed2-field-offset.rs | 38 ++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs create mode 100644 src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs (limited to 'src') diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs new file mode 100644 index 00000000000..e58fe60b5f6 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs @@ -0,0 +1,35 @@ +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed, C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed, C)] +struct PackedUnsized { + f: u8, + d: [u32], +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation does *not* think there is + // any padding in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs new file mode 100644 index 00000000000..910b5d94320 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs @@ -0,0 +1,38 @@ +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed(4))] +struct Slice([u32]); + +#[repr(packed(2), C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed(2), C)] +struct PackedUnsized { + f: u8, + d: Slice, +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation correctly adds exact 1 byte of padding + // in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } -- cgit 1.4.1-3-g733a5