diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 48b26cfd83cd..9474f05b55df 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -41,6 +41,7 @@ pub struct Allocation { /// The size of the allocation. Currently, must always equal `bytes.len()`. pub size: Size, /// The alignment of the allocation to detect unaligned reads. + /// (`Align` guarantees that this is a power of two.) pub align: Align, /// `true` if the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f4fe0bc3d3f0..55112c23ef42 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -342,8 +342,6 @@ pub enum UndefinedBehaviorInfo { UnterminatedCString(Pointer), /// Dereferencing a dangling pointer after it got freed. PointerUseAfterFree(AllocId), - /// Using a NULL pointer in the wrong way. - InvalidNullPointerUsage, /// Used a pointer outside the bounds it is valid for. PointerOutOfBounds { ptr: Pointer, @@ -355,6 +353,8 @@ pub enum UndefinedBehaviorInfo { required: Align, has: Align, }, + /// Using an integer as a pointer in the wrong way. + InvalidIntPointerUsage(u64), /// Writing to read-only memory. WriteToReadOnly(AllocId), /// Using a pointer-not-to-a-function as function pointer. @@ -401,7 +401,6 @@ impl fmt::Debug for UndefinedBehaviorInfo { 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 {}, \ @@ -411,6 +410,8 @@ impl fmt::Debug for UndefinedBehaviorInfo { ptr.alloc_id, allocation_size.bytes() ), + InvalidIntPointerUsage(0) => write!(f, "invalid use of NULL pointer"), + InvalidIntPointerUsage(i) => write!(f, "invalid use of {} as a pointer", i), AlignmentCheckFailed { required, has } => write!( f, "accessing memory with alignment {}, but alignment {} is required", @@ -450,24 +451,18 @@ impl fmt::Debug for UndefinedBehaviorInfo { pub enum UnsupportedOpInfo { /// Free-form case. Only for errors that are never caught! Unsupported(String), - /// When const-prop encounters a situation it does not support, it raises this error. /// This must not allocate for performance reasons (hence `str`, not `String`). ConstPropUnsupported(&'static str), - /// Accessing an unsupported foreign static. ReadForeignStatic(DefId), - /// Could not find MIR for a function. NoMirFor(DefId), - /// Modified a static during const-eval. /// FIXME: move this to `ConstEvalErrKind` through a machine hook. ModifiedStatic, - /// Encountered a pointer where we needed raw bytes. ReadPointerAsBytes, - /// Encountered raw bytes where we needed a pointer. ReadBytesAsPointer, } diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index d86ea026ad0d..b1210a47fd93 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -281,8 +281,10 @@ pub trait Machine<'mir, 'tcx>: Sized { int: u64, ) -> InterpResult<'tcx, Pointer> { Err((if int == 0 { - err_ub!(InvalidNullPointerUsage) + // This is UB, seriously. + err_ub!(InvalidIntPointerUsage(0)) } else { + // This is just something we cannot support during const-eval. err_unsup!(ReadBytesAsPointer) }) .into()) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 0244a75e8d95..7099c42ce7ac 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -369,7 +369,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { assert!(size.bytes() == 0); // Must be non-NULL. if bits == 0 { - throw_ub!(InvalidNullPointerUsage) + throw_ub!(InvalidIntPointerUsage(0)) } // Must be aligned. if let Some(align) = align { diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 51a557851fce..6fc7355fab38 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -171,7 +171,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(()); } let caller_arg = caller_arg.next().ok_or_else(|| { - err_ub_format!("calling a function passing fewer arguments than it requires") + err_ub_format!("calling a function with fewer arguments than it requires") })?; if rust_abi { assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); @@ -341,7 +341,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Now we should have no more caller args if caller_iter.next().is_some() { throw_ub_format!( - "calling a function passing more arguments than it expected" + "calling a function with more arguments than it expected" ) } // Don't forget to check the return type! diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 96f44256ff96..620e4391ad6e 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -353,13 +353,16 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M place.ptr, size, align ); match err.kind { - err_ub!(InvalidNullPointerUsage) => { + err_ub!(InvalidIntPointerUsage(0)) => { throw_validation_failure!(format_args!("a NULL {}", kind), self.path) } + err_ub!(InvalidIntPointerUsage(i)) => throw_validation_failure!( + format_args!("a {} to unallocated address {}", kind, i), + self.path + ), err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!( format_args!( - "an unaligned {} \ - (required {} byte alignment but found {})", + "an unaligned {} (required {} byte alignment but found {})", kind, required.bytes(), has.bytes() @@ -370,12 +373,17 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M format_args!("a dangling {} (created from integer)", kind), self.path ), - err_ub!(PointerOutOfBounds { .. }) | err_ub!(PointerUseAfterFree(_)) => { - throw_validation_failure!( - format_args!("a dangling {} (not entirely in bounds)", kind), - self.path - ) - } + err_ub!(PointerOutOfBounds { .. }) => throw_validation_failure!( + format_args!( + "a dangling {} (going beyond the bounds of its allocation)", + kind + ), + self.path + ), + err_ub!(PointerUseAfterFree(_)) => throw_validation_failure!( + format_args!("a dangling {} (use-after-free)", kind), + self.path + ), _ => bug!("Unexpected error during ptr inbounds test: {}", err), } } diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index cf51b8765fc6..80e60dbb58a5 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:32:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -70,7 +70,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:62:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:68:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr index 7222f87da248..90c8e95e8ebd 100644 --- a/src/test/ui/error-codes/E0396-fixed.stderr +++ b/src/test/ui/error-codes/E0396-fixed.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const VALUE: u8 = unsafe { *REG_ADDR }; | ---------------------------^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn these bytes into a pointer | = note: `#[deny(const_err)]` on by default