diff options
| author | Oliver Schneider <oli-obk@users.noreply.github.com> | 2017-07-20 07:09:52 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-20 07:09:52 +0200 |
| commit | f02d9e63fde6d692b38b3843b16132c0b79a7ef6 (patch) | |
| tree | d9ecc6add6a7ded16f8d14c449e4616a9fff3bb1 | |
| parent | 27c64479cd0e449634ef61bbf42dff42cfa1fc28 (diff) | |
| parent | 7648ccaae1296a43d3050536f9ed774782f9c775 (diff) | |
| download | rust-f02d9e63fde6d692b38b3843b16132c0b79a7ef6.tar.gz rust-f02d9e63fde6d692b38b3843b16132c0b79a7ef6.zip | |
Merge pull request #259 from RalfJung/ref-validate
No longer check aligment and non-NULLness on `&`
| -rw-r--r-- | src/cast.rs | 4 | ||||
| -rw-r--r-- | src/eval_context.rs | 24 | ||||
| -rw-r--r-- | src/memory.rs | 8 | ||||
| -rw-r--r-- | tests/compile-fail/int_ptr_cast.rs | 5 | ||||
| -rw-r--r-- | tests/compile-fail/int_ptr_cast2.rs | 5 | ||||
| -rw-r--r-- | tests/compile-fail/reference_to_packed.rs | 4 | ||||
| -rw-r--r-- | tests/compile-fail/unaligned_ptr_cast.rs | 2 | ||||
| -rw-r--r-- | tests/compile-fail/unaligned_ptr_cast2.rs | 7 |
8 files changed, 28 insertions, 31 deletions
diff --git a/src/cast.rs b/src/cast.rs index cb0b1121709..0fa38366e1c 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -46,9 +46,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { fn cast_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> { use rustc::ty::TypeVariants::*; match ty.sty { - TyBool if v == 0 => Ok(PrimVal::from_bool(false)), - TyBool if v == 1 => Ok(PrimVal::from_bool(true)), - TyBool => Err(EvalError::InvalidBool), + // Casts to bool are not permitted by rustc, no need to handle them here. TyInt(IntTy::I8) => Ok(PrimVal::Bytes(v as i128 as i8 as u128)), TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i128 as i16 as u128)), diff --git a/src/eval_context.rs b/src/eval_context.rs index 2f28063ff86..5bcd8368933 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -670,9 +670,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ref(_, _, ref lvalue) => { let src = self.eval_lvalue(lvalue)?; - // We ignore the alignment of the lvalue here -- this rvalue produces sth. of type &, which must always be aligned. + // We ignore the alignment of the lvalue here -- special handling for packed structs ends + // at the `&` operator. let (ptr, extra, _aligned) = self.force_allocation(src)?.to_ptr_extra_aligned(); - let ty = self.lvalue_ty(lvalue); let val = match extra { LvalueExtra::None => ptr.to_value(), @@ -682,10 +682,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { bug!("attempted to take a reference to an enum downcast lvalue"), }; - // Check alignment and non-NULLness. - let (_, align) = self.size_and_align_of_dst(ty, val)?; - self.memory.check_align(ptr, align)?; - self.write_value(val, dest, dest_ty)?; } @@ -1105,6 +1101,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { dest: Lvalue<'tcx>, dest_ty: Ty<'tcx>, ) -> EvalResult<'tcx> { + //trace!("Writing {:?} to {:?} at type {:?}", src_val, dest, dest_ty); // Note that it is really important that the type here is the right one, and matches the type things are read at. // In case `src_val` is a `ByValPair`, we don't do any magic here to handle padding properly, which is only // correct if we never look at this data with the wrong type. @@ -1382,7 +1379,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // if we transmute a ptr to an isize, reading it back into a primval shouldn't panic // Due to read_ptr ignoring the sign, we need to jump around some hoops match self.memory.read_int(ptr.to_ptr()?, size) { - Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(), + Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => + // Reading as an int failed because we are seeing ptr bytes *and* we are actually reading at ptr size. + // Let's try again, reading a ptr this time. + self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(), other => PrimVal::from_i128(other?), } } @@ -1397,11 +1397,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { U128 => 16, Us => self.memory.pointer_size(), }; - if size == self.memory.pointer_size() { - // if we transmute a ptr to an usize, reading it back into a primval shouldn't panic - self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval() - } else { - PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?) + // if we transmute a ptr to an usize, reading it back into a primval shouldn't panic + // for consistency's sake, we use the same code as above + match self.memory.read_uint(ptr.to_ptr()?, size) { + Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(), + other => PrimVal::from_u128(other?), } } diff --git a/src/memory.rs b/src/memory.rs index cf7f969be8e..71f4c329b5b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -720,12 +720,14 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn read_ptr(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Pointer> { let size = self.pointer_size(); - if self.check_defined(ptr, size).is_err() { - return Ok(PrimVal::Undef.into()); - } self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer let endianess = self.endianess(); let bytes = self.get_bytes_unchecked(ptr, size, size)?; + // Undef check happens *after* we established that the alignment is correct. + // We must not return Ok() for unaligned pointers! + if self.check_defined(ptr, size).is_err() { + return Ok(PrimVal::Undef.into()); + } let offset = read_target_uint(endianess, bytes).unwrap(); assert_eq!(offset as u64 as u128, offset); let offset = offset as u64; diff --git a/tests/compile-fail/int_ptr_cast.rs b/tests/compile-fail/int_ptr_cast.rs deleted file mode 100644 index ae5f65a7166..00000000000 --- a/tests/compile-fail/int_ptr_cast.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let x = 2usize as *const u32; - // This must fail because alignment is violated - let _ = unsafe { &*x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required -} diff --git a/tests/compile-fail/int_ptr_cast2.rs b/tests/compile-fail/int_ptr_cast2.rs deleted file mode 100644 index 1897066f7bc..00000000000 --- a/tests/compile-fail/int_ptr_cast2.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let x = 0usize as *const u32; - // This must fail because the pointer is NULL - let _ = unsafe { &*x }; //~ ERROR: invalid use of NULL pointer -} diff --git a/tests/compile-fail/reference_to_packed.rs b/tests/compile-fail/reference_to_packed.rs index 4cf353298b9..5ca733a64df 100644 --- a/tests/compile-fail/reference_to_packed.rs +++ b/tests/compile-fail/reference_to_packed.rs @@ -11,6 +11,6 @@ fn main() { x: 42, y: 99, }; - let p = &foo.x; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required - let i = *p; + let p = &foo.x; + let i = *p; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required } diff --git a/tests/compile-fail/unaligned_ptr_cast.rs b/tests/compile-fail/unaligned_ptr_cast.rs index fcab430f8fc..8ad1b323250 100644 --- a/tests/compile-fail/unaligned_ptr_cast.rs +++ b/tests/compile-fail/unaligned_ptr_cast.rs @@ -2,5 +2,5 @@ fn main() { let x = &2u16; let x = x as *const _ as *const u32; // This must fail because alignment is violated - let _ = unsafe { &*x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required + let _x = unsafe { *x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required } diff --git a/tests/compile-fail/unaligned_ptr_cast2.rs b/tests/compile-fail/unaligned_ptr_cast2.rs new file mode 100644 index 00000000000..15fb7dd3136 --- /dev/null +++ b/tests/compile-fail/unaligned_ptr_cast2.rs @@ -0,0 +1,7 @@ +fn main() { + let x = &2u16; + let x = x as *const _ as *const *const u8; + // This must fail because alignment is violated. Test specifically for loading pointers, which have special code + // in miri's memory. + let _x = unsafe { *x }; //~ ERROR: tried to access memory with alignment 2, but alignment +} |
