Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c796ef0

Browse files
authoredMay 2, 2025
Rollup merge of #140521 - RalfJung:oob-error, r=saethlin
interpret: better error message for out-of-bounds pointer arithmetic and accesses Fixes #93881 r? `@saethlin`
2 parents 296733d + 00f25a8 commit c796ef0

File tree

81 files changed

+202
-213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+202
-213
lines changed
 

‎compiler/rustc_const_eval/messages.ftl

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@ const_eval_already_reported =
1212
const_eval_assume_false =
1313
`assume` called with `false`
1414
15+
const_eval_bad_pointer_op = {$operation ->
16+
[MemoryAccess] memory access failed
17+
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
18+
*[Dereferenceable] pointer not dereferenceable
19+
}
20+
const_eval_bad_pointer_op_attempting = {const_eval_bad_pointer_op}: {$operation ->
21+
[MemoryAccess] attempting to access {$inbounds_size ->
22+
[1] 1 byte
23+
*[x] {$inbounds_size} bytes
24+
}
25+
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
26+
[1] 1 byte
27+
*[x] {$inbounds_size} bytes
28+
}
29+
*[Dereferenceable] pointer must {$inbounds_size ->
30+
[0] point to some allocation
31+
[1] be dereferenceable for 1 byte
32+
*[x] be dereferenceable for {$inbounds_size} bytes
33+
}
34+
}
35+
1536
const_eval_bounds_check_failed =
1637
indexing out of bounds: the len is {$len} but the index is {$index}
1738
const_eval_call_nonzero_intrinsic =
@@ -39,9 +60,9 @@ const_eval_copy_nonoverlapping_overlapping =
3960
`copy_nonoverlapping` called on overlapping ranges
4061
4162
const_eval_dangling_int_pointer =
42-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} which is a dangling pointer (it has no provenance)
63+
{const_eval_bad_pointer_op_attempting}, but got {$pointer} which is a dangling pointer (it has no provenance)
4364
const_eval_dangling_null_pointer =
44-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got a null pointer
65+
{const_eval_bad_pointer_op_attempting}, but got null pointer
4566
4667
const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind}
4768
const_eval_dead_local =
@@ -77,21 +98,6 @@ const_eval_error = {$error_kind ->
7798
const_eval_exact_div_has_remainder =
7899
exact_div: {$a} cannot be divided by {$b} without remainder
79100
80-
const_eval_expected_inbounds_pointer =
81-
expected a pointer to {$inbounds_size_abs ->
82-
[0] some allocation
83-
*[x] {$inbounds_size_is_neg ->
84-
[false] {$inbounds_size_abs ->
85-
[1] 1 byte of memory
86-
*[x] {$inbounds_size_abs} bytes of memory
87-
}
88-
*[true] the end of {$inbounds_size_abs ->
89-
[1] 1 byte of memory
90-
*[x] {$inbounds_size_abs} bytes of memory
91-
}
92-
}
93-
}
94-
95101
const_eval_extern_static =
96102
cannot access extern static `{$did}`
97103
const_eval_extern_type_field = `extern type` field does not have a known offset
@@ -111,7 +117,6 @@ const_eval_frame_note_inner = inside {$where_ ->
111117
112118
const_eval_frame_note_last = the failure occurred here
113119
114-
const_eval_in_bounds_test = out-of-bounds pointer use
115120
const_eval_incompatible_calling_conventions =
116121
calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
117122
@@ -206,7 +211,6 @@ const_eval_long_running =
206211
207212
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
208213
209-
const_eval_memory_access_test = memory access failed
210214
const_eval_memory_exhausted =
211215
tried to allocate more memory than available to compiler
212216
@@ -287,8 +291,6 @@ const_eval_offset_from_out_of_bounds =
287291
`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation
288292
const_eval_offset_from_overflow =
289293
`{$name}` called when first pointer is too far ahead of second
290-
const_eval_offset_from_test =
291-
out-of-bounds `offset_from` origin
292294
const_eval_offset_from_underflow =
293295
`{$name}` called when first pointer is too far before second
294296
const_eval_offset_from_unsigned_overflow =
@@ -312,27 +314,25 @@ const_eval_partial_pointer_overwrite =
312314
unable to overwrite parts of a pointer in memory at {$ptr}
313315
const_eval_pointer_arithmetic_overflow =
314316
overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
315-
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
317+
316318
const_eval_pointer_out_of_bounds =
317-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
318-
[true] which points to before the beginning of the allocation
319-
*[false] {$inbounds_size_is_neg ->
320-
[true] {$ptr_offset_abs ->
321-
[0] which is at the beginning of the allocation
322-
*[other] which does not have enough space to the beginning of the allocation
323-
}
324-
*[false] {$alloc_size_minus_ptr_offset ->
325-
[0] which is at or beyond the end of the allocation of size {$alloc_size ->
319+
{const_eval_bad_pointer_op_attempting}, but got {$pointer} which {$inbounds_size_is_neg ->
320+
[false] {$alloc_size_minus_ptr_offset ->
321+
[0] is at or beyond the end of the allocation of size {$alloc_size ->
326322
[1] 1 byte
327323
*[x] {$alloc_size} bytes
328324
}
329-
[1] which is only 1 byte from the end of the allocation
330-
*[x] which is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
325+
[1] is only 1 byte from the end of the allocation
326+
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
327+
}
328+
*[true] {$ptr_offset_abs ->
329+
[0] is at the beginning of the allocation
330+
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
331331
}
332-
}
333332
}
333+
334334
const_eval_pointer_use_after_free =
335-
{$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling
335+
{const_eval_bad_pointer_op}: {$alloc_id} has been freed, so this pointer is dangling
336336
const_eval_ptr_as_bytes_1 =
337337
this code performed an operation that depends on the underlying bytes representing a pointer
338338
const_eval_ptr_as_bytes_2 =

‎compiler/rustc_const_eval/src/errors.rs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ use either::Either;
55
use rustc_abi::WrappingRange;
66
use rustc_errors::codes::*;
77
use rustc_errors::{
8-
Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
9-
MultiSpan, Subdiagnostic,
8+
Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, Subdiagnostic,
109
};
1110
use rustc_hir::ConstContext;
1211
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
1312
use rustc_middle::mir::interpret::{
14-
CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind,
15-
InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
16-
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
13+
CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind, InvalidProgramInfo,
14+
Misalignment, Pointer, PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo,
15+
UnsupportedOpInfo, ValidationErrorInfo,
1716
};
1817
use rustc_middle::ty::{self, Mutability, Ty};
1918
use rustc_span::{Span, Symbol};
@@ -498,19 +497,6 @@ pub trait ReportErrorExt {
498497
}
499498
}
500499

501-
fn bad_pointer_message(msg: CheckInAllocMsg, dcx: DiagCtxtHandle<'_>) -> String {
502-
use crate::fluent_generated::*;
503-
504-
let msg = match msg {
505-
CheckInAllocMsg::MemoryAccessTest => const_eval_memory_access_test,
506-
CheckInAllocMsg::PointerArithmeticTest => const_eval_pointer_arithmetic_test,
507-
CheckInAllocMsg::OffsetFromTest => const_eval_offset_from_test,
508-
CheckInAllocMsg::InboundsTest => const_eval_in_bounds_test,
509-
};
510-
511-
dcx.eagerly_translate_to_string(msg, [].into_iter())
512-
}
513-
514500
impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
515501
fn diagnostic_message(&self) -> DiagMessage {
516502
use UndefinedBehaviorInfo::*;
@@ -564,7 +550,6 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
564550

565551
fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
566552
use UndefinedBehaviorInfo::*;
567-
let dcx = diag.dcx;
568553
match self {
569554
Ub(_) => {}
570555
Custom(custom) => {
@@ -612,12 +597,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
612597
diag.arg("vtable_dyn_type", vtable_dyn_type.to_string());
613598
}
614599
PointerUseAfterFree(alloc_id, msg) => {
615-
diag.arg("alloc_id", alloc_id)
616-
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
600+
diag.arg("alloc_id", alloc_id).arg("operation", format!("{:?}", msg));
617601
}
618602
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
619603
diag.arg("alloc_size", alloc_size.bytes());
620-
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
621604
diag.arg("pointer", {
622605
let mut out = format!("{:?}", alloc_id);
623606
if ptr_offset > 0 {
@@ -627,14 +610,17 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
627610
}
628611
out
629612
});
613+
diag.arg("inbounds_size", inbounds_size);
630614
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
631615
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
616+
diag.arg("ptr_offset", ptr_offset);
632617
diag.arg("ptr_offset_is_neg", ptr_offset < 0);
633618
diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs());
634619
diag.arg(
635620
"alloc_size_minus_ptr_offset",
636621
alloc_size.bytes().saturating_sub(ptr_offset as u64),
637622
);
623+
diag.arg("operation", format!("{:?}", msg));
638624
}
639625
DanglingIntPointer { addr, inbounds_size, msg } => {
640626
if addr != 0 {
@@ -644,9 +630,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
644630
);
645631
}
646632

633+
diag.arg("inbounds_size", inbounds_size);
647634
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
648635
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
649-
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
636+
diag.arg("operation", format!("{:?}", msg));
650637
}
651638
AlignmentCheckFailed(Misalignment { required, has }, msg) => {
652639
diag.arg("required", required.bytes());

0 commit comments

Comments
 (0)
Please sign in to comment.