adjust for InboundsCheck parameter of memory bounds check

This commit is contained in:
Ralf Jung 2018-11-20 08:42:51 +01:00
parent b8486ce9d6
commit 6085865975
3 changed files with 14 additions and 11 deletions

View file

@ -142,8 +142,9 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
// allocations sit right next to each other. The C/C++ standards are
// somewhat fuzzy about this case, so I think for now this check is
// "good enough".
self.memory().check_bounds_ptr(left, false)?;
self.memory().check_bounds_ptr(right, false)?;
// We require liveness, as dead allocations can of course overlap.
self.memory().check_bounds_ptr(left, InboundsCheck::Live)?;
self.memory().check_bounds_ptr(right, InboundsCheck::Live)?;
// Two live in-bounds pointers, we can compare across allocations
left == right
}
@ -153,15 +154,17 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
(Scalar::Bits { bits, size }, Scalar::Ptr(ptr)) => {
assert_eq!(size as u64, self.pointer_size().bytes());
let bits = bits as u64;
let (alloc_size, alloc_align) = self.memory().get_size_and_align(ptr.alloc_id);
// Case I: Comparing with NULL
if bits == 0 {
// Test if the ptr is in-bounds. Then it cannot be NULL.
if ptr.offset <= alloc_size {
if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() {
return Ok(false);
}
}
let (alloc_size, alloc_align) = self.memory().get_size_and_align(ptr.alloc_id);
// Case II: Alignment gives it away
if ptr.offset.bytes() % alloc_align.abi() == 0 {
// The offset maintains the allocation alignment, so we know `base+offset`
@ -293,11 +296,11 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
let offset = offset.checked_mul(pointee_size).ok_or_else(|| EvalErrorKind::Overflow(mir::BinOp::Mul))?;
// Now let's see what kind of pointer this is
if let Scalar::Ptr(ptr) = ptr {
// Both old and new pointer must be in-bounds.
// Both old and new pointer must be in-bounds of a *live* allocation.
// (Of the same allocation, but that part is trivial with our representation.)
self.memory().check_bounds_ptr(ptr, false)?;
self.memory().check_bounds_ptr(ptr, InboundsCheck::Live)?;
let ptr = ptr.signed_offset(offset, self)?;
self.memory().check_bounds_ptr(ptr, false)?;
self.memory().check_bounds_ptr(ptr, InboundsCheck::Live)?;
Ok(Scalar::Ptr(ptr))
} else {
// An integer pointer. They can only be offset by 0, and we pretend there

View file

@ -5,7 +5,7 @@ use rustc::hir::{Mutability, MutMutable, MutImmutable};
use crate::{
EvalResult, EvalErrorKind, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
MemoryKind, MiriMemoryKind, RangeMap, AllocId, Allocation, AllocationExtra,
MemoryKind, MiriMemoryKind, RangeMap, AllocId, Allocation, AllocationExtra, InboundsCheck,
Pointer, MemPlace, Scalar, Immediate, ImmTy, PlaceTy, MPlaceTy,
};
@ -523,7 +523,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
}
// Get the allocation
self.memory().check_bounds(ptr, size, false)?;
self.memory().check_bounds(ptr, size, InboundsCheck::Live)?;
let alloc = self.memory().get(ptr.alloc_id).expect("We checked that the ptr is fine!");
// If we got here, we do some checking, *but* we leave the tag unchanged.
if let Borrow::Shr(Some(_)) = ptr.tag {
@ -566,7 +566,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
ptr, place.layout.ty, new_bor);
// Get the allocation. It might not be mutable, so we cannot use `get_mut`.
self.memory().check_bounds(ptr, size, false)?;
self.memory().check_bounds(ptr, size, InboundsCheck::Live)?;
let alloc = self.memory().get(ptr.alloc_id).expect("We checked that the ptr is fine!");
// Update the stacks.
if let Borrow::Shr(Some(_)) = new_bor {

View file

@ -1,4 +1,4 @@
// error-pattern: pointer computed at offset 5, outside bounds of allocation
// error-pattern: must be in-bounds and live at offset 5, but is outside bounds of allocation
fn main() {
let v = [0i8; 4];
let x = &v as *const i8;