Skip to content

Show the offset, length and memory of uninit read errors #142673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions compiler/rustc_const_eval/src/const_eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ use std::mem;

use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo, UndefinedBehaviorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::ConstInt;
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{ConstInt, TyCtxt};
use rustc_span::{Span, Symbol};

use super::CompileTimeMachine;
use crate::errors::{self, FrameNote, ReportErrorExt};
use crate::interpret::{
ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
ErrorHandled, Frame, InterpCx, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
err_machine_stop,
};

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

if let InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(
Some((alloc_id, _access)),
)) = error
{
let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
let info = ecx.get_alloc_info(alloc_id);
let raw_bytes = errors::RawBytesNote {
size: info.size.bytes(),
align: info.align.bytes(),
bytes,
};
err.subdiagnostic(raw_bytes);
}

error.add_args(&mut err);

mk(&mut err, span, frames);

let g = err.emit();
let reported = if allowed_in_infallible {
ReportedErrorInfo::allowed_in_infallible(g)
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ fn report_eval_error<'tcx>(
let instance = with_no_trimmed_paths!(cid.instance.to_string());

super::report(
*ecx.tcx,
ecx,
error,
DUMMY_SP,
|| super::get_span_and_frames(ecx.tcx, ecx.stack()),
Expand Down Expand Up @@ -446,7 +446,7 @@ fn report_validation_error<'tcx>(
errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };

crate::const_eval::report(
*ecx.tcx,
ecx,
error,
DUMMY_SP,
|| crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
interp_ok(try_validation!(
self.ecx.read_immediate(val),
self.path,
Ub(InvalidUninitBytes(None)) =>
Ub(InvalidUninitBytes(_)) =>
Uninit { expected },
// The `Unsup` cases can only occur during CTFE
Unsup(ReadPointerAsInt(_)) =>
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_middle/src/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,11 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
read_provenance: bool,
) -> AllocResult<Scalar<Prov>> {
// First and foremost, if anything is uninit, bail.
if self.init_mask.is_range_initialized(range).is_err() {
return Err(AllocError::InvalidUninitBytes(None));
if let Err(bad) = self.init_mask.is_range_initialized(range) {
return Err(AllocError::InvalidUninitBytes(Some(BadBytesAccess {
access: range,
bad,
})));
}

// Get the integer part of the result. We HAVE TO check provenance before returning this!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ignore-target: windows # No pthreads on Windows
//@ normalize-stderr-test: ".*│.*\n" -> ""
//@ normalize-stderr-test: "size: [0-9]+" -> "size: SIZE"
//@ normalize-stderr-test: "align: [0-9]+" -> "align: ALIGN"
//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"

/// Test that destroying a pthread_cond twice fails, even without a check for number validity
Expand All @@ -15,6 +19,6 @@ fn main() {
libc::pthread_cond_destroy(cond.as_mut_ptr());

libc::pthread_cond_destroy(cond.as_mut_ptr());
//~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
//~^ ERROR: /Undefined Behavior: .* but memory is uninitialized/
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC
|
LL | libc::pthread_cond_destroy(cond.as_mut_ptr());
Expand All @@ -9,6 +9,10 @@ LL | libc::pthread_cond_destroy(cond.as_mut_ptr());
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC

Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
ALLOC (stack variable, size: SIZE, align: ALIGN) {
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//@ignore-target: windows # No pthreads on Windows
//@ignore-target: apple # Our macOS condattr don't have any fields so we do not notice this.
//@ normalize-stderr-test: ".*│.*\n" -> ""
//@ normalize-stderr-test: "size: [0-9]+" -> "size: SIZE"
//@ normalize-stderr-test: "align: [0-9]+" -> "align: ALIGN"
//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"

/// Test that destroying a pthread_condattr twice fails, even without a check for number validity

Expand All @@ -13,6 +17,6 @@ fn main() {
libc::pthread_condattr_destroy(attr.as_mut_ptr());

libc::pthread_condattr_destroy(attr.as_mut_ptr());
//~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
//~^ ERROR: /Undefined Behavior: .* but memory is uninitialized/
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC
|
LL | libc::pthread_condattr_destroy(attr.as_mut_ptr());
Expand All @@ -9,6 +9,10 @@ LL | libc::pthread_condattr_destroy(attr.as_mut_ptr());
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC

Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
ALLOC (stack variable, size: SIZE, align: ALIGN) {
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ignore-target: windows # No pthreads on Windows
//@ normalize-stderr-test: ".*│.*\n" -> ""
//@ normalize-stderr-test: "size: [0-9]+" -> "size: SIZE"
//@ normalize-stderr-test: "align: [0-9]+" -> "align: ALIGN"
//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"

/// Test that destroying a pthread_mutex twice fails, even without a check for number validity

Expand All @@ -16,6 +20,6 @@ fn main() {
libc::pthread_mutex_destroy(mutex.as_mut_ptr());

libc::pthread_mutex_destroy(mutex.as_mut_ptr());
//~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
//~^ ERROR: /Undefined Behavior: .* but memory is uninitialized/
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC
|
LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr());
Expand All @@ -9,6 +9,10 @@ LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr());
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC

Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
ALLOC (stack variable, size: SIZE, align: ALIGN) {
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ignore-target: windows # No pthreads on Windows
//@ normalize-stderr-test: ".*│.*\n" -> ""
//@ normalize-stderr-test: "size: [0-9]+" -> "size: SIZE"
//@ normalize-stderr-test: "align: [0-9]+" -> "align: ALIGN"
//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"

/// Test that destroying a pthread_mutexattr twice fails, even without a check for number validity

Expand All @@ -12,6 +16,6 @@ fn main() {
libc::pthread_mutexattr_destroy(attr.as_mut_ptr());

libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
//~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
//~^ ERROR: /Undefined Behavior: .* but memory is uninitialized/
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC
|
LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
Expand All @@ -9,6 +9,10 @@ LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC

Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
ALLOC (stack variable, size: SIZE, align: ALIGN) {
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ignore-target: windows # No pthreads on Windows
//@ normalize-stderr-test: ".*│.*\n" -> ""
//@ normalize-stderr-test: "size: [0-9]+" -> "size: SIZE"
//@ normalize-stderr-test: "align: [0-9]+" -> "align: ALIGN"
//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"

/// Test that destroying a pthread_rwlock twice fails, even without a check for number validity

Expand All @@ -9,6 +13,6 @@ fn main() {
libc::pthread_rwlock_destroy(&mut lock);

libc::pthread_rwlock_destroy(&mut lock);
//~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
//~^ ERROR: /Undefined Behavior: .* but memory is uninitialized/
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC
|
LL | libc::pthread_rwlock_destroy(&mut lock);
Expand All @@ -9,6 +9,10 @@ LL | libc::pthread_rwlock_destroy(&mut lock);
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC

Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
ALLOC (stack variable, size: SIZE, align: ALIGN) {
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/arg_inplace_observe_after.rs:LL:CC
|
LL | _observe = non_copy.0;
Expand All @@ -9,6 +9,11 @@ LL | _observe = non_copy.0;
= note: BACKTRACE:
= note: inside `main` at tests/fail/function_calls/arg_inplace_observe_after.rs:LL:CC

Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
ALLOC (stack variable, size: 4, align: 4) {
__ __ __ __ │ ░░░░
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC
|
LL | unsafe { ptr.read() };
Expand All @@ -14,6 +14,11 @@ note: inside `main`
LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
ALLOC (stack variable, size: 4, align: 4) {
__ __ __ __ │ ░░░░
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
LL | unsafe { ptr.read() };
Expand All @@ -14,6 +14,11 @@ note: inside `main`
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
ALLOC (stack variable, size: 4, align: 4) {
__ __ __ __ │ ░░░░
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ thread 'main' panicked at tests/fail/function_calls/return_pointer_on_unwind.rs:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC
|
LL | dbg!(x.0);
Expand All @@ -15,6 +15,19 @@ LL | dbg!(x.0);
= note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)

Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
ALLOC (stack variable, size: 132, align: 4) {
0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x30 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x40 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x50 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x60 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x70 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
0x80 │ __ __ __ __ │ ░░░░
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
//@compile-flags: -Zmiri-disable-validation
//@ normalize-stderr-test: ".*│.*\n" -> ""
//@ normalize-stderr-test: "size: [0-9]+" -> "size: SIZE"
//@ normalize-stderr-test: "align: [0-9]+" -> "align: ALIGN"
//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"

#![feature(core_intrinsics, custom_mir)]
use std::intrinsics::mir::*;

Expand All @@ -9,7 +14,7 @@ use std::intrinsics::mir::*;
pub unsafe fn deref_meta(p: *const *const [i32]) -> usize {
mir! {
{
RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .* but memory is uninitialized/
Return()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs:LL:CC
|
LL | RET = PtrMetadata(*p);
Expand All @@ -14,6 +14,10 @@ note: inside `main`
LL | let _meta = deref_meta(p.as_ptr().cast());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
ALLOC (stack variable, size: SIZE, align: ALIGN) {
}

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error
Expand Down
Loading
Loading