Skip to content

Commit 51488ae

Browse files
committed
Auto merge of #3001 - RalfJung:align, r=RalfJung
add some interesting tests for alignment corner cases `strange_enum_discriminant_offset` example found in rust-lang/rust#53998.
2 parents 273cdab + 2009c77 commit 51488ae

File tree

4 files changed

+67
-18
lines changed

4 files changed

+67
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// This tests that when a field sits at offset 0 in a 4-aligned struct, accessing the field
2+
/// requires alignment 4 even if the field type has lower alignment requirements.
3+
4+
#[repr(C)]
5+
pub struct S {
6+
x: u8,
7+
y: u32,
8+
}
9+
10+
unsafe fn foo(x: *const S) -> u8 {
11+
unsafe { (*x).x } //~ERROR: accessing memory with alignment 1, but alignment 4 is required
12+
}
13+
14+
fn main() {
15+
unsafe {
16+
let mem = [0u64; 16];
17+
let odd_ptr = std::ptr::addr_of!(mem).cast::<u8>().add(1);
18+
// `odd_ptr` is now not aligned enough for `S`.
19+
// If accessing field `x` can exploit that it is at offset 0
20+
// in a 4-aligned struct, that field access requires alignment 4,
21+
// thus making this UB.
22+
foo(odd_ptr.cast());
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
2+
--> $DIR/field_requires_parent_struct_alignment.rs:LL:CC
3+
|
4+
LL | unsafe { (*x).x }
5+
| ^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `foo` at $DIR/field_requires_parent_struct_alignment.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/field_requires_parent_struct_alignment.rs:LL:CC
13+
|
14+
LL | foo(odd_ptr.cast());
15+
| ^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to previous error
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![allow(unused)]
2+
3+
#[repr(u16)]
4+
enum DeviceKind {
5+
Nil = 0,
6+
}
7+
8+
#[repr(C, packed)]
9+
struct DeviceInfo {
10+
endianness: u8,
11+
device_kind: DeviceKind,
12+
}
13+
14+
fn main() {
15+
// The layout of `Option<(DeviceInfo, u64)>` is funny: it uses the
16+
// `DeviceKind` enum as niche, so that is offset 1, but the niche type is u16!
17+
// So despite the type having alignment 8 and the field type alignment 2,
18+
// the actual alignment is 1.
19+
let x = None::<(DeviceInfo, u8)>;
20+
let y = None::<(DeviceInfo, u16)>;
21+
let z = None::<(DeviceInfo, u64)>;
22+
format!("{} {} {}", x.is_some(), y.is_some(), y.is_some());
23+
}

tests/pass/issues/issue-53728.rs

-18
This file was deleted.

0 commit comments

Comments
 (0)