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
11 changes: 8 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,12 @@ pub fn eval_to_const_value_raw_provider<'tcx>(

// FIXME(oli-obk): why don't we have any tests for this code path?
super::report(
tcx,
&InterpCx::new(
tcx,
tcx.def_span(def_id),
key.typing_env,
CompileTimeMachine::new(CanAccessMutGlobal::Yes, CheckAlignment::No),
),
error.into_kind(),
span,
|| (span, vec![]),
Expand Down Expand Up @@ -433,7 +438,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 @@ -473,7 +478,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
12 changes: 10 additions & 2 deletions compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use either::{Either, Left, Right};
use rustc_abi as abi;
use rustc_abi::{BackendRepr, HasDataLayout, Size};
use rustc_hir::def::Namespace;
use rustc_middle::mir::interpret::ScalarSizeMismatch;
use rustc_middle::mir::interpret::{BadBytesAccess, ScalarSizeMismatch};
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
Expand Down Expand Up @@ -663,7 +663,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
let imm = self.read_immediate_raw(op)?.right().unwrap();
if matches!(*imm, Immediate::Uninit) {
throw_ub!(InvalidUninitBytes(None));
throw_ub!(InvalidUninitBytes(match op.to_op(self)?.as_mplace_or_imm() {
Left(mplace) => mplace.ptr().provenance.and_then(|prov| {
let start = mplace.ptr().into_parts().1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct -- depending on which type of provenance this is, start will be either relative to the allocation, or absolute. into_parts has a doc comment warning about this. :) Maybe we should rename it into_raw_parts or so to make it more clear that this API is somewhat dicey.

let size = op.layout().size;
let range = alloc_range(start, size);
Some((prov.get_alloc_id()?, BadBytesAccess { access: range, bad: range }))
}),
Right(_) => None,
}))
Comment on lines -666 to +674
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one doesn't show up in diagnostics, but it seemed good to change it, too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't it show up in diagnostics? Aren't all the miri output diffs caused by exactly this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah no, that diff is probably caused by the read_scalar change.

If this logic here can't be tested, I'd rather remove it, given that it is currently wrong due to how it uses into_parts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#142839 gets rid of it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is read_immediate, #142839 does nothing there...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right, I mixed up things.

hmm. yea I think I just tried this one because I thought it should be hit somewhere. So I'll turn it into a span_bug

}
interp_ok(imm)
}
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 @@ -396,7 +396,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
Loading
Loading