Skip to content

Commit

Permalink
Revert some miri changes
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Dec 20, 2024
1 parent 0a56ec0 commit abd406c
Show file tree
Hide file tree
Showing 28 changed files with 312 additions and 351 deletions.
19 changes: 18 additions & 1 deletion src/tools/miri/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
if fn_abi.conv != exp_abi {
throw_ub_format!(
"calling a function with ABI {:?} using caller ABI {:?}",
exp_abi, fn_abi.conv);
exp_abi,
fn_abi.conv
);
}
interp_ok(())
}
Expand Down Expand Up @@ -964,6 +966,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
return interp_ok(());
}

if ["__rust_alloc", "__rust_alloc_zeroed", "__rust_realloc", "__rust_dealloc"]
.contains(&link_name.as_str())
{
let attrs = self.eval_context_ref().tcx.codegen_fn_attrs(instance.def_id());
if attrs
.linkage
.map_or(false, |linkage| linkage == rustc_middle::mir::mono::Linkage::WeakAny)
&& attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
{
// We intentionally intercept the allocator methods even though libstd provides
// default implementations.
return interp_ok(());
}
}

throw_machine_stop!(TerminationInfo::SymbolShimClashing {
link_name,
span: body.span.data(),
Expand Down
29 changes: 29 additions & 0 deletions src/tools/miri/src/shims/alloc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::iter;

use rustc_abi::{Align, Size};
use rustc_ast::expand::allocator::AllocatorKind;

use crate::*;

Expand Down Expand Up @@ -51,6 +52,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
Align::from_bytes(prev_power_of_two(size)).unwrap()
}

/// Emulates calling the internal __rust_* allocator functions
fn emulate_allocator(
&mut self,
default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();

let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
// in real code, this symbol does not exist without an allocator
return interp_ok(EmulateItemResult::NotSupported);
};

match allocator_kind {
AllocatorKind::Global => {
// When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
// of this attribute. As such we have to call an exported Rust function,
// and not execute any Miri shim. Somewhat unintuitively doing so is done
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
// fallback case in `emulate_foreign_item`.
interp_ok(EmulateItemResult::NotSupported)
}
AllocatorKind::Default => {
default(this)?;
interp_ok(EmulateItemResult::NeedsReturn)
}
}
}

fn malloc(&mut self, size: u64, zero_init: bool) -> InterpResult<'tcx, Pointer> {
let this = self.eval_context_mut();
let align = this.malloc_align(size);
Expand Down
136 changes: 114 additions & 22 deletions src/tools/miri/src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::hash_map::Entry;
use std::io::Write;
use std::iter;
use std::path::Path;

use rustc_abi::{Align, AlignFromBytesError, Size};
Expand Down Expand Up @@ -501,33 +502,124 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
}

// Rust allocation
"miri_alloc" => {
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let size = this.read_target_usize(size)?;
let align = this.read_target_usize(align)?;
"__rust_alloc" | "miri_alloc" => {
let default = |ecx: &mut MiriInterpCx<'tcx>| {
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
// macro is used, we act like no shim exists, so that the exported function can run.
let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?;
let size = ecx.read_target_usize(size)?;
let align = ecx.read_target_usize(align)?;

ecx.check_rustc_alloc_request(size, align)?;

let memory_kind = match link_name.as_str() {
"__rust_alloc" => MiriMemoryKind::Rust,
"miri_alloc" => MiriMemoryKind::Miri,
_ => unreachable!(),
};

this.check_rustc_alloc_request(size, align)?;
let ptr = ecx.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
memory_kind.into(),
)?;

let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Miri.into(),
)?;
ecx.write_pointer(ptr, dest)
};

this.write_pointer(ptr, dest)?;
match link_name.as_str() {
"__rust_alloc" => return this.emulate_allocator(default),
"miri_alloc" => {
default(this)?;
return interp_ok(EmulateItemResult::NeedsReturn);
}
_ => unreachable!(),
}
}
"miri_dealloc" => {
let [ptr, old_size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let old_size = this.read_target_usize(old_size)?;
let align = this.read_target_usize(align)?;
"__rust_alloc_zeroed" => {
return this.emulate_allocator(|this| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let size = this.read_target_usize(size)?;
let align = this.read_target_usize(align)?;

// No need to check old_size/align; we anyway check that they match the allocation.
this.deallocate_ptr(
ptr,
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
MiriMemoryKind::Miri.into(),
)?;
this.check_rustc_alloc_request(size, align)?;

let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Rust.into(),
)?;

// We just allocated this, the access is definitely in-bounds.
this.write_bytes_ptr(
ptr.into(),
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
)
.unwrap();
this.write_pointer(ptr, dest)
});
}
"__rust_dealloc" | "miri_dealloc" => {
let default = |ecx: &mut MiriInterpCx<'tcx>| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
let [ptr, old_size, align] =
ecx.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = ecx.read_pointer(ptr)?;
let old_size = ecx.read_target_usize(old_size)?;
let align = ecx.read_target_usize(align)?;

let memory_kind = match link_name.as_str() {
"__rust_dealloc" => MiriMemoryKind::Rust,
"miri_dealloc" => MiriMemoryKind::Miri,
_ => unreachable!(),
};

// No need to check old_size/align; we anyway check that they match the allocation.
ecx.deallocate_ptr(
ptr,
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
memory_kind.into(),
)
};

match link_name.as_str() {
"__rust_dealloc" => {
return this.emulate_allocator(default);
}
"miri_dealloc" => {
default(this)?;
return interp_ok(EmulateItemResult::NeedsReturn);
}
_ => unreachable!(),
}
}
"__rust_realloc" => {
return this.emulate_allocator(|this| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
let [ptr, old_size, align, new_size] =
this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let old_size = this.read_target_usize(old_size)?;
let align = this.read_target_usize(align)?;
let new_size = this.read_target_usize(new_size)?;
// No need to check old_size; we anyway check that they match the allocation.

this.check_rustc_alloc_request(new_size, align)?;

let align = Align::from_bytes(align).unwrap();
let new_ptr = this.reallocate_ptr(
ptr,
Some((Size::from_bytes(old_size), align)),
Size::from_bytes(new_size),
align,
MiriMemoryKind::Rust.into(),
)?;
this.write_pointer(new_ptr, dest)
});
}

// C memory handling functions
Expand Down
15 changes: 15 additions & 0 deletions src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 1 and alignment ALIGN
--> tests/fail/alloc/deallocate-bad-alignment.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 1 and alignment ALIGN
|
= 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 tests/fail/alloc/deallocate-bad-alignment.rs:LL:CC

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

error: aborting due to 1 previous error

15 changes: 15 additions & 0 deletions src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
--> tests/fail/alloc/deallocate-bad-size.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(2, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
|
= 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 tests/fail/alloc/deallocate-bad-size.rs:LL:CC

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

error: aborting due to 1 previous error

14 changes: 4 additions & 10 deletions src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
--> tests/fail/alloc/deallocate-twice.rs:LL:CC
|
LL | unsafe { libc::free(ptr as *mut libc::c_void) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
|
= 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
Expand All @@ -17,13 +17,7 @@ help: ALLOC was deallocated here:
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::sys::alloc::unix::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
= note: inside `std::alloc::__default_lib_allocator::__rust_dealloc` at RUSTLIB/std/src/alloc.rs:LL:CC
note: inside `main`
--> tests/fail/alloc/deallocate-twice.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `main` at tests/fail/alloc/deallocate-twice.rs:LL:CC

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

Expand Down
21 changes: 21 additions & 0 deletions src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error: Undefined Behavior: deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation
--> RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC
|
LL | FREE();
| ^ deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation
|
= 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 `std::sys::alloc::PLATFORM::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC
= note: inside `<std::alloc::System as std::alloc::Allocator>::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC
note: inside `main`
--> tests/fail/alloc/global_system_mixup.rs:LL:CC
|
LL | unsafe { System.deallocate(ptr, l) };
| ^

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

error: aborting due to 1 previous error

20 changes: 7 additions & 13 deletions src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
error: memory leaked: ALLOC (C heap, size: 1, align: 1), allocated here:
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
--> tests/fail/alloc/reallocate-bad-size.rs:LL:CC
|
LL | unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
|
= 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 `std::sys::alloc::unix::<impl std::alloc::GlobalAlloc for std::alloc::System>::realloc` at RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
= note: inside `std::alloc::__default_lib_allocator::__rust_realloc` at RUSTLIB/std/src/alloc.rs:LL:CC
note: inside `main`
--> tests/fail/alloc/reallocate-bad-size.rs:LL:CC
|
LL | ... let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `main` at tests/fail/alloc/reallocate-bad-size.rs:LL:CC

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

note: set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check

error: aborting due to 1 previous error

14 changes: 4 additions & 10 deletions src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
--> tests/fail/alloc/reallocate-dangling.rs:LL:CC
|
LL | unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
LL | let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
|
= 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
Expand All @@ -17,13 +17,7 @@ help: ALLOC was deallocated here:
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::sys::alloc::unix::<impl std::alloc::GlobalAlloc for std::alloc::System>::realloc` at RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
= note: inside `std::alloc::__default_lib_allocator::__rust_realloc` at RUSTLIB/std/src/alloc.rs:LL:CC
note: inside `main`
--> tests/fail/alloc/reallocate-dangling.rs:LL:CC
|
LL | let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `main` at tests/fail/alloc/reallocate-dangling.rs:LL:CC

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

Expand Down
10 changes: 4 additions & 6 deletions src/tools/miri/tests/fail/alloc/stack_free.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
error: Undefined Behavior: deallocating ALLOC, which is stack variable memory, using C heap deallocation operation
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
error: Undefined Behavior: deallocating ALLOC, which is stack variable memory, using Rust heap deallocation operation
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | unsafe { libc::free(ptr as *mut libc::c_void) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating ALLOC, which is stack variable memory, using C heap deallocation operation
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating ALLOC, which is stack variable memory, using Rust heap deallocation operation
|
= 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 `std::sys::alloc::unix::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
= note: inside `std::alloc::__default_lib_allocator::__rust_dealloc` at RUSTLIB/std/src/alloc.rs:LL:CC
= note: inside `<std::boxed::Box<i32> as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
= note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
Expand Down
Loading

0 comments on commit abd406c

Please sign in to comment.