Skip to content

Commit c221618

Browse files
committed
Auto merge of #98112 - saethlin:mir-alignment-checks, r=oli-obk
Insert alignment checks for pointer dereferences when debug assertions are enabled Closes rust-lang/rust#54915 - [x] Jake tells me this sounds like a place to use `MirPatch`, but I can't figure out how to insert a new basic block with a new terminator in the middle of an existing basic block, using `MirPatch`. (if nobody else backs up this point I'm checking this as "not actually a good idea" because the code looks pretty clean to me after rearranging it a bit) - [x] Using `CastKind::PointerExposeAddress` is definitely wrong, we don't want to expose. Calling a function to get the pointer address seems quite excessive. ~I'll see if I can add a new `CastKind`.~ `CastKind::Transmute` to the rescue! - [x] Implement a more helpful panic message like slice bounds checking. r? `@oli-obk`
2 parents d061a3b + 1115f04 commit c221618

16 files changed

+53
-11
lines changed

src/shims/panic.rs

+28
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
220220
},
221221
)?;
222222
}
223+
MisalignedPointerDereference { required, found } => {
224+
// Forward to `panic_misaligned_pointer_dereference` lang item.
225+
226+
// First arg: required.
227+
let required = this.read_scalar(&this.eval_operand(required, None)?)?;
228+
// Second arg: found.
229+
let found = this.read_scalar(&this.eval_operand(found, None)?)?;
230+
231+
// Call the lang item.
232+
let panic_misaligned_pointer_dereference =
233+
this.tcx.lang_items().panic_misaligned_pointer_dereference_fn().unwrap();
234+
let panic_misaligned_pointer_dereference =
235+
ty::Instance::mono(this.tcx.tcx, panic_misaligned_pointer_dereference);
236+
this.call_function(
237+
panic_misaligned_pointer_dereference,
238+
Abi::Rust,
239+
&[required.into(), found.into()],
240+
None,
241+
StackPopCleanup::Goto {
242+
ret: None,
243+
unwind: match unwind {
244+
Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
245+
None => StackPopUnwind::Skip,
246+
},
247+
},
248+
)?;
249+
}
250+
223251
_ => {
224252
// Forward everything else to `panic` lang item.
225253
this.start_panic(

tests/fail/unaligned_pointers/alignment.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@normalize-stderr-test: "\| +\^+" -> "| ^"
2+
//@compile-flags: -Cdebug-assertions=no
23

34
fn main() {
45
// No retry needed, this fails reliably.

tests/fail/unaligned_pointers/atomic_unaligned.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@compile-flags: -Zmiri-symbolic-alignment-check
1+
//@compile-flags: -Zmiri-symbolic-alignment-check -Cdebug-assertions=no
22
#![feature(core_intrinsics)]
33

44
fn main() {

tests/fail/unaligned_pointers/drop_in_place.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//@compile-flags: -Cdebug-assertions=no
2+
13
#[repr(transparent)]
24
struct HasDrop(u8);
35

tests/fail/unaligned_pointers/dyn_alignment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// should find the bug even without validation and stacked borrows, but gets masked by optimizations
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
33

44
#[repr(align(256))]
55
#[derive(Debug)]

tests/fail/unaligned_pointers/intptrcast_alignment_check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance
1+
//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance -Cdebug-assertions=no
22
// With the symbolic alignment check, even with intptrcast and without
33
// validation, we want to be *sure* to catch bugs that arise from pointers being
44
// insufficiently aligned. The only way to achieve that is not not let programs

tests/fail/unaligned_pointers/reference_to_packed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This should fail even without validation/SB
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
33

44
#![allow(dead_code, unused_variables)]
55

tests/fail/unaligned_pointers/unaligned_ptr1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This should fail even without validation or Stacked Borrows.
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
33

44
fn main() {
55
// Try many times as this might work by chance.

tests/fail/unaligned_pointers/unaligned_ptr2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This should fail even without validation or Stacked Borrows.
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
33

44
fn main() {
55
// No retry needed, this fails reliably.

tests/fail/unaligned_pointers/unaligned_ptr3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This should fail even without validation or Stacked Borrows.
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
33

44
fn main() {
55
// Try many times as this might work by chance.

tests/fail/unaligned_pointers/unaligned_ptr4.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This should fail even without validation or Stacked Borrows.
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
33

44
fn main() {
55
// Make sure we notice when a u16 is loaded at offset 1 into a u8 allocation.

tests/fail/unaligned_pointers/unaligned_ptr_addr_of.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This should fail even without validation or Stacked Borrows.
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
2+
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
33
use std::ptr;
44

55
fn main() {

tests/fail/unaligned_pointers/unaligned_ptr_zst.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This should fail even without validation
22
// Some optimizations remove ZST accesses, thus masking this UB.
3-
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation
3+
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation -Cdebug-assertions=no
44

55
fn main() {
66
// Try many times as this might work by chance.

tests/panic/alignment-assertion.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=yes
2+
3+
fn main() {
4+
let mut x = [0u32; 2];
5+
let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
6+
unsafe {
7+
*(ptr.add(1).cast::<u32>()) = 42;
8+
}
9+
}
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x4 but is $HEX', $DIR/alignment-assertion.rs:LL:CC
2+
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

tests/pass/disable-alignment-check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@revisions: stack tree
22
//@[tree]compile-flags: -Zmiri-tree-borrows
3-
//@compile-flags: -Zmiri-disable-alignment-check
3+
//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=no
44

55
fn main() {
66
let mut x = [0u8; 20];

0 commit comments

Comments
 (0)