Skip to content

Commit 6ffb2af

Browse files
committed
Show the memory of uninit reads
1 parent bbc7905 commit 6ffb2af

25 files changed

+238
-85
lines changed

compiler/rustc_const_eval/src/const_eval/error.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ use std::mem;
22

33
use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
44
use rustc_middle::mir::AssertKind;
5-
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
5+
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo, UndefinedBehaviorInfo};
66
use rustc_middle::query::TyCtxtAt;
7+
use rustc_middle::ty::ConstInt;
78
use rustc_middle::ty::layout::LayoutError;
8-
use rustc_middle::ty::{ConstInt, TyCtxt};
99
use rustc_span::{Span, Symbol};
1010

1111
use super::CompileTimeMachine;
1212
use crate::errors::{self, FrameNote, ReportErrorExt};
1313
use crate::interpret::{
14-
ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
14+
ErrorHandled, Frame, InterpCx, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
1515
err_machine_stop,
1616
};
1717

@@ -135,7 +135,7 @@ pub fn get_span_and_frames<'tcx>(
135135
/// You can use it to add a stacktrace of current execution according to
136136
/// `get_span_and_frames` or just give context on where the const eval error happened.
137137
pub(super) fn report<'tcx, C, F>(
138-
tcx: TyCtxt<'tcx>,
138+
ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
139139
error: InterpErrorKind<'tcx>,
140140
span: Span,
141141
get_span_and_frames: C,
@@ -145,6 +145,7 @@ where
145145
C: FnOnce() -> (Span, Vec<FrameNote>),
146146
F: FnOnce(&mut Diag<'_>, Span, Vec<FrameNote>),
147147
{
148+
let tcx = ecx.tcx.tcx;
148149
// Special handling for certain errors
149150
match error {
150151
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
@@ -170,9 +171,24 @@ where
170171
InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
171172
);
172173

174+
if let InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(
175+
Some((alloc_id, _access)),
176+
)) = error
177+
{
178+
let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
179+
let info = ecx.get_alloc_info(alloc_id);
180+
let raw_bytes = errors::RawBytesNote {
181+
size: info.size.bytes(),
182+
align: info.align.bytes(),
183+
bytes,
184+
};
185+
err.subdiagnostic(raw_bytes);
186+
}
187+
173188
error.add_args(&mut err);
174189

175190
mk(&mut err, span, frames);
191+
176192
let g = err.emit();
177193
let reported = if allowed_in_infallible {
178194
ReportedErrorInfo::allowed_in_infallible(g)

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,12 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
293293

294294
// FIXME(oli-obk): why don't we have any tests for this code path?
295295
super::report(
296-
tcx,
296+
&InterpCx::new(
297+
tcx,
298+
tcx.def_span(def_id),
299+
key.typing_env,
300+
CompileTimeMachine::new(CanAccessMutGlobal::Yes, CheckAlignment::No),
301+
),
297302
error.into_kind(),
298303
span,
299304
|| (span, vec![]),
@@ -433,7 +438,7 @@ fn report_eval_error<'tcx>(
433438
let instance = with_no_trimmed_paths!(cid.instance.to_string());
434439

435440
super::report(
436-
*ecx.tcx,
441+
ecx,
437442
error,
438443
DUMMY_SP,
439444
|| super::get_span_and_frames(ecx.tcx, ecx.stack()),
@@ -473,7 +478,7 @@ fn report_validation_error<'tcx>(
473478
errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
474479

475480
crate::const_eval::report(
476-
*ecx.tcx,
481+
ecx,
477482
error,
478483
DUMMY_SP,
479484
|| crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),

tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at
33
|
44
LL | get_flag::<false, { unsafe { char_raw.character } }>();
55
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#7}` failed here
6+
|
7+
= note: the raw bytes of the constant (size: 4, align: 4) {
8+
ff __ __ __ │ .░░░
9+
}
610

711
error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
812
--> $DIR/invalid-patterns.rs:42:14
@@ -31,6 +35,10 @@ error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at
3135
|
3236
LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
3337
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#11}` failed here
38+
|
39+
= note: the raw bytes of the constant (size: 4, align: 4) {
40+
ff __ __ __ │ .░░░
41+
}
3442

3543
error[E0308]: mismatched types
3644
--> $DIR/invalid-patterns.rs:31:21

tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at
33
|
44
LL | get_flag::<false, { unsafe { char_raw.character } }>();
55
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#7}` failed here
6+
|
7+
= note: the raw bytes of the constant (size: 4, align: 4) {
8+
ff __ __ __ │ .░░░
9+
}
610

711
error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
812
--> $DIR/invalid-patterns.rs:42:14
@@ -31,6 +35,10 @@ error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at
3135
|
3236
LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
3337
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#11}` failed here
38+
|
39+
= note: the raw bytes of the constant (size: 4, align: 4) {
40+
ff __ __ __ │ .░░░
41+
}
3442

3543
error[E0308]: mismatched types
3644
--> $DIR/invalid-patterns.rs:31:21

tests/ui/consts/const-compare-bytes-ub.stderr

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at
3333
|
3434
LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1)
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::LHS_UNINIT` failed here
36+
|
37+
= note: the raw bytes of the constant (size: 1, align: 1) {
38+
__ │ ░
39+
}
3640

3741
error[E0080]: reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
3842
--> $DIR/const-compare-bytes-ub.rs:33:9
3943
|
4044
LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1)
4145
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::RHS_UNINIT` failed here
46+
|
47+
= note: the raw bytes of the constant (size: 1, align: 1) {
48+
__ │ ░
49+
}
4250

4351
error[E0080]: unable to turn pointer into integer
4452
--> $DIR/const-compare-bytes-ub.rs:37:9
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
2+
--> $DIR/const-err-enum-discriminant.rs:10:21
3+
|
4+
LL | Boo = [unsafe { Foo { b: () }.a }; 4][3],
5+
| ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here
6+
|
7+
= note: the raw bytes of the constant (size: 4, align: 4) {
8+
__ __ __ __ │ ░░░░
9+
}
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0080`.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory
2+
--> $DIR/const-err-enum-discriminant.rs:10:21
3+
|
4+
LL | Boo = [unsafe { Foo { b: () }.a }; 4][3],
5+
| ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here
6+
|
7+
= note: the raw bytes of the constant (size: 8, align: 8) {
8+
__ __ __ __ __ __ __ __ │ ░░░░░░░░
9+
}
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0080`.

tests/ui/consts/const-err-enum-discriminant.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//@ stderr-per-bitwidth
2+
13
#[derive(Copy, Clone)]
24
union Foo {
35
a: isize,

tests/ui/consts/const-err-enum-discriminant.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at
33
|
44
LL | Boo = [unsafe { Foo { b: () }.a }; 4][3],
55
| ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here
6+
|
7+
= note: the raw bytes of the constant (size: 4, align: 4) {
8+
__ __ __ __ │ ░░░░
9+
}
610

711
error: aborting due to 1 previous error
812

tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@ LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin
4343
= help: this code performed an operation that depends on the underlying bytes representing a pointer
4444
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
4545

46-
error[E0080]: reading memory at ALLOC0[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory
46+
error[E0080]: reading memory at ALLOC2[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory
4747
--> $DIR/const-pointer-values-in-various-types.rs:42:47
4848
|
4949
LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
5050
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::I32_REF_U128_UNION` failed here
51+
|
52+
= note: the raw bytes of the constant (size: 16, align: 16) {
53+
╾ALLOC0<imm>╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░
54+
}
5155

5256
error[E0080]: unable to turn pointer into integer
5357
--> $DIR/const-pointer-values-in-various-types.rs:45:43
@@ -85,11 +89,15 @@ LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int
8589
= help: this code performed an operation that depends on the underlying bytes representing a pointer
8690
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
8791

88-
error[E0080]: reading memory at ALLOC1[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory
92+
error[E0080]: reading memory at ALLOC3[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory
8993
--> $DIR/const-pointer-values-in-various-types.rs:57:47
9094
|
9195
LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
9296
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::I32_REF_I128_UNION` failed here
97+
|
98+
= note: the raw bytes of the constant (size: 16, align: 16) {
99+
╾ALLOC1<imm>╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░
100+
}
93101

94102
error[E0080]: unable to turn pointer into integer
95103
--> $DIR/const-pointer-values-in-various-types.rs:60:45

0 commit comments

Comments
 (0)