1 use rustc::mir::interpret::{Pointer, EvalResult, PrimVal, EvalContext};
5 pub trait EvalContextExt<'tcx> {
6 fn wrapping_pointer_offset(
11 ) -> EvalResult<'tcx, Pointer>;
18 ) -> EvalResult<'tcx, Pointer>;
21 impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> {
22 fn wrapping_pointer_offset(
27 ) -> EvalResult<'tcx, Pointer> {
28 // FIXME: assuming here that type size is < i64::max_value()
29 let pointee_size = self.type_size(pointee_ty)?.expect(
30 "cannot offset a pointer to an unsized type",
32 let offset = offset.overflowing_mul(pointee_size).0;
33 ptr.wrapping_signed_offset(offset, self)
41 ) -> EvalResult<'tcx, Pointer> {
42 // This function raises an error if the offset moves the pointer outside of its allocation. We consider
43 // ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0).
44 // We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own
48 // NULL pointers must only be offset by 0
49 return if offset == 0 {
52 err!(InvalidNullPointerUsage)
55 // FIXME: assuming here that type size is < i64::max_value()
56 let pointee_size = self.type_size(pointee_ty)?.expect(
57 "cannot offset a pointer to an unsized type",
59 return if let Some(offset) = offset.checked_mul(pointee_size) {
60 let ptr = ptr.signed_offset(offset, self)?;
61 // Do not do bounds-checking for integers; they can never alias a normal pointer anyway.
62 if let PrimVal::Ptr(ptr) = ptr.into_inner_primval() {
63 self.memory.check_bounds(ptr, false)?;
64 } else if ptr.is_null()? {
65 // We moved *to* a NULL pointer. That seems wrong, LLVM considers the NULL pointer its own small allocation. Reject this, for now.
66 return err!(InvalidNullPointerUsage);