Skip to content

Commit f02d9e6

Browse files
authored
Merge pull request #259 from RalfJung/ref-validate
No longer check aligment and non-NULLness on `&`
2 parents 27c6447 + 7648cca commit f02d9e6

8 files changed

+28
-31
lines changed

src/cast.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
4646
fn cast_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> {
4747
use rustc::ty::TypeVariants::*;
4848
match ty.sty {
49-
TyBool if v == 0 => Ok(PrimVal::from_bool(false)),
50-
TyBool if v == 1 => Ok(PrimVal::from_bool(true)),
51-
TyBool => Err(EvalError::InvalidBool),
49+
// Casts to bool are not permitted by rustc, no need to handle them here.
5250

5351
TyInt(IntTy::I8) => Ok(PrimVal::Bytes(v as i128 as i8 as u128)),
5452
TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i128 as i16 as u128)),

src/eval_context.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
670670

671671
Ref(_, _, ref lvalue) => {
672672
let src = self.eval_lvalue(lvalue)?;
673-
// We ignore the alignment of the lvalue here -- this rvalue produces sth. of type &, which must always be aligned.
673+
// We ignore the alignment of the lvalue here -- special handling for packed structs ends
674+
// at the `&` operator.
674675
let (ptr, extra, _aligned) = self.force_allocation(src)?.to_ptr_extra_aligned();
675-
let ty = self.lvalue_ty(lvalue);
676676

677677
let val = match extra {
678678
LvalueExtra::None => ptr.to_value(),
@@ -682,10 +682,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
682682
bug!("attempted to take a reference to an enum downcast lvalue"),
683683
};
684684

685-
// Check alignment and non-NULLness.
686-
let (_, align) = self.size_and_align_of_dst(ty, val)?;
687-
self.memory.check_align(ptr, align)?;
688-
689685
self.write_value(val, dest, dest_ty)?;
690686
}
691687

@@ -1105,6 +1101,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11051101
dest: Lvalue<'tcx>,
11061102
dest_ty: Ty<'tcx>,
11071103
) -> EvalResult<'tcx> {
1104+
//trace!("Writing {:?} to {:?} at type {:?}", src_val, dest, dest_ty);
11081105
// Note that it is really important that the type here is the right one, and matches the type things are read at.
11091106
// In case `src_val` is a `ByValPair`, we don't do any magic here to handle padding properly, which is only
11101107
// correct if we never look at this data with the wrong type.
@@ -1382,7 +1379,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
13821379
// if we transmute a ptr to an isize, reading it back into a primval shouldn't panic
13831380
// Due to read_ptr ignoring the sign, we need to jump around some hoops
13841381
match self.memory.read_int(ptr.to_ptr()?, size) {
1385-
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
1382+
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() =>
1383+
// Reading as an int failed because we are seeing ptr bytes *and* we are actually reading at ptr size.
1384+
// Let's try again, reading a ptr this time.
1385+
self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
13861386
other => PrimVal::from_i128(other?),
13871387
}
13881388
}
@@ -1397,11 +1397,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
13971397
U128 => 16,
13981398
Us => self.memory.pointer_size(),
13991399
};
1400-
if size == self.memory.pointer_size() {
1401-
// if we transmute a ptr to an usize, reading it back into a primval shouldn't panic
1402-
self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval()
1403-
} else {
1404-
PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?)
1400+
// if we transmute a ptr to an usize, reading it back into a primval shouldn't panic
1401+
// for consistency's sake, we use the same code as above
1402+
match self.memory.read_uint(ptr.to_ptr()?, size) {
1403+
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
1404+
other => PrimVal::from_u128(other?),
14051405
}
14061406
}
14071407

src/memory.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -720,12 +720,14 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
720720

721721
pub fn read_ptr(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Pointer> {
722722
let size = self.pointer_size();
723-
if self.check_defined(ptr, size).is_err() {
724-
return Ok(PrimVal::Undef.into());
725-
}
726723
self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer
727724
let endianess = self.endianess();
728725
let bytes = self.get_bytes_unchecked(ptr, size, size)?;
726+
// Undef check happens *after* we established that the alignment is correct.
727+
// We must not return Ok() for unaligned pointers!
728+
if self.check_defined(ptr, size).is_err() {
729+
return Ok(PrimVal::Undef.into());
730+
}
729731
let offset = read_target_uint(endianess, bytes).unwrap();
730732
assert_eq!(offset as u64 as u128, offset);
731733
let offset = offset as u64;

tests/compile-fail/int_ptr_cast.rs

-5
This file was deleted.

tests/compile-fail/int_ptr_cast2.rs

-5
This file was deleted.

tests/compile-fail/reference_to_packed.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ fn main() {
1111
x: 42,
1212
y: 99,
1313
};
14-
let p = &foo.x; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
15-
let i = *p;
14+
let p = &foo.x;
15+
let i = *p; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
1616
}

tests/compile-fail/unaligned_ptr_cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ fn main() {
22
let x = &2u16;
33
let x = x as *const _ as *const u32;
44
// This must fail because alignment is violated
5-
let _ = unsafe { &*x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required
5+
let _x = unsafe { *x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required
66
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let x = &2u16;
3+
let x = x as *const _ as *const *const u8;
4+
// This must fail because alignment is violated. Test specifically for loading pointers, which have special code
5+
// in miri's memory.
6+
let _x = unsafe { *x }; //~ ERROR: tried to access memory with alignment 2, but alignment
7+
}

0 commit comments

Comments
 (0)