use super::{Pointer, EvalResult, PrimVal, EvalContext}; use rustc::ty::Ty; use rustc::ty::layout::LayoutOf; pub trait EvalContextExt<'tcx> { fn wrapping_pointer_offset( &self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64, ) -> EvalResult<'tcx, Pointer>; fn pointer_offset( &self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64, ) -> EvalResult<'tcx, Pointer>; } impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> { fn wrapping_pointer_offset( &self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64, ) -> EvalResult<'tcx, Pointer> { // FIXME: assuming here that type size is < i64::max_value() let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64; let offset = offset.overflowing_mul(pointee_size).0; ptr.wrapping_signed_offset(offset, self) } fn pointer_offset( &self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64, ) -> EvalResult<'tcx, Pointer> { // This function raises an error if the offset moves the pointer outside of its allocation. We consider // ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0). // We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own // allocation. if ptr.is_null()? { // NULL pointers must only be offset by 0 return if offset == 0 { Ok(ptr) } else { err!(InvalidNullPointerUsage) }; } // FIXME: assuming here that type size is < i64::max_value() let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64; return if let Some(offset) = offset.checked_mul(pointee_size) { let ptr = ptr.signed_offset(offset, self)?; // Do not do bounds-checking for integers; they can never alias a normal pointer anyway. if let PrimVal::Ptr(ptr) = ptr.into_inner_primval() { self.memory.check_bounds(ptr, false)?; } else if ptr.is_null()? { // We moved *to* a NULL pointer. That seems wrong, LLVM considers the NULL pointer its own small allocation. Reject this, for now. return err!(InvalidNullPointerUsage); } Ok(ptr) } else { err!(OverflowingMath) }; } }