From acf2ceb534e1f72f088110bf3a348a34ce040ac1 Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Sat, 26 Mar 2016 23:56:49 -0600 Subject: [PATCH] Check for undefinedness when reading from memory. --- src/error.rs | 12 +++++++++--- src/memory.rs | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/error.rs b/src/error.rs index f16bdc3b6b3..08ef5a46ff2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,6 +9,7 @@ pub enum EvalError { ReadPointerAsBytes, ReadBytesAsPointer, InvalidPointerMath, + ReadUndefBytes, } pub type EvalResult = Result; @@ -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", } } diff --git a/src/memory.rs b/src/memory.rs index 4a3160607b6..b44a412a588 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -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 { let size = self.pointer_size; + try!(self.check_defined(ptr, size)); let offset = try!(self.get_bytes_unchecked(ptr, size)) .read_uint::(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); -- 2.44.0