about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-07-31 16:00:48 +0200
committerRalf Jung <post@ralfj.de>2023-07-31 16:07:15 +0200
commita63db6de5ae034bd006be663e760b9f81226b44c (patch)
tree8d95cb7f44754c78e5534531422c8e3d75565359
parente1071af908f70aaa32903a92a167cfb0cf1e9d84 (diff)
downloadrust-a63db6de5ae034bd006be663e760b9f81226b44c.tar.gz
rust-a63db6de5ae034bd006be663e760b9f81226b44c.zip
add some interesting tests for alignment corner cases
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.rs24
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr20
-rw-r--r--src/tools/miri/tests/pass/align_strange_enum_discriminant_offset.rs23
-rw-r--r--src/tools/miri/tests/pass/issues/issue-53728.rs18
4 files changed, 67 insertions, 18 deletions
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 00000000000..fa1812adc29
--- /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::<u8>().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 00000000000..0f030a6e27c
--- /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 00000000000..e0d05e0b65a
--- /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 0c858d3444f..00000000000
--- 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)>;
-}