From 20aea2059264109e615478d05988e1b200b1adec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Aug 2020 17:36:46 +0200 Subject: [PATCH 1/2] miri engine: add option to use force_int for alignment check --- src/librustc_mir/interpret/machine.rs | 10 ++++++++++ src/librustc_mir/interpret/memory.rs | 23 +++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 5cab4ba37e3a5..edd9b7a9e626e 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -122,6 +122,10 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether memory accesses should be alignment-checked. fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool; + /// Whether, when cehcking alignment, we should `force_int` and thus support + /// custom alignment logic based on whatever the integer address happens to be. + fn force_int_for_alignment_check(memory_extra: &Self::MemoryExtra) -> bool; + /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; @@ -375,6 +379,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { false } + #[inline(always)] + fn force_int_for_alignment_check(_memory_extra: &Self::MemoryExtra) -> bool { + // We do not support `force_int`. + false + } + #[inline(always)] fn enforce_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { false // for now, we don't enforce validity diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 49d97ff7ceccc..8d80fa82185ed 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -8,7 +8,7 @@ use std::borrow::Cow; use std::collections::VecDeque; -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use std::fmt; use std::ptr; @@ -380,7 +380,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // if this is already a `Pointer` we want to do the bounds checks! sptr } else { - // A "real" access, we must get a pointer. + // A "real" access, we must get a pointer to be able to check the bounds. Scalar::from(self.force_ptr(sptr)?) }; Ok(match normalized.to_bits_or_ptr(self.pointer_size(), self) { @@ -411,15 +411,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { - if alloc_align.bytes() < align.bytes() { - // The allocation itself is not aligned enough. - // FIXME: Alignment check is too strict, depending on the base address that - // got picked we might be aligned even if this check fails. - // We instead have to fall back to converting to an integer and checking - // the "real" alignment. - throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align }); + if M::force_int_for_alignment_check(&self.extra) { + let bits = self + .force_bits(ptr.into(), self.pointer_size()) + .expect("ptr-to-int cast for align check should never fail"); + check_offset_align(bits.try_into().unwrap(), align)?; + } else { + // Check allocation alignment and offset alignment. + if alloc_align.bytes() < align.bytes() { + throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align }); + } + check_offset_align(ptr.offset.bytes(), align)?; } - check_offset_align(ptr.offset.bytes(), align)?; } // We can still be zero-sized in this branch, in which case we have to From 6da8503dff7b8792916bf6cd489e92c49ea7e868 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Aug 2020 14:11:03 +0200 Subject: [PATCH 2/2] fix typo Co-authored-by: Oliver Scherer --- src/librustc_mir/interpret/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index edd9b7a9e626e..3718da1723b16 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -122,7 +122,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether memory accesses should be alignment-checked. fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool; - /// Whether, when cehcking alignment, we should `force_int` and thus support + /// Whether, when checking alignment, we should `force_int` and thus support /// custom alignment logic based on whatever the integer address happens to be. fn force_int_for_alignment_check(memory_extra: &Self::MemoryExtra) -> bool;