提交 f02d9e63 编写于 作者: O Oliver Schneider 提交者: GitHub

Merge pull request #259 from RalfJung/ref-validate

No longer check aligment and non-NULLness on `&`
......@@ -46,9 +46,7 @@ fn cast_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimV
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)),
......
......@@ -670,9 +670,9 @@ pub(super) fn eval_rvalue_into_lvalue(
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 @@ pub(super) fn eval_rvalue_into_lvalue(
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 @@ pub(super) fn write_value(
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 @@ fn try_read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Opt
// 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 @@ fn try_read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Opt
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?),
}
}
......
......@@ -720,12 +720,14 @@ pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<
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;
......
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
}
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
}
......@@ -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
}
......@@ -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
}
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
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册