about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2017-07-19 20:24:09 -0700
committerRalf Jung <post@ralfj.de>2017-07-19 20:24:09 -0700
commitede055c2be77ef4326ac96c255f7b6b7a37f3a18 (patch)
treef7eb95f8df952e0a5aee8b83b4bca386442c5f00
parentf9818bf8187b9a9d9ce9828a3fa1213fc08bdd94 (diff)
downloadrust-ede055c2be77ef4326ac96c255f7b6b7a37f3a18.tar.gz
rust-ede055c2be77ef4326ac96c255f7b6b7a37f3a18.zip
fix checking alignment of pointer loads
-rw-r--r--src/eval_context.rs16
-rw-r--r--src/memory.rs8
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;