Skip to content

Commit fd61d06

Browse files
committed
Auto merge of #71704 - RalfJung:miri-error-print, r=oli-obk
Miri: tweak error print I started by adjusting the "invalid use of int as pointer" message (it wasn't really clear what is invalid about the use). But then I realized that these are all `Debug` impls we use for these errors, for some reason, so I fixed that to use `Display` instead. ~~This includes #71590 (to get the `Display` impl for `Pointer`), so the diff will look better once that finally lands. Here's the [relative diff](RalfJung/rust@e72ebf5...RalfJung:miri-error-print).~~ r? @oli-obk
2 parents bd0bacc + cce0cb3 commit fd61d06

File tree

10 files changed

+87
-82
lines changed

10 files changed

+87
-82
lines changed

src/librustc_middle/mir/interpret/error.rs

+71-40
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{AllocId, CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
1+
use super::{AllocId, Pointer, RawConst, ScalarMaybeUndef};
22

33
use crate::mir::interpret::ConstValue;
44
use crate::ty::layout::LayoutError;
@@ -285,7 +285,7 @@ pub enum InvalidProgramInfo<'tcx> {
285285
TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
286286
}
287287

288-
impl fmt::Debug for InvalidProgramInfo<'_> {
288+
impl fmt::Display for InvalidProgramInfo<'_> {
289289
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290290
use InvalidProgramInfo::*;
291291
match self {
@@ -304,14 +304,38 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
304304
}
305305
}
306306

307+
/// Details of why a pointer had to be in-bounds.
308+
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
309+
pub enum CheckInAllocMsg {
310+
MemoryAccessTest,
311+
NullPointerTest,
312+
PointerArithmeticTest,
313+
InboundsTest,
314+
}
315+
316+
impl fmt::Display for CheckInAllocMsg {
317+
/// When this is printed as an error the context looks like this
318+
/// "{test name} failed: pointer must be in-bounds at offset..."
319+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320+
write!(
321+
f,
322+
"{}",
323+
match *self {
324+
CheckInAllocMsg::MemoryAccessTest => "memory access",
325+
CheckInAllocMsg::NullPointerTest => "NULL pointer test",
326+
CheckInAllocMsg::PointerArithmeticTest => "pointer arithmetic",
327+
CheckInAllocMsg::InboundsTest => "inbounds test",
328+
}
329+
)
330+
}
331+
}
332+
307333
/// Error information for when the program caused Undefined Behavior.
308334
pub enum UndefinedBehaviorInfo {
309335
/// Free-form case. Only for errors that are never caught!
310336
Ub(String),
311337
/// Unreachable code was executed.
312338
Unreachable,
313-
/// An enum discriminant was set to a value which was outside the range of valid values.
314-
InvalidDiscriminant(ScalarMaybeUndef),
315339
/// A slice/array index projection went out-of-bounds.
316340
BoundsCheckFailed {
317341
len: u64,
@@ -335,17 +359,15 @@ pub enum UndefinedBehaviorInfo {
335359
msg: CheckInAllocMsg,
336360
allocation_size: Size,
337361
},
362+
/// Using an integer as a pointer in the wrong way.
363+
DanglingIntPointer(u64, CheckInAllocMsg),
338364
/// Used a pointer with bad alignment.
339365
AlignmentCheckFailed {
340366
required: Align,
341367
has: Align,
342368
},
343-
/// Using an integer as a pointer in the wrong way.
344-
InvalidIntPointerUsage(u64),
345369
/// Writing to read-only memory.
346370
WriteToReadOnly(AllocId),
347-
/// Using a pointer-not-to-a-function as function pointer.
348-
InvalidFunctionPointer(Pointer),
349371
// Trying to access the data behind a function pointer.
350372
DerefFunctionPointer(AllocId),
351373
/// The value validity check found a problem.
@@ -356,6 +378,10 @@ pub enum UndefinedBehaviorInfo {
356378
InvalidBool(u8),
357379
/// Using a non-character `u32` as character.
358380
InvalidChar(u32),
381+
/// An enum discriminant was set to a value which was outside the range of valid values.
382+
InvalidDiscriminant(ScalarMaybeUndef),
383+
/// Using a pointer-not-to-a-function as function pointer.
384+
InvalidFunctionPointer(Pointer),
359385
/// Using uninitialized data where it is not allowed.
360386
InvalidUndefBytes(Option<Pointer>),
361387
/// Working with a local that is not currently live.
@@ -367,29 +393,26 @@ pub enum UndefinedBehaviorInfo {
367393
},
368394
}
369395

370-
impl fmt::Debug for UndefinedBehaviorInfo {
396+
impl fmt::Display for UndefinedBehaviorInfo {
371397
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372398
use UndefinedBehaviorInfo::*;
373399
match self {
374400
Ub(msg) => write!(f, "{}", msg),
375401
Unreachable => write!(f, "entering unreachable code"),
376-
InvalidDiscriminant(val) => write!(f, "encountering invalid enum discriminant {}", val),
377-
BoundsCheckFailed { ref len, ref index } => write!(
378-
f,
379-
"indexing out of bounds: the len is {:?} but the index is {:?}",
380-
len, index
381-
),
402+
BoundsCheckFailed { ref len, ref index } => {
403+
write!(f, "indexing out of bounds: the len is {} but the index is {}", len, index)
404+
}
382405
DivisionByZero => write!(f, "dividing by zero"),
383406
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
384407
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
385408
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
386409
UnterminatedCString(p) => write!(
387410
f,
388-
"reading a null-terminated string starting at {:?} with no null found before end of allocation",
411+
"reading a null-terminated string starting at {} with no null found before end of allocation",
389412
p,
390413
),
391414
PointerUseAfterFree(a) => {
392-
write!(f, "pointer to {:?} was dereferenced after this allocation got freed", a)
415+
write!(f, "pointer to {} was dereferenced after this allocation got freed", a)
393416
}
394417
PointerOutOfBounds { ptr, msg, allocation_size } => write!(
395418
f,
@@ -400,25 +423,34 @@ impl fmt::Debug for UndefinedBehaviorInfo {
400423
ptr.alloc_id,
401424
allocation_size.bytes()
402425
),
403-
InvalidIntPointerUsage(0) => write!(f, "invalid use of NULL pointer"),
404-
InvalidIntPointerUsage(i) => write!(f, "invalid use of {} as a pointer", i),
426+
DanglingIntPointer(_, CheckInAllocMsg::NullPointerTest) => {
427+
write!(f, "NULL pointer is not allowed for this operation")
428+
}
429+
DanglingIntPointer(i, msg) => {
430+
write!(f, "{} failed: 0x{:x} is not a valid pointer", msg, i)
431+
}
405432
AlignmentCheckFailed { required, has } => write!(
406433
f,
407434
"accessing memory with alignment {}, but alignment {} is required",
408435
has.bytes(),
409436
required.bytes()
410437
),
411-
WriteToReadOnly(a) => write!(f, "writing to {:?} which is read-only", a),
438+
WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a),
439+
DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a),
440+
ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
441+
InvalidBool(b) => {
442+
write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:2x}", b)
443+
}
444+
InvalidChar(c) => {
445+
write!(f, "interpreting an invalid 32-bit value as a char: 0x{:8x}", c)
446+
}
447+
InvalidDiscriminant(val) => write!(f, "enum value has invalid discriminant: {}", val),
412448
InvalidFunctionPointer(p) => {
413-
write!(f, "using {:?} as function pointer but it does not point to a function", p)
449+
write!(f, "using {} as function pointer but it does not point to a function", p)
414450
}
415-
DerefFunctionPointer(a) => write!(f, "accessing {:?} which contains a function", a),
416-
ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
417-
InvalidBool(b) => write!(f, "interpreting an invalid 8-bit value as a bool: {}", b),
418-
InvalidChar(c) => write!(f, "interpreting an invalid 32-bit value as a char: {}", c),
419451
InvalidUndefBytes(Some(p)) => write!(
420452
f,
421-
"reading uninitialized memory at {:?}, but this operation requires initialized memory",
453+
"reading uninitialized memory at {}, but this operation requires initialized memory",
422454
p
423455
),
424456
InvalidUndefBytes(None) => write!(
@@ -455,7 +487,7 @@ pub enum UnsupportedOpInfo {
455487
ReadBytesAsPointer,
456488
}
457489

458-
impl fmt::Debug for UnsupportedOpInfo {
490+
impl fmt::Display for UnsupportedOpInfo {
459491
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
460492
use UnsupportedOpInfo::*;
461493
match self {
@@ -481,7 +513,7 @@ pub enum ResourceExhaustionInfo {
481513
StepLimitReached,
482514
}
483515

484-
impl fmt::Debug for ResourceExhaustionInfo {
516+
impl fmt::Display for ResourceExhaustionInfo {
485517
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486518
use ResourceExhaustionInfo::*;
487519
match self {
@@ -499,7 +531,6 @@ impl fmt::Debug for ResourceExhaustionInfo {
499531
pub trait AsAny: Any {
500532
fn as_any(&self) -> &dyn Any;
501533
}
502-
503534
impl<T: Any> AsAny for T {
504535
#[inline(always)]
505536
fn as_any(&self) -> &dyn Any {
@@ -508,7 +539,7 @@ impl<T: Any> AsAny for T {
508539
}
509540

510541
/// A trait for machine-specific errors (or other "machine stop" conditions).
511-
pub trait MachineStopType: AsAny + fmt::Debug + Send {}
542+
pub trait MachineStopType: AsAny + fmt::Display + Send {}
512543
impl MachineStopType for String {}
513544

514545
impl dyn MachineStopType {
@@ -538,21 +569,21 @@ pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
538569

539570
impl fmt::Display for InterpError<'_> {
540571
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541-
// Forward `Display` to `Debug`.
542-
fmt::Debug::fmt(self, f)
572+
use InterpError::*;
573+
match *self {
574+
Unsupported(ref msg) => write!(f, "{}", msg),
575+
InvalidProgram(ref msg) => write!(f, "{}", msg),
576+
UndefinedBehavior(ref msg) => write!(f, "{}", msg),
577+
ResourceExhaustion(ref msg) => write!(f, "{}", msg),
578+
MachineStop(ref msg) => write!(f, "{}", msg),
579+
}
543580
}
544581
}
545582

583+
// Forward `Debug` to `Display`, so it does not look awful.
546584
impl fmt::Debug for InterpError<'_> {
547585
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548-
use InterpError::*;
549-
match *self {
550-
Unsupported(ref msg) => write!(f, "{:?}", msg),
551-
InvalidProgram(ref msg) => write!(f, "{:?}", msg),
552-
UndefinedBehavior(ref msg) => write!(f, "{:?}", msg),
553-
ResourceExhaustion(ref msg) => write!(f, "{:?}", msg),
554-
MachineStop(ref msg) => write!(f, "{:?}", msg),
555-
}
586+
fmt::Display::fmt(self, f)
556587
}
557588
}
558589

src/librustc_middle/mir/interpret/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,16 @@ use crate::ty::subst::GenericArgKind;
117117
use crate::ty::{self, Instance, Ty, TyCtxt};
118118

119119
pub use self::error::{
120-
struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo,
121-
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
120+
struct_error, CheckInAllocMsg, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
121+
FrameInfo, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
122122
ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
123123
};
124124

125125
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef};
126126

127127
pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask};
128128

129-
pub use self::pointer::{CheckInAllocMsg, Pointer, PointerArithmetic};
129+
pub use self::pointer::{Pointer, PointerArithmetic};
130130

131131
/// Uniquely identifies one of the following:
132132
/// - A constant

src/librustc_middle/mir/interpret/pointer.rs

+1-27
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,7 @@ use rustc_macros::HashStable;
44
use rustc_target::abi::{HasDataLayout, Size};
55

66
use std::convert::TryFrom;
7-
use std::fmt::{self, Display};
8-
9-
/// Used by `check_in_alloc` to indicate context of check
10-
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
11-
pub enum CheckInAllocMsg {
12-
MemoryAccessTest,
13-
NullPointerTest,
14-
PointerArithmeticTest,
15-
InboundsTest,
16-
}
17-
18-
impl Display for CheckInAllocMsg {
19-
/// When this is printed as an error the context looks like this
20-
/// "{test name} failed: pointer must be in-bounds at offset..."
21-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22-
write!(
23-
f,
24-
"{}",
25-
match *self {
26-
CheckInAllocMsg::MemoryAccessTest => "Memory access",
27-
CheckInAllocMsg::NullPointerTest => "Null pointer test",
28-
CheckInAllocMsg::PointerArithmeticTest => "Pointer arithmetic",
29-
CheckInAllocMsg::InboundsTest => "Inbounds test",
30-
}
31-
)
32-
}
33-
}
7+
use std::fmt;
348

359
////////////////////////////////////////////////////////////////////////////////
3610
// Pointer arithmetic

src/librustc_mir/interpret/machine.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_middle::ty::{self, Ty};
1010
use rustc_span::def_id::DefId;
1111

1212
use super::{
13-
AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
14-
OpTy, Operand, PlaceTy, Pointer, Scalar,
13+
AllocId, Allocation, AllocationExtra, CheckInAllocMsg, Frame, ImmTy, InterpCx, InterpResult,
14+
Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar,
1515
};
1616

1717
/// Data returned by Machine::stack_pop,
@@ -346,7 +346,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
346346
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
347347
Err((if int == 0 {
348348
// This is UB, seriously.
349-
err_ub!(InvalidIntPointerUsage(0))
349+
err_ub!(DanglingIntPointer(0, CheckInAllocMsg::InboundsTest))
350350
} else {
351351
// This is just something we cannot support during const-eval.
352352
err_unsup!(ReadBytesAsPointer)

src/librustc_mir/interpret/memory.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
365365
assert!(size.bytes() == 0);
366366
// Must be non-NULL.
367367
if bits == 0 {
368-
throw_ub!(InvalidIntPointerUsage(0))
368+
throw_ub!(DanglingIntPointer(0, msg))
369369
}
370370
// Must be aligned.
371371
if let Some(align) = align {

src/librustc_mir/interpret/validity.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
360360
place.ptr, size, align
361361
);
362362
match err.kind {
363-
err_ub!(InvalidIntPointerUsage(0)) => {
363+
err_ub!(DanglingIntPointer(0, _)) => {
364364
throw_validation_failure!(format_args!("a NULL {}", kind), self.path)
365365
}
366-
err_ub!(InvalidIntPointerUsage(i)) => throw_validation_failure!(
366+
err_ub!(DanglingIntPointer(i, _)) => throw_validation_failure!(
367367
format_args!("a {} to unallocated address {}", kind, i),
368368
self.path
369369
),

src/librustc_mir/transform/const_prop.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ macro_rules! throw_machine_stop_str {
4343
// We make a new local type for it. The type itself does not carry any information,
4444
// but its vtable (for the `MachineStopType` trait) does.
4545
struct Zst;
46-
// Debug-printing this type shows the desired string.
47-
impl std::fmt::Debug for Zst {
46+
// Printing this type shows the desired string.
47+
impl std::fmt::Display for Zst {
4848
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4949
write!(f, $($tt)*)
5050
}

src/test/ui/consts/const-eval/ub-nonnull.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
1313
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
1414
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
1515
LL | | let out_of_bounds_ptr = &ptr[255];
16-
| | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc11 which has size 1
16+
| | ^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc11 which has size 1
1717
LL | | mem::transmute(out_of_bounds_ptr)
1818
LL | | } };
1919
| |____-

src/test/ui/consts/const-eval/ub-wide-ptr.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,13 @@ error[E0080]: could not evaluate static initializer
186186
--> $DIR/ub-wide-ptr.rs:121:5
187187
|
188188
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
189-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
189+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inbounds test failed: 0x0 is not a valid pointer
190190

191191
error[E0080]: could not evaluate static initializer
192192
--> $DIR/ub-wide-ptr.rs:125:5
193193
|
194194
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
195-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
195+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
196196

197197
error: aborting due to 24 previous errors
198198

src/test/ui/consts/offset_from_ub.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ error: any use of this value will cause an error
6666
LL | intrinsics::ptr_offset_from(self, origin)
6767
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6868
| |
69-
| invalid use of NULL pointer
69+
| inbounds test failed: 0x0 is not a valid pointer
7070
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
7171
| inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:37:14
7272
|

0 commit comments

Comments
 (0)