diff --git a/src/error.rs b/src/error.rs index 82b4eff6e926..fde3db15968c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,7 +10,7 @@ use syntax::codemap::Span; pub enum EvalError<'tcx> { FunctionPointerTyMismatch(&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>), DanglingPointerDeref, - ZstAllocAccess, + InvalidMemoryAccess, InvalidFunctionPointer, InvalidBool, InvalidDiscriminant, @@ -20,7 +20,6 @@ pub enum EvalError<'tcx> { allocation_size: usize, }, ReadPointerAsBytes, - ReadBytesAsPointer, InvalidPointerMath, ReadUndefBytes, InvalidBoolOp(mir::BinOp), @@ -54,8 +53,8 @@ impl<'tcx> Error for EvalError<'tcx> { match *self { EvalError::FunctionPointerTyMismatch(..) => "tried to call a function through a function pointer of a different type", - EvalError::ZstAllocAccess => - "tried to access the ZST allocation", + EvalError::InvalidMemoryAccess => + "tried to access memory through an invalid pointer", EvalError::DanglingPointerDeref => "dangling pointer was dereferenced", EvalError::InvalidFunctionPointer => @@ -68,8 +67,6 @@ impl<'tcx> Error for EvalError<'tcx> { "pointer offset outside bounds of allocation", EvalError::ReadPointerAsBytes => "a raw memory access tried to access part of a pointer value as raw bytes", - EvalError::ReadBytesAsPointer => - "attempted to interpret some raw bytes as a pointer address", EvalError::InvalidPointerMath => "attempted to do math or a comparison on pointers into different allocations", EvalError::ReadUndefBytes => diff --git a/src/interpreter/cast.rs b/src/interpreter/cast.rs index 06cbf2495dac..6227999569cf 100644 --- a/src/interpreter/cast.rs +++ b/src/interpreter/cast.rs @@ -25,8 +25,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { U16(u) => self.cast_const_int(u as u64, ty, false), U32(u) => self.cast_const_int(u as u64, ty, false), Char(c) => self.cast_const_int(c as u64, ty, false), - U64(u) | - IntegerPtr(u) => self.cast_const_int(u, ty, false), + U64(u) => self.cast_const_int(u, ty, false), FnPtr(ptr) | Ptr(ptr) => self.cast_ptr(ptr, ty), } @@ -74,7 +73,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyFloat(ast::FloatTy::F64) => Ok(F64(v as f64)), ty::TyFloat(ast::FloatTy::F32) if negative => Ok(F32(v as i64 as f32)), ty::TyFloat(ast::FloatTy::F32) => Ok(F32(v as f32)), - ty::TyRawPtr(_) => Ok(IntegerPtr(v)), + ty::TyRawPtr(_) => Ok(Ptr(Pointer::from_int(v as usize))), ty::TyChar if v as u8 as u64 == v => Ok(Char(v as u8 as char)), ty::TyChar => Err(EvalError::InvalidChar(v)), _ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))), diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index b590905264e6..9de72dc6225b 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -1064,13 +1064,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { &ty::TyRef(_, ty::TypeAndMut { ty, .. }) | &ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { if self.type_is_sized(ty) { - match self.memory.read_ptr(ptr) { - Ok(p) => PrimVal::Ptr(p), - Err(EvalError::ReadBytesAsPointer) => { - PrimVal::IntegerPtr(self.memory.read_usize(ptr)?) - } - Err(e) => return Err(e), - } + PrimVal::Ptr(self.memory.read_ptr(ptr)?) } else { bug!("primitive read of fat pointer type: {:?}", ty); } diff --git a/src/interpreter/terminator/intrinsics.rs b/src/interpreter/terminator/intrinsics.rs index f7fa1588b561..38b62254130f 100644 --- a/src/interpreter/terminator/intrinsics.rs +++ b/src/interpreter/terminator/intrinsics.rs @@ -132,18 +132,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr_arg = args_ptrs[0]; let offset = self.memory.read_isize(args_ptrs[1])?; - match self.memory.read_ptr(ptr_arg) { - Ok(ptr) => { - let result_ptr = ptr.offset(offset as isize * pointee_size); - self.memory.write_ptr(dest, result_ptr)?; - } - Err(EvalError::ReadBytesAsPointer) => { - let addr = self.memory.read_isize(ptr_arg)?; - let result_addr = addr + offset * pointee_size as i64; - self.memory.write_isize(dest, result_addr)?; - } - Err(e) => return Err(e), - } + let ptr = self.memory.read_ptr(ptr_arg)?; + let result_ptr = ptr.offset(offset as isize * pointee_size); + self.memory.write_ptr(dest, result_ptr)?; } "overflowing_sub" => { diff --git a/src/memory.rs b/src/memory.rs index 53c50e45e856..27e6ffff00eb 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -55,6 +55,12 @@ impl Pointer { pub fn points_to_zst(&self) -> bool { self.alloc_id == ZST_ALLOC_ID } + pub fn from_int(i: usize) -> Self { + Pointer { + alloc_id: ZST_ALLOC_ID, + offset: i, + } + } fn zst_ptr() -> Self { Pointer { alloc_id: ZST_ALLOC_ID, @@ -279,7 +285,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Some(alloc) => Ok(alloc), None => match self.functions.get(&id) { Some(_) => Err(EvalError::DerefFunctionPointer), - None if id == ZST_ALLOC_ID => Err(EvalError::ZstAllocAccess), + None if id == ZST_ALLOC_ID => Err(EvalError::InvalidMemoryAccess), None => Err(EvalError::DanglingPointerDeref), } } @@ -291,7 +297,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Some(alloc) => Ok(alloc), None => match self.functions.get(&id) { Some(_) => Err(EvalError::DerefFunctionPointer), - None if id == ZST_ALLOC_ID => Err(EvalError::ZstAllocAccess), + None if id == ZST_ALLOC_ID => Err(EvalError::InvalidMemoryAccess), None => Err(EvalError::DanglingPointerDeref), } } @@ -511,7 +517,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { let alloc = self.get(ptr.alloc_id)?; match alloc.relocations.get(&ptr.offset) { Some(&alloc_id) => Ok(Pointer { alloc_id: alloc_id, offset: offset }), - None => Err(EvalError::ReadBytesAsPointer), + None => Ok(Pointer::from_int(offset)), } } @@ -522,7 +528,6 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> { - let pointer_size = self.pointer_size(); match val { PrimVal::Bool(b) => self.write_bool(ptr, b), PrimVal::I8(n) => self.write_int(ptr, n as i64, 1), @@ -534,7 +539,6 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { PrimVal::U32(n) => self.write_uint(ptr, n as u64, 4), PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8), PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4), - PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size), PrimVal::F32(f) => self.write_f32(ptr, f), PrimVal::F64(f) => self.write_f64(ptr, f), PrimVal::FnPtr(p) | diff --git a/src/primval.rs b/src/primval.rs index 50ef05a245df..717ad99dbcd5 100644 --- a/src/primval.rs +++ b/src/primval.rs @@ -14,7 +14,6 @@ pub enum PrimVal { Ptr(Pointer), FnPtr(Pointer), - IntegerPtr(u64), Char(char), F32(f32), F64(f64), @@ -209,14 +208,8 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva }) } - (IntegerPtr(l), IntegerPtr(r)) => int_binops!(IntegerPtr, l, r), - - (Ptr(_), IntegerPtr(_)) | - (IntegerPtr(_), Ptr(_)) | (FnPtr(_), Ptr(_)) | - (Ptr(_), FnPtr(_)) | - (FnPtr(_), IntegerPtr(_)) | - (IntegerPtr(_), FnPtr(_)) => + (Ptr(_), FnPtr(_)) => unrelated_ptr_ops(bin_op)?, (FnPtr(l_ptr), FnPtr(r_ptr)) => match bin_op { diff --git a/tests/compile-fail/null_pointer_deref.rs b/tests/compile-fail/null_pointer_deref.rs index 3d1afe921561..fcf34ed44c93 100644 --- a/tests/compile-fail/null_pointer_deref.rs +++ b/tests/compile-fail/null_pointer_deref.rs @@ -1,4 +1,4 @@ fn main() { - let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: attempted to interpret some raw bytes as a pointer address + let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: tried to access memory through an invalid pointer panic!("this should never print: {}", x); } diff --git a/tests/compile-fail/wild_pointer_deref.rs b/tests/compile-fail/wild_pointer_deref.rs index 1f472489b4fc..937546fdc350 100644 --- a/tests/compile-fail/wild_pointer_deref.rs +++ b/tests/compile-fail/wild_pointer_deref.rs @@ -1,5 +1,5 @@ fn main() { let p = 42 as *const i32; - let x = unsafe { *p }; //~ ERROR: attempted to interpret some raw bytes as a pointer address + let x = unsafe { *p }; //~ ERROR: tried to access memory through an invalid pointer panic!("this should never print: {}", x); } diff --git a/tests/compile-fail/zst.rs b/tests/compile-fail/zst.rs index a244befed018..970cc9abc9da 100644 --- a/tests/compile-fail/zst.rs +++ b/tests/compile-fail/zst.rs @@ -1,4 +1,4 @@ fn main() { let x = &() as *const () as *const i32; - let _ = unsafe { *x }; //~ ERROR: tried to access the ZST allocation + let _ = unsafe { *x }; //~ ERROR: tried to access memory through an invalid pointer } diff --git a/tests/run-pass/zst.rs b/tests/run-pass/zst.rs index 4ebb2001e720..78d3025587f0 100644 --- a/tests/run-pass/zst.rs +++ b/tests/run-pass/zst.rs @@ -21,4 +21,6 @@ fn main() { assert_eq!(use_zst(), A); assert_eq!(&A as *const A as *const (), &() as *const _); assert_eq!(&A as *const A, &A as *const A); + let x = 42 as *mut (); + unsafe { *x = (); } }