Skip to content

Miri error reform #69839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fmt, tweak messages and bless
  • Loading branch information
RalfJung committed Mar 11, 2020
commit d02543a453f0381c92339301fc86bcc08c70abcd
45 changes: 25 additions & 20 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_hir as hir;
use rustc_macros::HashStable;
use rustc_session::CtfeBacktrace;
use rustc_span::{Pos, Span, def_id::DefId};
use std::{any::Any, env, fmt};
use std::{any::Any, fmt};

#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
pub enum ErrorHandled {
Expand Down Expand Up @@ -326,7 +326,10 @@ pub enum UndefinedBehaviorInfo {
/// An enum discriminant was set to a value which was outside the range of valid values.
InvalidDiscriminant(ScalarMaybeUndef),
/// A slice/array index projection went out-of-bounds.
BoundsCheckFailed { len: u64, index: u64 },
BoundsCheckFailed {
len: u64,
index: u64,
},
/// Something was divided by 0 (x / 0).
DivisionByZero,
/// Something was "remainded" by 0 (x % 0).
Expand Down Expand Up @@ -395,16 +398,14 @@ impl fmt::Debug for UndefinedBehaviorInfo {
"reading a null-terminated string starting at {:?} with no null found before end of allocation",
p,
),
PointerUseAfterFree(a) => write!(
f,
"pointer to allocation {:?} was dereferenced after allocation got freed",
a
),
PointerUseAfterFree(a) => {
write!(f, "pointer to {:?} was dereferenced after this allocation got freed", a)
}
InvalidNullPointerUsage => write!(f, "invalid use of NULL pointer"),
PointerOutOfBounds { ptr, msg, allocation_size } => write!(
f,
"{} failed: pointer must be in-bounds at offset {}, \
but is outside bounds of allocation {} which has size {}",
but is outside bounds of {} which has size {}",
msg,
ptr.offset.bytes(),
ptr.alloc_id,
Expand All @@ -416,16 +417,23 @@ impl fmt::Debug for UndefinedBehaviorInfo {
has.bytes(),
required.bytes()
),
WriteToReadOnly(a) => write!(f, "writing to read-only allocation {:?}", a),
WriteToReadOnly(a) => write!(f, "writing to {:?} which is read-only", a),
InvalidFunctionPointer(p) => {
write!(f, "using {:?} as function pointer but it does not point to a function", p)
}
DerefFunctionPointer(a) => write!(f, "accessing data behind function pointer allocation {:?}", a),
DerefFunctionPointer(a) => write!(f, "accessing {:?} which contains a function", a),
ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
InvalidBool(b) => write!(f, "interpreting an invalid 8-bit value as a bool: {}", b),
InvalidChar(c) => write!(f, "interpreting an invalid 32-bit value as a char: {}", c),
InvalidUndefBytes(Some(p)) => write!(f, "reading uninitialized memory at {:?}, but this operation requires initialized memory", p),
InvalidUndefBytes(None) => write!(f, "using uninitialized data, but this operation requires initialized memory"),
InvalidUndefBytes(Some(p)) => write!(
f,
"reading uninitialized memory at {:?}, but this operation requires initialized memory",
p
),
InvalidUndefBytes(None) => write!(
f,
"using uninitialized data, but this operation requires initialized memory"
),
DeadLocal => write!(f, "accessing a dead local variable"),
ReadFromReturnPlace => write!(f, "tried to read from the return place"),
}
Expand Down Expand Up @@ -472,21 +480,18 @@ impl fmt::Debug for UnsupportedOpInfo {
ConstPropUnsupported(ref msg) => {
write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
}
ReadForeignStatic(did) => write!(f, "tried to read from foreign (extern) static {:?}", did),
ReadForeignStatic(did) => {
write!(f, "tried to read from foreign (extern) static {:?}", did)
}
NoMirFor(did) => write!(f, "could not load MIR for {:?}", did),
ModifiedStatic => write!(
f,
"tried to modify a static's initial value from another static's \
initializer"
),

ReadPointerAsBytes => write!(
f,
"unable to turn this pointer into raw bytes",
),
ReadBytesAsPointer => {
write!(f, "unable to turn these bytes into a pointer")
}
ReadPointerAsBytes => write!(f, "unable to turn this pointer into raw bytes",),
ReadBytesAsPointer => write!(f, "unable to turn these bytes into a pointer"),
}
}
}
Expand Down
29 changes: 22 additions & 7 deletions src/librustc_mir/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
kind: MemoryKind<M::MemoryKinds>,
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
if ptr.offset.bytes() != 0 {
throw_ub_format!("reallocating {:?} which does not point to the beginning of an object", ptr);
throw_ub_format!(
"reallocating {:?} which does not point to the beginning of an object",
ptr
);
}

// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
Expand Down Expand Up @@ -251,7 +254,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
trace!("deallocating: {}", ptr.alloc_id);

if ptr.offset.bytes() != 0 {
throw_ub_format!("deallocating {:?} which does not point to the beginning of an object", ptr);
throw_ub_format!(
"deallocating {:?} which does not point to the beginning of an object",
ptr
);
}

let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
Expand All @@ -260,22 +266,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
// Deallocating static memory -- always an error
return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"),
Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) =>
err_ub_format!("deallocating static memory"),
Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => {
err_ub_format!("deallocating static memory")
}
None => err_ub!(PointerUseAfterFree(ptr.alloc_id)),
}
.into());
}
};

if alloc_kind != kind {
throw_ub_format!("deallocating `{:?}` memory using `{:?}` deallocation operation", alloc_kind, kind);
throw_ub_format!(
"deallocating `{:?}` memory using `{:?}` deallocation operation",
alloc_kind,
kind
);
}
if let Some((size, align)) = old_size_and_align {
if size != alloc.size || align != alloc.align {
throw_ub_format!(
"incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}",
alloc.size.bytes(), alloc.align.bytes(), size.bytes(), align.bytes(),
alloc.size.bytes(),
alloc.align.bytes(),
size.bytes(),
align.bytes(),
)
}
}
Expand Down Expand Up @@ -370,7 +384,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
// It is sufficient to check this for the end pointer. The addition
// checks for overflow.
let end_ptr = ptr.offset(size, self)?;
if end_ptr.offset > allocation_size { // equal is okay!
if end_ptr.offset > allocation_size {
// equal is okay!
throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size })
}
// Test align. Check this last; if both bounds and alignment are violated
Expand Down
20 changes: 9 additions & 11 deletions src/librustc_mir/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,18 +356,16 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
err_ub!(InvalidNullPointerUsage) => {
throw_validation_failure!(format_args!("a NULL {}", kind), self.path)
}
err_ub!(AlignmentCheckFailed { required, has }) => {
throw_validation_failure!(
format_args!(
"an unaligned {} \
err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!(
format_args!(
"an unaligned {} \
(required {} byte alignment but found {})",
kind,
required.bytes(),
has.bytes()
),
self.path
)
}
kind,
required.bytes(),
has.bytes()
),
self.path
),
err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(
format_args!("a dangling {} (created from integer)", kind),
self.path
Expand Down
Loading