]> git.lizzy.rs Git - rust.git/commitdiff
Check for undefinedness when reading from memory.
authorScott Olson <scott@solson.me>
Sun, 27 Mar 2016 05:56:49 +0000 (23:56 -0600)
committerScott Olson <scott@solson.me>
Sun, 27 Mar 2016 05:56:49 +0000 (23:56 -0600)
src/error.rs
src/memory.rs

index f16bdc3b6b3c8400bf638992cedf50ba47f70a4a..08ef5a46ff2d499b4e40038c21319fd2000a7a25 100644 (file)
@@ -9,6 +9,7 @@ pub enum EvalError {
     ReadPointerAsBytes,
     ReadBytesAsPointer,
     InvalidPointerMath,
+    ReadUndefBytes,
 }
 
 pub type EvalResult<T> = Result<T, EvalError>;
@@ -16,15 +17,20 @@ pub enum EvalError {
 impl Error for EvalError {
     fn description(&self) -> &str {
         match *self {
-            EvalError::DanglingPointerDeref => "dangling pointer was dereferenced",
-            EvalError::InvalidBool => "invalid boolean value read",
-            EvalError::PointerOutOfBounds => "pointer offset outside bounds of allocation",
+            EvalError::DanglingPointerDeref =>
+                "dangling pointer was dereferenced",
+            EvalError::InvalidBool =>
+                "invalid boolean value read",
+            EvalError::PointerOutOfBounds =>
+                "pointer offset outside bounds of allocation",
             EvalError::ReadPointerAsBytes =>
                 "a raw memory access tried to access part of a pointer value as raw bytes",
             EvalError::ReadBytesAsPointer =>
                 "attempted to interpret some raw bytes as a pointer address",
             EvalError::InvalidPointerMath =>
                 "attempted to do math or a comparison on pointers into different allocations",
+            EvalError::ReadUndefBytes =>
+                "attempted to read undefined bytes",
         }
     }
 
index 4a3160607b6547e8cc2ae8aa42861df3e5cd8ec3..b44a412a5880fafe77f72684d61f59203ddae997 100644 (file)
@@ -155,7 +155,7 @@ fn get_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<&[u8]> {
         if try!(self.relocations(ptr, size)).count() != 0 {
             return Err(EvalError::ReadPointerAsBytes);
         }
-        // TODO(tsion): Track and check for undef bytes.
+        try!(self.check_defined(ptr, size));
         self.get_bytes_unchecked(ptr, size)
     }
 
@@ -170,7 +170,6 @@ fn get_bytes_mut(&mut self, ptr: Pointer, size: usize) -> EvalResult<&mut [u8]>
     ////////////////////////////////////////////////////////////////////////////////
 
     pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
-        // TODO(tsion): Track and check for undef bytes.
         try!(self.check_relocation_edges(src, size));
 
         let src_bytes = try!(self.get_bytes_unchecked_mut(src, size)).as_mut_ptr();
@@ -187,6 +186,7 @@ pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<(
             }
         }
 
+        // TODO(tsion): Copy undef ranges from src to dest.
         self.copy_relocations(src, dest, size)
     }
 
@@ -196,6 +196,7 @@ pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<()> {
 
     pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<Pointer> {
         let size = self.pointer_size;
+        try!(self.check_defined(ptr, size));
         let offset = try!(self.get_bytes_unchecked(ptr, size))
             .read_uint::<NativeEndian>(size).unwrap() as usize;
         let alloc = try!(self.get(ptr.alloc_id));
@@ -291,6 +292,7 @@ fn relocations(&self, ptr: Pointer, size: usize)
         Ok(try!(self.get(ptr.alloc_id)).relocations.range(Included(&start), Excluded(&end)))
     }
 
+    // TODO(tsion): Mark partially-overwritten relocations as undefined.
     fn clear_relocations(&mut self, ptr: Pointer, size: usize) -> EvalResult<()> {
         let keys: Vec<_> = try!(self.relocations(ptr, size)).map(|(&k, _)| k).collect();
         let alloc = try!(self.get_mut(ptr.alloc_id));
@@ -324,6 +326,15 @@ fn copy_relocations(&mut self, src: Pointer, dest: Pointer, size: usize) -> Eval
     // Undefined bytes
     ////////////////////////////////////////////////////////////////////////////////
 
+    fn check_defined(&self, ptr: Pointer, size: usize) -> EvalResult<()> {
+        let alloc = try!(self.get(ptr.alloc_id));
+        if !alloc.is_range_defined(ptr.offset, ptr.offset + size) {
+            panic!();
+            return Err(EvalError::ReadUndefBytes);
+        }
+        Ok(())
+    }
+
     fn mark_definedness(&mut self, ptr: Pointer, size: usize, new_state: bool) -> EvalResult<()> {
         let mut alloc = try!(self.get_mut(ptr.alloc_id));
         alloc.mark_definedness(ptr.offset, ptr.offset + size, new_state);