Skip to content

Commit

Permalink
improve dangling/oob errors and make them more uniform
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jul 27, 2024
1 parent 5b38b14 commit 316ae6a
Show file tree
Hide file tree
Showing 72 changed files with 196 additions and 156 deletions.
27 changes: 19 additions & 8 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ const_eval_copy_nonoverlapping_overlapping =
`copy_nonoverlapping` called on overlapping ranges
const_eval_dangling_int_pointer =
{$bad_pointer_message}: {$pointer} is a dangling pointer (it has no provenance)
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} which is a dangling pointer (it has no provenance)
const_eval_dangling_null_pointer =
{$bad_pointer_message}: null pointer is a dangling pointer (it has no provenance)
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got a null pointer
const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind}
const_eval_dead_local =
Expand Down Expand Up @@ -87,6 +87,13 @@ const_eval_error = {$error_kind ->
const_eval_exact_div_has_remainder =
exact_div: {$a} cannot be divided by {$b} without remainder
const_eval_expected_inbounds_pointer =
expected {$inbounds_size ->
[0] a pointer to some allocation
[1] a pointer to 1 byte of memory
*[x] a pointer to {$inbounds_size} bytes of memory
}
const_eval_extern_static =
cannot access extern static ({$did})
const_eval_extern_type_field = `extern type` field does not have a known offset
Expand Down Expand Up @@ -265,10 +272,16 @@ const_eval_pointer_arithmetic_overflow =
overflowing in-bounds pointer arithmetic
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
const_eval_pointer_out_of_bounds =
{$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer to {$ptr_size} {$ptr_size ->
[1] byte
*[many] bytes
} starting at offset {$ptr_offset} is out-of-bounds
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
[true] which points to before the beginning of the allocation
*[false] {$alloc_size_minus_ptr_offset ->
[0] which is at or beyond the end of the allocation of size {$alloc_size ->
[1] 1 byte
*[x] {$alloc_size} bytes
}
*[x] and there are only {$alloc_size_minus_ptr_offset} bytes starting at that pointer
}
}
const_eval_pointer_use_after_free =
{$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling
const_eval_ptr_as_bytes_1 =
Expand Down Expand Up @@ -466,5 +479,3 @@ const_eval_write_through_immutable_pointer =
const_eval_write_to_read_only =
writing to {$allocation} which is read-only
const_eval_zst_pointer_out_of_bounds =
{$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer at offset {$ptr_offset} is out-of-bounds
42 changes: 28 additions & 14 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use rustc_errors::{
use rustc_hir::ConstContext;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::mir::interpret::{
CheckInAllocMsg, ExpectedKind, InterpError, InvalidMetaKind, InvalidProgramInfo, Misalignment,
PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
ValidationErrorInfo,
CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpError, InvalidMetaKind,
InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
};
use rustc_middle::ty::{self, Mutability, Ty};
use rustc_span::Span;
Expand Down Expand Up @@ -488,10 +488,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
UnterminatedCString(_) => const_eval_unterminated_c_string,
PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free,
PointerOutOfBounds { ptr_size: Size::ZERO, .. } => const_eval_zst_pointer_out_of_bounds,
PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds,
DanglingIntPointer(0, _) => const_eval_dangling_null_pointer,
DanglingIntPointer(_, _) => const_eval_dangling_int_pointer,
DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer,
DanglingIntPointer { .. } => const_eval_dangling_int_pointer,
AlignmentCheckFailed { .. } => const_eval_alignment_check_failed,
WriteToReadOnly(_) => const_eval_write_to_read_only,
DerefFunctionPointer(_) => const_eval_deref_function_pointer,
Expand Down Expand Up @@ -573,18 +572,33 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
diag.arg("alloc_id", alloc_id)
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
}
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => {
diag.arg("alloc_id", alloc_id)
.arg("alloc_size", alloc_size.bytes())
.arg("ptr_offset", ptr_offset)
.arg("ptr_size", ptr_size.bytes())
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
diag.arg("alloc_size", alloc_size.bytes())
.arg("inbounds_size", inbounds_size.bytes())
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
diag.arg(
"pointer",
Pointer::new(
Some(CtfeProvenance::from(alloc_id)),
Size::from_bytes(ptr_offset as u64),
)
.to_string(),
);
diag.arg("ptr_offset_is_neg", ptr_offset < 0);
diag.arg(
"alloc_size_minus_ptr_offset",
alloc_size.bytes().saturating_sub(ptr_offset as u64),
);
}
DanglingIntPointer(ptr, msg) => {
if ptr != 0 {
diag.arg("pointer", format!("{ptr:#x}[noalloc]"));
DanglingIntPointer { addr, inbounds_size, msg } => {
if addr != 0 {
diag.arg(
"pointer",
Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
);
}

diag.arg("inbounds_size", inbounds_size.bytes());
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
}
AlignmentCheckFailed(Misalignment { required, has }, msg) => {
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
Ok(match self.ptr_try_get_alloc_id(ptr) {
Err(addr) => {
// We couldn't get a proper allocation.
throw_ub!(DanglingIntPointer(addr, msg));
throw_ub!(DanglingIntPointer { addr, inbounds_size: size, msg });
}
Ok((alloc_id, offset, prov)) => {
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
Expand All @@ -470,7 +470,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
alloc_id,
alloc_size,
ptr_offset: self.target_usize_to_isize(offset.bytes()),
ptr_size: size,
inbounds_size: size,
msg,
})
}
Expand Down Expand Up @@ -1443,7 +1443,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ptr: Pointer<Option<M::Provenance>>,
) -> InterpResult<'tcx, (AllocId, Size, M::ProvenanceExtra)> {
self.ptr_try_get_alloc_id(ptr).map_err(|offset| {
err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into()
err_ub!(DanglingIntPointer {
addr: offset,
// We don't know the actually required size.
inbounds_size: Size::ZERO,
msg: CheckInAllocMsg::InboundsTest
})
.into()
})
}
}
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
try_validation!(
self.ecx.get_ptr_vtable_ty(vtable, Some(data)),
self.path,
Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
Ub(DanglingIntPointer{ .. } | InvalidVTablePointer(..)) =>
InvalidVTablePtr { value: format!("{vtable}") },
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
Expand Down Expand Up @@ -405,8 +405,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
),
self.path,
Ub(DanglingIntPointer(0, _)) => NullPtr { ptr_kind },
Ub(DanglingIntPointer(i, _)) => DanglingPtrNoProvenance {
Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind },
Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
ptr_kind,
// FIXME this says "null pointer" when null but we need translate
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(*i))
Expand Down Expand Up @@ -605,7 +605,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
let _fn = try_validation!(
self.ecx.get_ptr_fn(ptr),
self.path,
Ub(DanglingIntPointer(..) | InvalidFunctionPointer(..)) =>
Ub(DanglingIntPointer{ .. } | InvalidFunctionPointer(..)) =>
InvalidFnPtr { value: format!("{ptr}") },
);
// FIXME: Check if the signature matches
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,16 +329,21 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// Using a pointer after it got freed.
PointerUseAfterFree(AllocId, CheckInAllocMsg),
/// Used a pointer outside the bounds it is valid for.
/// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
PointerOutOfBounds {
alloc_id: AllocId,
alloc_size: Size,
ptr_offset: i64,
ptr_size: Size,
/// The size of the memory range that was expected to be in-bounds.
inbounds_size: Size,
msg: CheckInAllocMsg,
},
/// Using an integer as a pointer in the wrong way.
DanglingIntPointer(u64, CheckInAllocMsg),
DanglingIntPointer {
addr: u64,
/// The size of the memory range that was expected to be in-bounds (or 0 if we don't know).
inbounds_size: Size,
msg: CheckInAllocMsg,
},
/// Used a pointer with bad alignment.
AlignmentCheckFailed(Misalignment, CheckAlignMsg),
/// Writing to read-only memory.
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,12 @@ impl Provenance for CtfeProvenance {
fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Print AllocId.
fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag
// Print offset only if it is non-zero.
if ptr.offset.bytes() > 0 {
write!(f, "+{:#x}", ptr.offset.bytes())?;
// Print offset only if it is non-zero. Print it signed.
let signed_offset = ptr.offset.bytes() as i64;
if signed_offset > 0 {
write!(f, "+{:#x}", signed_offset)?;
} else if signed_offset < 0 {
write!(f, "-{:#x}", signed_offset.unsigned_abs())?;
}
// Print immutable status.
if ptr.provenance.immutable() {
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail-dep/libc/affinity.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: memory access failed: ALLOC has size 128, so pointer to 129 bytes starting at offset 0 is out-of-bounds
error: Undefined Behavior: memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC and there are only 128 bytes starting at that pointer
--> $DIR/affinity.rs:LL:CC
|
LL | let err = unsafe { sched_setaffinity(PID, size_of::<cpu_set_t>() + 1, &cpuset) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 128, so pointer to 129 bytes starting at offset 0 is out-of-bounds
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC and there are only 128 bytes starting at that pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail-dep/libc/memchr_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ use std::ptr;
// null is explicitly called out as UB in the C docs.
fn main() {
unsafe {
libc::memchr(ptr::null(), 0, 0); //~ERROR: dangling
libc::memchr(ptr::null(), 0, 0); //~ERROR: null pointer
}
}
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/memchr_null.rs:LL:CC
|
LL | libc::memchr(ptr::null(), 0, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ use std::ptr;
// null is explicitly called out as UB in the C docs.
fn main() {
unsafe {
libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: dangling
libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: null pointer
}
}
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/memcmp_null.rs:LL:CC
|
LL | libc::memcmp(ptr::null(), ptr::null(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/memcmp_zero.rs:LL:CC
|
LL | libc::memcmp(ptr.cast(), ptr.cast(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x17[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/memcpy_zero.rs:LL:CC
|
LL | libc::memcpy(to.cast(), from.cast(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x17[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ use std::ptr;
// null is explicitly called out as UB in the C docs.
fn main() {
unsafe {
libc::memrchr(ptr::null(), 0, 0); //~ERROR: dangling
libc::memrchr(ptr::null(), 0, 0); //~ERROR: null pointer
}
}
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/memrchr_null.rs:LL:CC
|
LL | libc::memrchr(ptr::null(), 0, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
//@error-in-other-file: pointer to 4 bytes starting at offset 0 is out-of-bounds
//@error-in-other-file: expected a pointer to 4 bytes of memory

fn main() {
unsafe {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
Loading

0 comments on commit 316ae6a

Please sign in to comment.