2016-03-14 21:48:00 -06:00
|
|
|
use std::error::Error;
|
|
|
|
use std::fmt;
|
2016-05-30 15:27:52 +02:00
|
|
|
use rustc::mir::repr as mir;
|
2016-06-14 10:34:54 +02:00
|
|
|
use rustc::ty::BareFnTy;
|
2016-06-01 11:22:37 +02:00
|
|
|
use memory::Pointer;
|
2016-06-17 13:09:20 +02:00
|
|
|
use rustc_const_math::ConstMathErr;
|
|
|
|
use syntax::codemap::Span;
|
2016-03-14 21:48:00 -06:00
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
2016-06-14 10:34:54 +02:00
|
|
|
pub enum EvalError<'tcx> {
|
|
|
|
FunctionPointerTyMismatch(&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>),
|
2016-03-14 21:48:00 -06:00
|
|
|
DanglingPointerDeref,
|
2016-06-08 13:43:34 +02:00
|
|
|
InvalidFunctionPointer,
|
2016-03-14 21:48:00 -06:00
|
|
|
InvalidBool,
|
2016-03-28 21:08:08 -06:00
|
|
|
InvalidDiscriminant,
|
2016-05-31 12:05:25 +02:00
|
|
|
PointerOutOfBounds {
|
2016-06-01 11:22:37 +02:00
|
|
|
ptr: Pointer,
|
2016-05-31 12:05:25 +02:00
|
|
|
size: usize,
|
2016-06-01 11:22:37 +02:00
|
|
|
allocation_size: usize,
|
2016-05-31 12:05:25 +02:00
|
|
|
},
|
2016-03-18 23:03:46 -06:00
|
|
|
ReadPointerAsBytes,
|
2016-03-17 07:24:10 -06:00
|
|
|
ReadBytesAsPointer,
|
2016-03-18 23:03:46 -06:00
|
|
|
InvalidPointerMath,
|
2016-03-26 23:56:49 -06:00
|
|
|
ReadUndefBytes,
|
2016-05-30 15:27:52 +02:00
|
|
|
InvalidBoolOp(mir::BinOp),
|
|
|
|
Unimplemented(String),
|
2016-06-13 11:39:15 +02:00
|
|
|
DerefFunctionPointer,
|
|
|
|
ExecuteMemory,
|
2016-06-17 13:09:20 +02:00
|
|
|
ArrayIndexOutOfBounds(Span, u64, u64),
|
|
|
|
Math(Span, ConstMathErr),
|
2016-06-20 12:29:45 +02:00
|
|
|
InvalidChar(u32),
|
2016-07-05 10:47:10 +02:00
|
|
|
OutOfMemory {
|
|
|
|
allocation_size: u64,
|
|
|
|
memory_size: u64,
|
|
|
|
memory_usage: u64,
|
|
|
|
}
|
2016-03-14 21:48:00 -06:00
|
|
|
}
|
|
|
|
|
2016-06-14 10:34:54 +02:00
|
|
|
pub type EvalResult<'tcx, T> = Result<T, EvalError<'tcx>>;
|
2016-03-14 21:48:00 -06:00
|
|
|
|
2016-06-14 10:34:54 +02:00
|
|
|
impl<'tcx> Error for EvalError<'tcx> {
|
2016-03-14 21:48:00 -06:00
|
|
|
fn description(&self) -> &str {
|
|
|
|
match *self {
|
2016-06-14 10:34:54 +02:00
|
|
|
EvalError::FunctionPointerTyMismatch(..) =>
|
|
|
|
"tried to call a function through a function pointer of a different type",
|
2016-03-26 23:56:49 -06:00
|
|
|
EvalError::DanglingPointerDeref =>
|
|
|
|
"dangling pointer was dereferenced",
|
2016-06-08 13:43:34 +02:00
|
|
|
EvalError::InvalidFunctionPointer =>
|
|
|
|
"tried to use a pointer as a function pointer",
|
2016-03-26 23:56:49 -06:00
|
|
|
EvalError::InvalidBool =>
|
|
|
|
"invalid boolean value read",
|
2016-03-28 21:08:08 -06:00
|
|
|
EvalError::InvalidDiscriminant =>
|
|
|
|
"invalid enum discriminant value read",
|
2016-05-31 12:05:25 +02:00
|
|
|
EvalError::PointerOutOfBounds { .. } =>
|
2016-03-26 23:56:49 -06:00
|
|
|
"pointer offset outside bounds of allocation",
|
2016-03-18 23:03:46 -06:00
|
|
|
EvalError::ReadPointerAsBytes =>
|
|
|
|
"a raw memory access tried to access part of a pointer value as raw bytes",
|
2016-03-17 07:24:10 -06:00
|
|
|
EvalError::ReadBytesAsPointer =>
|
2016-03-18 23:03:46 -06:00
|
|
|
"attempted to interpret some raw bytes as a pointer address",
|
|
|
|
EvalError::InvalidPointerMath =>
|
|
|
|
"attempted to do math or a comparison on pointers into different allocations",
|
2016-03-26 23:56:49 -06:00
|
|
|
EvalError::ReadUndefBytes =>
|
|
|
|
"attempted to read undefined bytes",
|
2016-05-30 15:27:52 +02:00
|
|
|
EvalError::InvalidBoolOp(_) =>
|
|
|
|
"invalid boolean operation",
|
|
|
|
EvalError::Unimplemented(ref msg) => msg,
|
2016-06-13 11:39:15 +02:00
|
|
|
EvalError::DerefFunctionPointer =>
|
|
|
|
"tried to dereference a function pointer",
|
|
|
|
EvalError::ExecuteMemory =>
|
|
|
|
"tried to treat a memory pointer as a function pointer",
|
2016-06-17 13:09:20 +02:00
|
|
|
EvalError::ArrayIndexOutOfBounds(..) =>
|
|
|
|
"array index out of bounds",
|
|
|
|
EvalError::Math(..) =>
|
|
|
|
"mathematical operation failed",
|
2016-06-20 12:29:45 +02:00
|
|
|
EvalError::InvalidChar(..) =>
|
|
|
|
"tried to interpret an invalid 32-bit value as a char",
|
2016-07-05 10:47:10 +02:00
|
|
|
EvalError::OutOfMemory{..} =>
|
|
|
|
"could not allocate more memory"
|
2016-03-14 21:48:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cause(&self) -> Option<&Error> { None }
|
|
|
|
}
|
|
|
|
|
2016-06-14 10:34:54 +02:00
|
|
|
impl<'tcx> fmt::Display for EvalError<'tcx> {
|
2016-03-14 21:48:00 -06:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2016-05-31 12:05:25 +02:00
|
|
|
match *self {
|
2016-06-01 11:22:37 +02:00
|
|
|
EvalError::PointerOutOfBounds { ptr, size, allocation_size } => {
|
|
|
|
write!(f, "memory access of {}..{} outside bounds of allocation {} which has size {}",
|
|
|
|
ptr.offset, ptr.offset + size, ptr.alloc_id, allocation_size)
|
|
|
|
},
|
2016-06-14 10:34:54 +02:00
|
|
|
EvalError::FunctionPointerTyMismatch(expected, got) =>
|
|
|
|
write!(f, "tried to call a function of type {:?} through a function pointer of type {:?}", expected, got),
|
2016-06-17 13:09:20 +02:00
|
|
|
EvalError::ArrayIndexOutOfBounds(span, len, index) =>
|
2016-06-21 09:43:27 +02:00
|
|
|
write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
|
2016-06-17 13:09:20 +02:00
|
|
|
EvalError::Math(span, ref err) =>
|
2016-06-21 09:43:27 +02:00
|
|
|
write!(f, "{:?} at {:?}", err, span),
|
2016-06-20 12:29:45 +02:00
|
|
|
EvalError::InvalidChar(c) =>
|
2016-06-21 09:43:27 +02:00
|
|
|
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
|
2016-07-05 10:47:10 +02:00
|
|
|
EvalError::OutOfMemory { allocation_size, memory_size, memory_usage } =>
|
|
|
|
write!(f, "tried to allocate {} more bytes, but only {} bytes are free of the {} byte memory",
|
|
|
|
allocation_size, memory_size - memory_usage, memory_size),
|
2016-05-31 12:05:25 +02:00
|
|
|
_ => write!(f, "{}", self.description()),
|
|
|
|
}
|
2016-03-14 21:48:00 -06:00
|
|
|
}
|
|
|
|
}
|