From a63db6de5ae034bd006be663e760b9f81226b44c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Jul 2023 16:00:48 +0200 Subject: [PATCH] add some interesting tests for alignment corner cases --- .../field_requires_parent_struct_alignment.rs | 24 +++++++++++++++++++ ...ld_requires_parent_struct_alignment.stderr | 20 ++++++++++++++++ .../align_strange_enum_discriminant_offset.rs | 23 ++++++++++++++++++ .../miri/tests/pass/issues/issue-53728.rs | 18 -------------- 4 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.rs create mode 100644 src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr create mode 100644 src/tools/miri/tests/pass/align_strange_enum_discriminant_offset.rs delete mode 100644 src/tools/miri/tests/pass/issues/issue-53728.rs diff --git a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.rs new file mode 100644 index 0000000000000..fa1812adc2961 --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.rs @@ -0,0 +1,24 @@ +/// This tests that when a field sits at offset 0 in a 4-aligned struct, accessing the field +/// requires alignment 4 even if the field type has lower alignment requirements. + +#[repr(C)] +pub struct S { + x: u8, + y: u32, +} + +unsafe fn foo(x: *const S) -> u8 { + unsafe { (*x).x } //~ERROR: accessing memory with alignment 1, but alignment 4 is required +} + +fn main() { + unsafe { + let mem = [0u64; 16]; + let odd_ptr = std::ptr::addr_of!(mem).cast::().add(1); + // `odd_ptr` is now not aligned enough for `S`. + // If accessing field `x` can exploit that it is at offset 0 + // in a 4-aligned struct, that field access requires alignment 4, + // thus making this UB. + foo(odd_ptr.cast()); + } +} diff --git a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr new file mode 100644 index 0000000000000..0f030a6e27ce0 --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required + --> $DIR/field_requires_parent_struct_alignment.rs:LL:CC + | +LL | unsafe { (*x).x } + | ^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `foo` at $DIR/field_requires_parent_struct_alignment.rs:LL:CC +note: inside `main` + --> $DIR/field_requires_parent_struct_alignment.rs:LL:CC + | +LL | foo(odd_ptr.cast()); + | ^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/pass/align_strange_enum_discriminant_offset.rs b/src/tools/miri/tests/pass/align_strange_enum_discriminant_offset.rs new file mode 100644 index 0000000000000..e0d05e0b65abf --- /dev/null +++ b/src/tools/miri/tests/pass/align_strange_enum_discriminant_offset.rs @@ -0,0 +1,23 @@ +#![allow(unused)] + +#[repr(u16)] +enum DeviceKind { + Nil = 0, +} + +#[repr(C, packed)] +struct DeviceInfo { + endianness: u8, + device_kind: DeviceKind, +} + +fn main() { + // The layout of `Option<(DeviceInfo, u64)>` is funny: it uses the + // `DeviceKind` enum as niche, so that is offset 1, but the niche type is u16! + // So despite the type having alignment 8 and the field type alignment 2, + // the actual alignment is 1. + let x = None::<(DeviceInfo, u8)>; + let y = None::<(DeviceInfo, u16)>; + let z = None::<(DeviceInfo, u64)>; + format!("{} {} {}", x.is_some(), y.is_some(), y.is_some()); +} diff --git a/src/tools/miri/tests/pass/issues/issue-53728.rs b/src/tools/miri/tests/pass/issues/issue-53728.rs deleted file mode 100644 index 0c858d3444fb3..0000000000000 --- a/src/tools/miri/tests/pass/issues/issue-53728.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[repr(u16)] -#[allow(dead_code)] -enum DeviceKind { - Nil = 0, -} - -#[repr(packed)] -#[allow(dead_code)] -struct DeviceInfo { - endianness: u8, - device_kind: DeviceKind, -} - -fn main() { - let _x = None::<(DeviceInfo, u8)>; - let _y = None::<(DeviceInfo, u16)>; - let _z = None::<(DeviceInfo, u64)>; -}