Move alignment and bounds check from Memory to Allocation

This commit is contained in:
Oliver Scherer 2018-11-12 08:37:54 +01:00
parent d98c46ce57
commit 7c9d786e50
2 changed files with 45 additions and 42 deletions

View file

@ -49,6 +49,51 @@ pub struct Allocation<Tag=(),Extra=()> {
pub extra: Extra, pub extra: Extra,
} }
/// Alignment and bounds checks
impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
/// 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.
/// If you want to check bounds before doing a memory access, better use `check_bounds`.
pub fn check_bounds_ptr(
&self,
ptr: Pointer<M::PointerTag>,
check: InboundsCheck,
) -> EvalResult<'tcx> {
let allocation_size = match check {
InboundsCheck::Live => {
let alloc = self.get(ptr.alloc_id)?;
alloc.bytes.len() as u64
}
InboundsCheck::MaybeDead => {
self.get_size_and_align(ptr.alloc_id).0.bytes()
}
};
if ptr.offset.bytes() > allocation_size {
return err!(PointerOutOfBounds {
ptr: ptr.erase_tag(),
check,
allocation_size: Size::from_bytes(allocation_size),
});
}
Ok(())
}
/// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
#[inline(always)]
pub fn check_bounds(
&self,
ptr: Pointer<M::PointerTag>,
size: Size,
check: InboundsCheck,
) -> EvalResult<'tcx> {
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
self.check_bounds_ptr(ptr.offset(size, &*self)?, check)
}
}
/// Byte accessors /// Byte accessors
impl<'tcx, Tag, Extra> Allocation<Tag, Extra> { impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
/// The last argument controls whether we error out when there are undefined /// The last argument controls whether we error out when there are undefined

View file

@ -284,48 +284,6 @@ 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. `check` indicates whether we
/// additionally require the pointer to be pointing to a *live* (still allocated)
/// allocation.
/// If you want to check bounds before doing a memory access, better use `check_bounds`.
pub fn check_bounds_ptr(
&self,
ptr: Pointer<M::PointerTag>,
check: InboundsCheck,
) -> EvalResult<'tcx> {
let allocation_size = match check {
InboundsCheck::Live => {
let alloc = self.get(ptr.alloc_id)?;
alloc.bytes.len() as u64
}
InboundsCheck::MaybeDead => {
self.get_size_and_align(ptr.alloc_id).0.bytes()
}
};
if ptr.offset.bytes() > allocation_size {
return err!(PointerOutOfBounds {
ptr: ptr.erase_tag(),
check,
allocation_size: Size::from_bytes(allocation_size),
});
}
Ok(())
}
/// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
#[inline(always)]
pub fn check_bounds(
&self,
ptr: Pointer<M::PointerTag>,
size: Size,
check: InboundsCheck,
) -> EvalResult<'tcx> {
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
self.check_bounds_ptr(ptr.offset(size, &*self)?, check)
}
} }
/// Allocation accessors /// Allocation accessors