Error out when "primitive MIR math" (as opposed to unchecked intrinsics) overflows
Fixes #178
This commit is contained in:
parent
e1562fbe71
commit
3e1596d8c9
@ -23,7 +23,6 @@ pub enum EvalError<'tcx> {
|
||||
},
|
||||
ReadPointerAsBytes,
|
||||
InvalidPointerMath,
|
||||
OverflowingPointerMath,
|
||||
ReadUndefBytes,
|
||||
DeadLocal,
|
||||
InvalidBoolOp(mir::BinOp),
|
||||
@ -32,6 +31,7 @@ pub enum EvalError<'tcx> {
|
||||
ExecuteMemory,
|
||||
ArrayIndexOutOfBounds(Span, u64, u64),
|
||||
Math(Span, ConstMathErr),
|
||||
OverflowingMath,
|
||||
InvalidChar(u128),
|
||||
OutOfMemory {
|
||||
allocation_size: u64,
|
||||
@ -83,8 +83,6 @@ impl<'tcx> Error for EvalError<'tcx> {
|
||||
"a raw memory access tried to access part of a pointer value as raw bytes",
|
||||
EvalError::InvalidPointerMath =>
|
||||
"attempted to do math or a comparison on pointers into different allocations",
|
||||
EvalError::OverflowingPointerMath =>
|
||||
"attempted to do overflowing math on a pointer",
|
||||
EvalError::ReadUndefBytes =>
|
||||
"attempted to read undefined bytes",
|
||||
EvalError::DeadLocal =>
|
||||
@ -100,6 +98,8 @@ impl<'tcx> Error for EvalError<'tcx> {
|
||||
"array index out of bounds",
|
||||
EvalError::Math(..) =>
|
||||
"mathematical operation failed",
|
||||
EvalError::OverflowingMath =>
|
||||
"attempted to do overflowing math",
|
||||
EvalError::NoMirFor(..) =>
|
||||
"mir not found",
|
||||
EvalError::InvalidChar(..) =>
|
||||
|
@ -452,8 +452,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
BinaryOp(bin_op, ref left, ref right) => {
|
||||
// ignore overflow bit, rustc inserts check branches for us
|
||||
self.intrinsic_overflowing(bin_op, left, right, dest, dest_ty)?;
|
||||
if self.intrinsic_overflowing(bin_op, left, right, dest, dest_ty)? {
|
||||
// There was an overflow in an unchecked binop. Right now, we consider this an error and bail out.
|
||||
// The rationale is that the reason rustc emits unchecked binops in release mode (vs. the checked binops
|
||||
// it emits in debug mode) is performance, but it doesn't cust us any performance in miri.
|
||||
// If, however, the compiler ever starts transforming unchecked intrinsics into unchecked binops,
|
||||
// we have to go back to just ignoring the overflow here.
|
||||
return Err(EvalError::OverflowingMath);
|
||||
}
|
||||
}
|
||||
|
||||
CheckedBinaryOp(bin_op, ref left, ref right) => {
|
||||
@ -869,7 +875,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
self.memory.check_bounds(ptr, false)?;
|
||||
Ok(ptr)
|
||||
} else {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
Err(EvalError::OverflowingMath)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl Pointer {
|
||||
if let Some(res) = self.offset.checked_sub(n) {
|
||||
Ok(Pointer::new(self.alloc_id, res))
|
||||
} else {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
Err(EvalError::OverflowingMath)
|
||||
}
|
||||
} else {
|
||||
self.offset(i as u64, layout)
|
||||
@ -83,12 +83,12 @@ impl Pointer {
|
||||
pub fn offset<'tcx>(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
if let Some(res) = self.offset.checked_add(i) {
|
||||
if res as u128 >= (1u128 << layout.pointer_size.bits()) {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
Err(EvalError::OverflowingMath)
|
||||
} else {
|
||||
Ok(Pointer::new(self.alloc_id, res))
|
||||
}
|
||||
} else {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
Err(EvalError::OverflowingMath)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// error-pattern: overflowing math on a pointer
|
||||
// error-pattern: overflowing math
|
||||
fn main() {
|
||||
let v = [0i8; 4];
|
||||
let x = &v as *const i8;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//error-pattern: overflowing math on a pointer
|
||||
//error-pattern: overflowing math
|
||||
fn main() {
|
||||
let v = [1i8, 2];
|
||||
let x = &v[1] as *const i8;
|
||||
|
Loading…
x
Reference in New Issue
Block a user