A MIR transform that checks pointers are aligned

This commit is contained in:
Ben Kimock 2022-11-10 11:37:28 -05:00
parent e216300876
commit 8ccf53332e
34 changed files with 360 additions and 20 deletions

View file

@ -169,7 +169,7 @@ fn check_rvalue<'tcx>(
Err((span, "unsizing casts are not allowed in const fn".into()))
}
},
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
Rvalue::Cast(CastKind::PointerExposeAddress | CastKind::PointerAddress, _, _) => {
Err((span, "casting pointers to ints is unstable in const fn".into()))
},
Rvalue::Cast(CastKind::DynStar, _, _) => {

View file

@ -220,6 +220,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
},
)?;
}
MisalignedPointerDereference { required, found } => {
// Forward to `panic_misaligned_pointer_dereference` lang item.
// First arg: required.
let required = this.read_scalar(&this.eval_operand(required, None)?)?;
// Second arg: found.
let found = this.read_scalar(&this.eval_operand(found, None)?)?;
// Call the lang item.
let panic_misaligned_pointer_dereference =
this.tcx.lang_items().panic_misaligned_pointer_dereference_fn().unwrap();
let panic_misaligned_pointer_dereference =
ty::Instance::mono(this.tcx.tcx, panic_misaligned_pointer_dereference);
this.call_function(
panic_misaligned_pointer_dereference,
Abi::Rust,
&[required.into(), found.into()],
None,
StackPopCleanup::Goto {
ret: None,
unwind: match unwind {
Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
None => StackPopUnwind::Skip,
},
},
)?;
}
_ => {
// Forward everything else to `panic` lang item.
this.start_panic(

View file

@ -1,4 +1,5 @@
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@compile-flags: -Cdebug-assertions=no
fn main() {
// No retry needed, this fails reliably.

View file

@ -1,4 +1,4 @@
//@compile-flags: -Zmiri-symbolic-alignment-check
//@compile-flags: -Zmiri-symbolic-alignment-check -Cdebug-assertions=no
#![feature(core_intrinsics)]
fn main() {

View file

@ -1,3 +1,5 @@
//@compile-flags: -Cdebug-assertions=no
#[repr(transparent)]
struct HasDrop(u8);

View file

@ -1,5 +1,5 @@
// should find the bug even without validation and stacked borrows, but gets masked by optimizations
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
#[repr(align(256))]
#[derive(Debug)]

View file

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

View file

@ -1,5 +1,5 @@
// This should fail even without validation/SB
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
#![allow(dead_code, unused_variables)]

View file

@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
fn main() {
// Try many times as this might work by chance.

View file

@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
fn main() {
// No retry needed, this fails reliably.

View file

@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
fn main() {
// Try many times as this might work by chance.

View file

@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
fn main() {
// Make sure we notice when a u16 is loaded at offset 1 into a u8 allocation.

View file

@ -1,5 +1,5 @@
// This should fail even without validation or Stacked Borrows.
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
use std::ptr;
fn main() {

View file

@ -1,6 +1,6 @@
// This should fail even without validation
// Some optimizations remove ZST accesses, thus masking this UB.
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation -Cdebug-assertions=no
fn main() {
// Try many times as this might work by chance.

View file

@ -0,0 +1,9 @@
//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=yes
fn main() {
let mut x = [0u32; 2];
let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
unsafe {
*(ptr.add(1).cast::<u32>()) = 42;
}
}

View file

@ -0,0 +1,2 @@
thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x4 but is $HEX', $DIR/alignment-assertion.rs:LL:CC
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

View file

@ -1,6 +1,6 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
//@compile-flags: -Zmiri-disable-alignment-check
//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=no
fn main() {
let mut x = [0u8; 20];