Skip to content

Commit 95ea8cb

Browse files
committed
Revert some miri changes
1 parent 60d514e commit 95ea8cb

28 files changed

+312
-351
lines changed

src/tools/miri/src/helpers.rs

+15
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
980980
return interp_ok(());
981981
}
982982

983+
if ["__rust_alloc", "__rust_alloc_zeroed", "__rust_realloc", "__rust_dealloc"]
984+
.contains(&link_name.as_str())
985+
{
986+
let attrs = self.eval_context_ref().tcx.codegen_fn_attrs(instance.def_id());
987+
if attrs
988+
.linkage
989+
.map_or(false, |linkage| linkage == rustc_middle::mir::mono::Linkage::WeakAny)
990+
&& attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
991+
{
992+
// We intentionally intercept the allocator methods even though libstd provides
993+
// default implementations.
994+
return interp_ok(());
995+
}
996+
}
997+
983998
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
984999
link_name,
9851000
span: body.span.data(),

src/tools/miri/src/shims/alloc.rs

+29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::{Align, Size};
2+
use rustc_ast::expand::allocator::AllocatorKind;
23

34
use crate::*;
45

@@ -49,6 +50,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
4950
Align::from_bytes(prev_power_of_two(size)).unwrap()
5051
}
5152

53+
/// Emulates calling the internal __rust_* allocator functions
54+
fn emulate_allocator(
55+
&mut self,
56+
default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>,
57+
) -> InterpResult<'tcx, EmulateItemResult> {
58+
let this = self.eval_context_mut();
59+
60+
let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
61+
// in real code, this symbol does not exist without an allocator
62+
return interp_ok(EmulateItemResult::NotSupported);
63+
};
64+
65+
match allocator_kind {
66+
AllocatorKind::Global => {
67+
// When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
68+
// of this attribute. As such we have to call an exported Rust function,
69+
// and not execute any Miri shim. Somewhat unintuitively doing so is done
70+
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
71+
// fallback case in `emulate_foreign_item`.
72+
interp_ok(EmulateItemResult::NotSupported)
73+
}
74+
AllocatorKind::Default => {
75+
default(this)?;
76+
interp_ok(EmulateItemResult::NeedsReturn)
77+
}
78+
}
79+
}
80+
5281
fn malloc(&mut self, size: u64, init: AllocInit) -> InterpResult<'tcx, Pointer> {
5382
let this = self.eval_context_mut();
5483
let align = this.malloc_align(size);

src/tools/miri/src/shims/foreign_items.rs

+117-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::hash_map::Entry;
22
use std::io::Write;
3+
use std::iter;
34
use std::path::Path;
45

56
use rustc_abi::{Align, AlignFromBytesError, Size};
@@ -502,34 +503,127 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
502503
}
503504

504505
// Rust allocation
505-
"miri_alloc" => {
506-
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
507-
let size = this.read_target_usize(size)?;
508-
let align = this.read_target_usize(align)?;
506+
"__rust_alloc" | "miri_alloc" => {
507+
let default = |ecx: &mut MiriInterpCx<'tcx>| {
508+
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
509+
// macro is used, we act like no shim exists, so that the exported function can run.
510+
let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?;
511+
let size = ecx.read_target_usize(size)?;
512+
let align = ecx.read_target_usize(align)?;
513+
514+
ecx.check_rustc_alloc_request(size, align)?;
515+
516+
let memory_kind = match link_name.as_str() {
517+
"__rust_alloc" => MiriMemoryKind::Rust,
518+
"miri_alloc" => MiriMemoryKind::Miri,
519+
_ => unreachable!(),
520+
};
509521

510-
this.check_rustc_alloc_request(size, align)?;
522+
let ptr = ecx.allocate_ptr(
523+
Size::from_bytes(size),
524+
Align::from_bytes(align).unwrap(),
525+
memory_kind.into(),
526+
AllocInit::Uninit,
527+
)?;
511528

512-
let ptr = this.allocate_ptr(
513-
Size::from_bytes(size),
514-
Align::from_bytes(align).unwrap(),
515-
MiriMemoryKind::Miri.into(),
516-
AllocInit::Uninit,
517-
)?;
529+
ecx.write_pointer(ptr, dest)
530+
};
518531

519-
this.write_pointer(ptr, dest)?;
532+
match link_name.as_str() {
533+
"__rust_alloc" => return this.emulate_allocator(default),
534+
"miri_alloc" => {
535+
default(this)?;
536+
return interp_ok(EmulateItemResult::NeedsReturn);
537+
}
538+
_ => unreachable!(),
539+
}
520540
}
521-
"miri_dealloc" => {
522-
let [ptr, old_size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
523-
let ptr = this.read_pointer(ptr)?;
524-
let old_size = this.read_target_usize(old_size)?;
525-
let align = this.read_target_usize(align)?;
541+
"__rust_alloc_zeroed" => {
542+
return this.emulate_allocator(|this| {
543+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
544+
// default case.
545+
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
546+
let size = this.read_target_usize(size)?;
547+
let align = this.read_target_usize(align)?;
548+
549+
this.check_rustc_alloc_request(size, align)?;
550+
551+
let ptr = this.allocate_ptr(
552+
Size::from_bytes(size),
553+
Align::from_bytes(align).unwrap(),
554+
MiriMemoryKind::Rust.into(),
555+
AllocInit::Zero,
556+
)?;
526557

527-
// No need to check old_size/align; we anyway check that they match the allocation.
528-
this.deallocate_ptr(
529-
ptr,
530-
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
531-
MiriMemoryKind::Miri.into(),
532-
)?;
558+
// We just allocated this, the access is definitely in-bounds.
559+
this.write_bytes_ptr(
560+
ptr.into(),
561+
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
562+
)
563+
.unwrap();
564+
this.write_pointer(ptr, dest)
565+
});
566+
}
567+
"__rust_dealloc" | "miri_dealloc" => {
568+
let default = |ecx: &mut MiriInterpCx<'tcx>| {
569+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
570+
// default case.
571+
let [ptr, old_size, align] =
572+
ecx.check_shim(abi, Conv::Rust, link_name, args)?;
573+
let ptr = ecx.read_pointer(ptr)?;
574+
let old_size = ecx.read_target_usize(old_size)?;
575+
let align = ecx.read_target_usize(align)?;
576+
577+
let memory_kind = match link_name.as_str() {
578+
"__rust_dealloc" => MiriMemoryKind::Rust,
579+
"miri_dealloc" => MiriMemoryKind::Miri,
580+
_ => unreachable!(),
581+
};
582+
583+
// No need to check old_size/align; we anyway check that they match the allocation.
584+
ecx.deallocate_ptr(
585+
ptr,
586+
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
587+
memory_kind.into(),
588+
)
589+
};
590+
591+
match link_name.as_str() {
592+
"__rust_dealloc" => {
593+
return this.emulate_allocator(default);
594+
}
595+
"miri_dealloc" => {
596+
default(this)?;
597+
return interp_ok(EmulateItemResult::NeedsReturn);
598+
}
599+
_ => unreachable!(),
600+
}
601+
}
602+
"__rust_realloc" => {
603+
return this.emulate_allocator(|this| {
604+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
605+
// default case.
606+
let [ptr, old_size, align, new_size] =
607+
this.check_shim(abi, Conv::Rust, link_name, args)?;
608+
let ptr = this.read_pointer(ptr)?;
609+
let old_size = this.read_target_usize(old_size)?;
610+
let align = this.read_target_usize(align)?;
611+
let new_size = this.read_target_usize(new_size)?;
612+
// No need to check old_size; we anyway check that they match the allocation.
613+
614+
this.check_rustc_alloc_request(new_size, align)?;
615+
616+
let align = Align::from_bytes(align).unwrap();
617+
let new_ptr = this.reallocate_ptr(
618+
ptr,
619+
Some((Size::from_bytes(old_size), align)),
620+
Size::from_bytes(new_size),
621+
align,
622+
MiriMemoryKind::Rust.into(),
623+
AllocInit::Uninit,
624+
)?;
625+
this.write_pointer(new_ptr, dest)
626+
});
533627
}
534628

535629
// C memory handling functions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 1 and alignment ALIGN
2+
--> tests/fail/alloc/deallocate-bad-alignment.rs:LL:CC
3+
|
4+
LL | dealloc(x, Layout::from_size_align_unchecked(1, 2));
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 1 and alignment ALIGN
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at tests/fail/alloc/deallocate-bad-alignment.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to 1 previous error
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
2+
--> tests/fail/alloc/deallocate-bad-size.rs:LL:CC
3+
|
4+
LL | dealloc(x, Layout::from_size_align_unchecked(2, 1));
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at tests/fail/alloc/deallocate-bad-size.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to 1 previous error
15+

src/tools/miri/tests/fail/alloc/deallocate-twice.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
2-
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
2+
--> tests/fail/alloc/deallocate-twice.rs:LL:CC
33
|
4-
LL | unsafe { libc::free(ptr as *mut libc::c_void) }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
4+
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
@@ -17,13 +17,7 @@ help: ALLOC was deallocated here:
1717
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
1818
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1919
= note: BACKTRACE (of the first span):
20-
= 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
21-
= note: inside `std::alloc::__default_lib_allocator::__rust_dealloc` at RUSTLIB/std/src/alloc.rs:LL:CC
22-
note: inside `main`
23-
--> tests/fail/alloc/deallocate-twice.rs:LL:CC
24-
|
25-
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
= note: inside `main` at tests/fail/alloc/deallocate-twice.rs:LL:CC
2721

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

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: Undefined Behavior: deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation
2+
--> RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC
3+
|
4+
LL | FREE();
5+
| ^ deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= 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
11+
= note: inside `<std::alloc::System as std::alloc::Allocator>::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC
12+
note: inside `main`
13+
--> tests/fail/alloc/global_system_mixup.rs:LL:CC
14+
|
15+
LL | unsafe { System.deallocate(ptr, l) };
16+
| ^
17+
18+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
19+
20+
error: aborting due to 1 previous error
21+
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
1-
error: memory leaked: ALLOC (C heap, size: 1, align: 1), allocated here:
2-
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
1+
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
2+
--> tests/fail/alloc/reallocate-bad-size.rs:LL:CC
33
|
4-
LL | unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size 1 and alignment ALIGN, but gave size 2 and alignment ALIGN
66
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
79
= note: BACKTRACE:
8-
= 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
9-
= note: inside `std::alloc::__default_lib_allocator::__rust_realloc` at RUSTLIB/std/src/alloc.rs:LL:CC
10-
note: inside `main`
11-
--> tests/fail/alloc/reallocate-bad-size.rs:LL:CC
12-
|
13-
LL | ... let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
= note: inside `main` at tests/fail/alloc/reallocate-bad-size.rs:LL:CC
1511

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

18-
note: set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check
19-
2014
error: aborting due to 1 previous error
2115

src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
2-
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
2+
--> tests/fail/alloc/reallocate-dangling.rs:LL:CC
33
|
4-
LL | unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
4+
LL | let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
@@ -17,13 +17,7 @@ help: ALLOC was deallocated here:
1717
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
1818
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1919
= note: BACKTRACE (of the first span):
20-
= 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
21-
= note: inside `std::alloc::__default_lib_allocator::__rust_realloc` at RUSTLIB/std/src/alloc.rs:LL:CC
22-
note: inside `main`
23-
--> tests/fail/alloc/reallocate-dangling.rs:LL:CC
24-
|
25-
LL | let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
= note: inside `main` at tests/fail/alloc/reallocate-dangling.rs:LL:CC
2721

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

src/tools/miri/tests/fail/alloc/stack_free.stderr

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
error: Undefined Behavior: deallocating ALLOC, which is stack variable memory, using C heap deallocation operation
2-
--> RUSTLIB/std/src/sys/alloc/unix.rs:LL:CC
1+
error: Undefined Behavior: deallocating ALLOC, which is stack variable memory, using Rust heap deallocation operation
2+
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
33
|
4-
LL | unsafe { libc::free(ptr as *mut libc::c_void) }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating ALLOC, which is stack variable memory, using C heap deallocation operation
4+
LL | self.1.deallocate(From::from(ptr.cast()), layout);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating ALLOC, which is stack variable memory, using Rust heap deallocation operation
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= 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
11-
= note: inside `std::alloc::__default_lib_allocator::__rust_dealloc` at RUSTLIB/std/src/alloc.rs:LL:CC
1210
= note: inside `<std::boxed::Box<i32> as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC
1311
= 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
1412
= note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC

0 commit comments

Comments
 (0)