ReadPointerAsBytes,
ReadBytesAsPointer,
InvalidPointerMath,
+ ReadUndefBytes,
}
pub type EvalResult<T> = Result<T, 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",
}
}
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)
}
////////////////////////////////////////////////////////////////////////////////
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();
}
}
+ // TODO(tsion): Copy undef ranges from src to dest.
self.copy_relocations(src, dest, size)
}
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));
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));
// 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);