diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 296c2e2dd6b3d..c612d6ad1bb24 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -57,23 +57,14 @@ pub struct Allocation { impl<'tcx, Tag, Extra> Allocation { /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end /// of an allocation (i.e., at the first *inaccessible* location) *is* considered - /// in-bounds! This follows C's/LLVM's rules. `check` indicates whether we - /// additionally require the pointer to be pointing to a *live* (still allocated) - /// allocation. + /// in-bounds! This follows C's/LLVM's rules. /// If you want to check bounds before doing a memory access, better use `check_bounds`. pub fn check_bounds_ptr( &self, ptr: Pointer, ) -> EvalResult<'tcx> { let allocation_size = self.bytes.len() as u64; - if ptr.offset.bytes() > allocation_size { - return err!(PointerOutOfBounds { - ptr: ptr.erase_tag(), - check: InboundsCheck::Live, - allocation_size: Size::from_bytes(allocation_size), - }); - } - Ok(()) + ptr.check_in_alloc(Size::from_bytes(allocation_size), InboundsCheck::Live) } /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds". diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 969f2c0e8376a..a046825f088bb 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -2,7 +2,7 @@ use mir; use ty::layout::{self, HasDataLayout, Size}; use super::{ - AllocId, EvalResult, + AllocId, EvalResult, InboundsCheck, }; //////////////////////////////////////////////////////////////////////////////// @@ -148,4 +148,21 @@ impl<'tcx, Tag> Pointer { pub fn erase_tag(self) -> Pointer { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } + + #[inline(always)] + pub fn check_in_alloc( + self, + allocation_size: Size, + check: InboundsCheck, + ) -> EvalResult<'tcx, ()> { + if self.offset > allocation_size { + err!(PointerOutOfBounds { + ptr: self.erase_tag(), + check, + allocation_size, + }) + } else { + Ok(()) + } + } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 4250023764555..c673b57a66f5f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -28,9 +28,9 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use syntax::ast::Mutability; use super::{ - Pointer, AllocId, Allocation, GlobalId, AllocationExtra, InboundsCheck, + Pointer, AllocId, Allocation, GlobalId, AllocationExtra, EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, - Machine, AllocMap, MayLeak, ErrorHandled, AllocationExtra, + Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -251,9 +251,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead)?; - // data required for alignment check - let (_, align) = self.get_size_and_align(ptr.alloc_id); + let align = self.check_bounds_ptr_maybe_dead(ptr)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -284,6 +282,23 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { }) } } + + /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end + /// of an allocation (i.e., at the first *inaccessible* location) *is* considered + /// in-bounds! This follows C's/LLVM's rules. + /// This function also works for deallocated allocations. + /// Use `.get(ptr.alloc_id)?.check_bounds_ptr(ptr)` if you want to force the allocation + /// to still be live. + /// If you want to check bounds before doing a memory access, better first obtain + /// an `Allocation` and call `check_bounds`. + pub fn check_bounds_ptr_maybe_dead( + &self, + ptr: Pointer, + ) -> EvalResult<'tcx, Align> { + let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id); + ptr.check_in_alloc(allocation_size, InboundsCheck::MaybeDead)?; + Ok(align) + } } /// Allocation accessors diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 9588a931c4a35..539bc6d965fd6 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -19,7 +19,7 @@ use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerEx use rustc::mir::interpret::{ GlobalId, AllocId, ConstValue, Pointer, Scalar, - EvalResult, EvalErrorKind, InboundsCheck, + EvalResult, EvalErrorKind, }; use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind}; pub use rustc::mir::interpret::ScalarMaybeUndef; @@ -647,7 +647,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && - self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok(); + self.memory.check_bounds_ptr_maybe_dead(ptr).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 8ce5a0365cf65..ed4cb65ea74b1 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -17,7 +17,7 @@ use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ - Scalar, AllocType, EvalResult, EvalErrorKind, InboundsCheck, + Scalar, AllocType, EvalResult, EvalErrorKind, }; use super::{ diff --git a/src/tools/miri b/src/tools/miri index dd7f545a69e4b..32e93ed7762e5 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit dd7f545a69e4b720407e458bf4ade0b207bbf9ee +Subproject commit 32e93ed7762e5aa1a721636096848fc3c7bc7218