diff options
| author | Ralf Jung <post@ralfj.de> | 2017-07-19 20:24:09 -0700 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2017-07-19 20:24:09 -0700 |
| commit | ede055c2be77ef4326ac96c255f7b6b7a37f3a18 (patch) | |
| tree | f7eb95f8df952e0a5aee8b83b4bca386442c5f00 | |
| parent | f9818bf8187b9a9d9ce9828a3fa1213fc08bdd94 (diff) | |
| download | rust-ede055c2be77ef4326ac96c255f7b6b7a37f3a18.tar.gz rust-ede055c2be77ef4326ac96c255f7b6b7a37f3a18.zip | |
fix checking alignment of pointer loads
| -rw-r--r-- | src/eval_context.rs | 16 | ||||
| -rw-r--r-- | src/memory.rs | 8 |
2 files changed, 15 insertions, 9 deletions
diff --git a/src/eval_context.rs b/src/eval_context.rs index f2790bd6936..5bcd8368933 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -1101,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. @@ -1378,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?), } } @@ -1393,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; |
