Skip to content
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

miri: catch function calls where the argument is caller-invalid / the return value callee-invalid #115608

Merged
merged 1 commit into from
Sep 8, 2023
Merged
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
7 changes: 7 additions & 0 deletions compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,13 @@ where
dest: &impl Writeable<'tcx, M::Provenance>,
allow_transmute: bool,
) -> InterpResult<'tcx> {
// Generally for transmutation, data must be valid both at the old and new type.
// But if the types are the same, the 2nd validation below suffices.
if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) {
self.validate_operand(&src.to_op(self)?)?;
}

// Do the actual copy.
self.copy_op_no_validate(src, dest, allow_transmute)?;

if M::enforce_validity(self, dest.layout()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: constructing invalid value: encountered a null reference
--> $DIR/cast_fn_ptr1.rs:LL:CC
--> $DIR/cast_fn_ptr_invalid_callee_arg.rs:LL:CC
|
LL | g(0usize as *const i32)
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
|
= 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 $DIR/cast_fn_ptr1.rs:LL:CC
= note: inside `main` at $DIR/cast_fn_ptr_invalid_callee_arg.rs:LL:CC

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![allow(internal_features)]
#![feature(core_intrinsics, custom_mir)]

use std::intrinsics::mir::*;
use std::num::NonZeroU32;
use std::ptr;

// This function supposedly returns a NonZeroU32, but actually returns something invalid in a way that
// never materializes a bad NonZeroU32 value: we take a pointer to the return place and cast the pointer
// type. That way we never get an "invalid value constructed" error inside the function, it can
// only possibly be detected when the return value is passed to the caller.
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn f() -> NonZeroU32 {
mir! {
{
let tmp = ptr::addr_of_mut!(RET);
let ptr = tmp as *mut u32;
*ptr = 0;
Return()
}
}
}

fn main() {
let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZeroU32) };
// There's a NonZeroU32-to-u32 transmute happening here
f(); //~ERROR: expected something greater or equal to 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
--> $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
|
LL | f();
| ^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
|
= 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 $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC

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

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#![allow(internal_features)]
#![feature(core_intrinsics, custom_mir)]

use std::intrinsics::mir::*;
use std::num::NonZeroU32;
use std::ptr;

fn f(c: u32) {
println!("{c}");
}

// Call that function in a bad way, with an invalid NonZeroU32, but without
// ever materializing this as a NonZeroU32 value outside the call itself.
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn call(f: fn(NonZeroU32)) {
mir! {
let _res: ();
{
let c = 0;
let tmp = ptr::addr_of!(c);
let ptr = tmp as *const NonZeroU32;
// The call site now is a NonZeroU32-to-u32 transmute.
Call(_res = f(*ptr), retblock) //~ERROR: expected something greater or equal to 1
}
retblock = {
Return()
}
}
}

fn main() {
let f: fn(NonZeroU32) = unsafe { std::mem::transmute(f as fn(u32)) };
call(f);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
|
LL | Call(_res = f(*ptr), retblock)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
|
= 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 `call` at $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
note: inside `main`
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
|
LL | call(f);
| ^^^^^^^

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

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: constructing invalid value: encountered a null reference
--> $DIR/cast_fn_ptr2.rs:LL:CC
--> $DIR/cast_fn_ptr_invalid_caller_ret.rs:LL:CC
|
LL | let _x = g();
| ^^^ constructing invalid value: encountered a null reference
|
= 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 $DIR/cast_fn_ptr2.rs:LL:CC
= note: inside `main` at $DIR/cast_fn_ptr_invalid_caller_ret.rs:LL:CC

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

Expand Down
Loading