about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-17 12:11:41 +0000
committerbors <bors@rust-lang.org>2020-08-17 12:11:41 +0000
commit8cdc94e84040ce797fd33d0a7cfda4ec4f2f2421 (patch)
tree613072e59d3b4b3c447a7ad960c5af2bc3ffd988 /src
parent67e7b9b8cf776222825dbbd4cb1e39b7765ef27c (diff)
parent6da8503dff7b8792916bf6cd489e92c49ea7e868 (diff)
downloadrust-8cdc94e84040ce797fd33d0a7cfda4ec4f2f2421.tar.gz
rust-8cdc94e84040ce797fd33d0a7cfda4ec4f2f2421.zip
Auto merge of #75592 - RalfJung:miri-int-align, r=oli-obk
miri engine: add option to use force_int for alignment check

This is needed for https://github.com/rust-lang/miri/issues/1074. The Miri-side patch is at https://github.com/rust-lang/miri/pull/1513.

r? @oli-obk
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/interpret/machine.rs10
-rw-r--r--src/librustc_mir/interpret/memory.rs23
2 files changed, 23 insertions, 10 deletions
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 5cab4ba37e3..3718da1723b 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 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;
+
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
@@ -376,6 +380,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     }
 
     #[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 49d97ff7cec..8d80fa82185 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