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 f9191d1

Browse files
committedApr 30, 2025·
interpret: better error message for out-of-bounds pointer arithmetic and accesses
1 parent 427288b commit f9191d1

File tree

92 files changed

+216
-230
lines changed

Some content is hidden

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

92 files changed

+216
-230
lines changed
 

‎compiler/rustc_const_eval/messages.ftl

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@ 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+
} at {$pointer}
25+
[InboundsPointerArithmetic] attempting to offset pointer to {$pointer} by {$inbounds_size ->
26+
[1] 1 byte
27+
*[x] {$inbounds_size} bytes
28+
}
29+
*[Dereferenceable] pointer to {$pointer} must be dereferenceable for {$inbounds_size ->
30+
[1] 1 byte
31+
*[x] {$inbounds_size} bytes
32+
}
33+
}
34+
1535
const_eval_bounds_check_failed =
1636
indexing out of bounds: the len is {$len} but the index is {$index}
1737
const_eval_call_nonzero_intrinsic =
@@ -39,9 +59,9 @@ const_eval_copy_nonoverlapping_overlapping =
3959
`copy_nonoverlapping` called on overlapping ranges
4060
4161
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)
62+
{const_eval_bad_pointer_op_attempting}, but got a dangling pointer (it has no provenance)
4363
const_eval_dangling_null_pointer =
44-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got a null pointer
64+
{const_eval_bad_pointer_op_attempting}, but got null pointer
4565
4666
const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind}
4767
const_eval_dead_local =
@@ -77,21 +97,6 @@ const_eval_error = {$error_kind ->
7797
const_eval_exact_div_has_remainder =
7898
exact_div: {$a} cannot be divided by {$b} without remainder
7999
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-
95100
const_eval_extern_static =
96101
cannot access extern static `{$did}`
97102
const_eval_extern_type_field = `extern type` field does not have a known offset
@@ -111,7 +116,6 @@ const_eval_frame_note_inner = inside {$where_ ->
111116
112117
const_eval_frame_note_last = the failure occurred here
113118
114-
const_eval_in_bounds_test = out-of-bounds pointer use
115119
const_eval_incompatible_calling_conventions =
116120
calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
117121
@@ -206,7 +210,6 @@ const_eval_long_running =
206210
207211
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
208212
209-
const_eval_memory_access_test = memory access failed
210213
const_eval_memory_exhausted =
211214
tried to allocate more memory than available to compiler
212215
@@ -287,8 +290,6 @@ const_eval_offset_from_out_of_bounds =
287290
`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation
288291
const_eval_offset_from_overflow =
289292
`{$name}` called when first pointer is too far ahead of second
290-
const_eval_offset_from_test =
291-
out-of-bounds `offset_from` origin
292293
const_eval_offset_from_underflow =
293294
`{$name}` called when first pointer is too far before second
294295
const_eval_offset_from_unsigned_overflow =
@@ -312,27 +313,25 @@ const_eval_partial_pointer_overwrite =
312313
unable to overwrite parts of a pointer in memory at {$ptr}
313314
const_eval_pointer_arithmetic_overflow =
314315
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
316+
316317
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 ->
318+
{const_eval_bad_pointer_op_attempting}, but {$inbounds_size_is_neg ->
319+
[false] this pointer {$alloc_size_minus_ptr_offset ->
320+
[0] is at or beyond the end of the allocation of size {$alloc_size ->
326321
[1] 1 byte
327322
*[x] {$alloc_size} bytes
328323
}
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
324+
[1] is only 1 byte from the end of the allocation
325+
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
326+
}
327+
*[true] this pointer {$ptr_offset_abs ->
328+
[0] is at the beginning of the allocation
329+
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
331330
}
332-
}
333331
}
332+
334333
const_eval_pointer_use_after_free =
335-
{$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling
334+
{const_eval_bad_pointer_op}: {$alloc_id} has been freed, so this pointer is dangling
336335
const_eval_ptr_as_bytes_1 =
337336
this code performed an operation that depends on the underlying bytes representing a pointer
338337
const_eval_ptr_as_bytes_2 =

‎compiler/rustc_const_eval/src/errors.rs

Lines changed: 14 additions & 29 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,26 +610,28 @@ 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 } => {
640-
if addr != 0 {
641-
diag.arg(
642-
"pointer",
643-
Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
644-
);
645-
}
626+
diag.arg(
627+
"pointer",
628+
Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
629+
);
646630

631+
diag.arg("inbounds_size", inbounds_size);
647632
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
648633
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
649-
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
634+
diag.arg("operation", format!("{:?}", msg));
650635
}
651636
AlignmentCheckFailed(Misalignment { required, has }, msg) => {
652637
diag.arg("required", required.bytes());

0 commit comments

Comments
 (0)
Please sign in to comment.