Skip to content

Commit c87797e

Browse files
committed
place evaluation: require the original pointer to be aligned if an access happens
1 parent d4d85a8 commit c87797e

File tree

6 files changed

+55
-8
lines changed

6 files changed

+55
-8
lines changed

src/helpers.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
697697
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
698698
let this = self.eval_context_ref();
699699
let ptr = this.read_pointer(op)?;
700-
701-
let mplace = MPlaceTy::from_aligned_ptr(ptr, layout);
702-
703-
Ok(mplace)
700+
Ok(this.ptr_to_mplace(ptr, layout))
704701
}
705702

706703
/// Calculates the MPlaceTy given the offset and layout of an access on an operand

src/shims/unix/fs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
13701370
("d_reclen", size.into()),
13711371
("d_type", file_type.into()),
13721372
],
1373-
&MPlaceTy::from_aligned_ptr(entry, dirent64_layout),
1373+
&this.ptr_to_mplace(entry, dirent64_layout),
13741374
)?;
13751375

13761376
let name_ptr = entry.offset(Size::from_bytes(d_name_offset), this)?;

src/shims/unix/linux/sync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn futex<'tcx>(
3434

3535
let thread = this.get_active_thread();
3636
// This is a vararg function so we have to bring our own type for this pointer.
37-
let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32);
37+
let addr = this.ptr_to_mplace(addr, this.machine.layouts.i32);
3838
let addr_usize = addr.ptr().addr().bytes();
3939

4040
let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG");

src/shims/windows/sync.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
322322

323323
let layout = this.machine.layouts.uint(size).unwrap();
324324
let futex_val = this
325-
.read_scalar_atomic(&MPlaceTy::from_aligned_ptr(ptr, layout), AtomicReadOrd::Relaxed)?;
326-
let compare_val = this.read_scalar(&MPlaceTy::from_aligned_ptr(compare, layout))?;
325+
.read_scalar_atomic(&this.ptr_to_mplace(ptr, layout), AtomicReadOrd::Relaxed)?;
326+
let compare_val = this.read_scalar(&this.ptr_to_mplace(compare, layout))?;
327327

328328
if futex_val == compare_val {
329329
// If the values are the same, we have to block.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// This tests that when a field sits at a well-aligned offset, accessing the field
2+
/// requires high alignment even if the field type has lower alignment requirements.
3+
4+
#[repr(C, align(16))]
5+
#[derive(Default, Copy, Clone)]
6+
pub struct Aligned {
7+
_pad: [u8; 11],
8+
packed: Packed,
9+
}
10+
#[repr(packed)]
11+
#[derive(Default, Copy, Clone)]
12+
pub struct Packed {
13+
_pad: [u8; 5],
14+
x: u8,
15+
}
16+
17+
unsafe fn foo(x: *const Aligned) -> u8 {
18+
unsafe { (*x).packed.x } //~ERROR: accessing memory with alignment 1, but alignment 16 is required
19+
}
20+
21+
fn main() {
22+
unsafe {
23+
let mem = [Aligned::default(); 16];
24+
let odd_ptr = std::ptr::addr_of!(mem).cast::<u8>().add(1);
25+
// `odd_ptr` is now not aligned enough for `Aligned`.
26+
// If accessing the nested field `packed.x` can exploit that it is at offset 16
27+
// in a 16-aligned struct, this has to be UB.
28+
foo(odd_ptr.cast());
29+
}
30+
}
Lines changed: 20 additions & 0 deletions
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_alignment2.rs:LL:CC
3+
|
4+
LL | unsafe { (*x).packed.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_alignment2.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/field_requires_parent_struct_alignment2.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+

0 commit comments

Comments
 (0)