From e6aa23343e3cd322efe0585b9c95c300ab1cdca7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Oct 2023 08:53:54 +0200 Subject: [PATCH] add test to ensure RET assignments do not get propagated on unwinding --- .../return_pointer_on_unwind.rs | 55 +++++++++++++++++++ .../return_pointer_on_unwind.stderr | 19 +++++++ 2 files changed, 74 insertions(+) create mode 100644 src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs create mode 100644 src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs new file mode 100644 index 000000000000..79e29b79d6a2 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs @@ -0,0 +1,55 @@ +// Doesn't need an aliasing model. +//@compile-flags: -Zmiri-disable-stacked-borrows +#![feature(raw_ref_op)] +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; +use std::panic; + +#[repr(C)] +struct S(i32, [u8; 128]); + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn docall(out: &mut S) { + mir! { + { + Call(*out = callee(), after_call) + } + + after_call = { + Return() + } + } +} + +fn startpanic() -> () { + panic!() +} + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn callee() -> S { + mir! { + type RET = S; + let _unit: (); + { + // We test whether changes done to RET before unwinding + // become visible to the outside. In codegen we can see them + // but Miri should detect this as UB! + RET.0 = 42; + Call(_unit = startpanic(), after_call) + } + + after_call = { + Return() + } + } +} + +fn main() { + let mut x = S(0, [0; 128]); + panic::catch_unwind(panic::AssertUnwindSafe(|| docall(&mut x))).unwrap_err(); + // The return place got de-initialized before the call and assigning to RET + // does not propagate if we do not reach the `Return`. + dbg!(x.0); //~ERROR: uninitialized +} diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr new file mode 100644 index 000000000000..ecd9a111840a --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr @@ -0,0 +1,19 @@ +thread 'main' panicked at $DIR/return_pointer_on_unwind.rs:LL:CC: +explicit panic +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/return_pointer_on_unwind.rs:LL:CC + | +LL | dbg!(x.0); + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = 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) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error +