Skip to content

directly call handle_alloc_error #3480

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

Merged
merged 3 commits into from
Apr 17, 2024
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
17 changes: 1 addition & 16 deletions tests/fail/alloc/alloc_error_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,7 @@
#![feature(allocator_api)]

use std::alloc::*;
use std::ptr::NonNull;

struct BadAlloc;

// Create a failing allocator; Miri's native allocator never fails so this is the only way to
// actually call the alloc error handler.
unsafe impl Allocator for BadAlloc {
fn allocate(&self, _l: Layout) -> Result<NonNull<[u8]>, AllocError> {
Err(AllocError)
}

unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
unreachable!();
}
}

fn main() {
let _b = Box::new_in(0, BadAlloc);
handle_alloc_error(Layout::for_value(&0));
}
4 changes: 1 addition & 3 deletions tests/fail/alloc/alloc_error_handler.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ LL | ABORT();
= note: inside `std::alloc::_::__rg_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
= note: inside `std::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::boxed::Box::<i32, BadAlloc>::new_uninit_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<i32, BadAlloc>::new_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
note: inside `main`
--> $DIR/alloc_error_handler.rs:LL:CC
|
LL | let _b = Box::new_in(0, BadAlloc);
LL | handle_alloc_error(Layout::for_value(&0));
| ^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
Expand Down
49 changes: 49 additions & 0 deletions tests/fail/alloc/alloc_error_handler_custom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//@compile-flags: -Cpanic=abort
#![feature(start, core_intrinsics)]
#![feature(alloc_error_handler)]
#![feature(allocator_api)]
#![no_std]

extern crate alloc;

use alloc::alloc::*;
use core::fmt::Write;

#[path = "../../utils/mod.no_std.rs"]
mod utils;

#[alloc_error_handler]
fn alloc_error_handler(layout: Layout) -> ! {
let _ = writeln!(utils::MiriStderr, "custom alloc error handler: {layout:?}");
core::intrinsics::abort(); //~ERROR: aborted
}

// rustc requires us to provide some more things that aren't actually used by this test
mod plumbing {
use super::*;

#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {}
}

struct NoAlloc;

unsafe impl GlobalAlloc for NoAlloc {
unsafe fn alloc(&self, _: Layout) -> *mut u8 {
unreachable!();
}

unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
unreachable!();
}
}

#[global_allocator]
static GLOBAL: NoAlloc = NoAlloc;
}

#[start]
fn start(_: isize, _: *const *const u8) -> isize {
handle_alloc_error(Layout::for_value(&0));
}
27 changes: 27 additions & 0 deletions tests/fail/alloc/alloc_error_handler_custom.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
custom alloc error handler: Layout { size: 4, align: 4 (1 << 2) }
error: abnormal termination: the program aborted execution
--> $DIR/alloc_error_handler_custom.rs:LL:CC
|
LL | core::intrinsics::abort();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the program aborted execution
|
= note: BACKTRACE:
= note: inside `alloc_error_handler` at $DIR/alloc_error_handler_custom.rs:LL:CC
note: inside `_::__rg_oom`
--> $DIR/alloc_error_handler_custom.rs:LL:CC
|
LL | #[alloc_error_handler]
| ---------------------- in this procedural macro expansion
LL | fn alloc_error_handler(layout: Layout) -> ! {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
note: inside `start`
--> $DIR/alloc_error_handler_custom.rs:LL:CC
|
LL | handle_alloc_error(Layout::for_value(&0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

36 changes: 9 additions & 27 deletions tests/fail/alloc/alloc_error_handler_no_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,24 @@
extern crate alloc;

use alloc::alloc::*;
use alloc::boxed::Box;
use core::ptr::NonNull;
use core::fmt::Write;

struct BadAlloc;
#[path = "../../utils/mod.no_std.rs"]
mod utils;

// Create a failing allocator; that is the only way to actually call the alloc error handler.
unsafe impl Allocator for BadAlloc {
fn allocate(&self, _l: Layout) -> Result<NonNull<[u8]>, AllocError> {
Err(AllocError)
}

unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
unreachable!();
}
}
// The default no_std alloc_error_handler is a panic.

#[alloc_error_handler]
fn alloc_error_handler(_: Layout) -> ! {
extern "Rust" {
fn miri_write_to_stderr(bytes: &[u8]);
}
let msg = "custom alloc error handler called!\n";
unsafe { miri_write_to_stderr(msg.as_bytes()) };
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let _ = writeln!(utils::MiriStderr, "custom panic handler called!");
let _ = writeln!(utils::MiriStderr, "{panic_info}");
core::intrinsics::abort(); //~ERROR: aborted
}

// rustc requires us to provide some more things that aren't actually used by this test
mod plumbing {
use super::*;

#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
core::intrinsics::abort();
}

struct NoAlloc;

unsafe impl GlobalAlloc for NoAlloc {
Expand All @@ -60,6 +43,5 @@ mod plumbing {

#[start]
fn start(_: isize, _: *const *const u8) -> isize {
let _b = Box::new_in(0, BadAlloc);
0
handle_alloc_error(Layout::for_value(&0));
}
23 changes: 9 additions & 14 deletions tests/fail/alloc/alloc_error_handler_no_std.stderr
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
custom alloc error handler called!
custom panic handler called!
panicked at RUSTLIB/alloc/src/alloc.rs:LL:CC:
memory allocation of 4 bytes failed
error: abnormal termination: the program aborted execution
--> $DIR/alloc_error_handler_no_std.rs:LL:CC
|
LL | core::intrinsics::abort();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the program aborted execution
|
= note: BACKTRACE:
= note: inside `alloc_error_handler` at $DIR/alloc_error_handler_no_std.rs:LL:CC
note: inside `_::__rg_oom`
--> $DIR/alloc_error_handler_no_std.rs:LL:CC
|
LL | #[alloc_error_handler]
| ---------------------- in this procedural macro expansion
LL | fn alloc_error_handler(_: Layout) -> ! {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `panic_handler` at $DIR/alloc_error_handler_no_std.rs:LL:CC
= note: inside `alloc::alloc::__alloc_error_handler::__rdl_oom` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `alloc::boxed::Box::<i32, BadAlloc>::new_uninit_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `alloc::boxed::Box::<i32, BadAlloc>::new_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
note: inside `start`
--> $DIR/alloc_error_handler_no_std.rs:LL:CC
|
LL | let _b = Box::new_in(0, BadAlloc);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
LL | handle_alloc_error(Layout::for_value(&0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

error: aborting due to 1 previous error

24 changes: 4 additions & 20 deletions tests/fail/panic/no_std.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
//@compile-flags: -Cpanic=abort
#![feature(start, core_intrinsics)]
#![no_std]
//@compile-flags: -Cpanic=abort

// Plumbing to let us use `writeln!` to host stderr:

extern "Rust" {
fn miri_write_to_stderr(bytes: &[u8]);
}

struct HostErr;

use core::fmt::Write;

impl Write for HostErr {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
unsafe {
miri_write_to_stderr(s.as_bytes());
}
Ok(())
}
}

// Aaaand the test:
#[path = "../../utils/mod.no_std.rs"]
mod utils;

#[start]
fn start(_: isize, _: *const *const u8) -> isize {
Expand All @@ -30,6 +14,6 @@ fn start(_: isize, _: *const *const u8) -> isize {

#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
writeln!(HostErr, "{panic_info}").ok();
writeln!(utils::MiriStderr, "{panic_info}").ok();
core::intrinsics::abort(); //~ ERROR: the program aborted execution
}
20 changes: 20 additions & 0 deletions tests/panic/alloc_error_handler_hook.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![feature(allocator_api, alloc_error_hook)]

use std::alloc::*;

struct Bomb;
impl Drop for Bomb {
fn drop(&mut self) {
eprintln!("yes we are unwinding!");
}
}

#[allow(unreachable_code, unused_variables)]
fn main() {
// This is a particularly tricky hook, since it unwinds, which the default one does not.
set_alloc_error_hook(|_layout| panic!("alloc error hook called"));

let bomb = Bomb;
handle_alloc_error(Layout::for_value(&0));
std::mem::forget(bomb); // defuse unwinding bomb
}
4 changes: 4 additions & 0 deletions tests/panic/alloc_error_handler_hook.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
thread 'main' panicked at $DIR/alloc_error_handler_hook.rs:LL:CC:
alloc error hook called
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
yes we are unwinding!
18 changes: 2 additions & 16 deletions tests/panic/alloc_error_handler_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,6 @@
#![feature(allocator_api)]

use std::alloc::*;
use std::ptr::NonNull;

struct BadAlloc;

// Create a failing allocator; Miri's native allocator never fails so this is the only way to
// actually call the alloc error handler.
unsafe impl Allocator for BadAlloc {
fn allocate(&self, _l: Layout) -> Result<NonNull<[u8]>, AllocError> {
Err(AllocError)
}

unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
unreachable!();
}
}

struct Bomb;
impl Drop for Bomb {
Expand All @@ -25,8 +10,9 @@ impl Drop for Bomb {
}
}

#[allow(unreachable_code, unused_variables)]
fn main() {
let bomb = Bomb;
let _b = Box::new_in(0, BadAlloc);
handle_alloc_error(Layout::for_value(&0));
std::mem::forget(bomb); // defuse unwinding bomb
}
22 changes: 3 additions & 19 deletions tests/pass/no_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,14 @@
#![feature(start)]
#![no_std]

// Plumbing to let us use `writeln!` to host stdout:

extern "Rust" {
fn miri_write_to_stdout(bytes: &[u8]);
}

struct Host;

use core::fmt::Write;

impl Write for Host {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
unsafe {
miri_write_to_stdout(s.as_bytes());
}
Ok(())
}
}

// Aaaand the test:
#[path = "../utils/mod.no_std.rs"]
mod utils;

#[start]
fn start(_: isize, _: *const *const u8) -> isize {
writeln!(Host, "hello, world!").unwrap();
writeln!(utils::MiriStdout, "hello, world!").unwrap();
0
}

Expand Down
5 changes: 2 additions & 3 deletions tests/pass/tree_borrows/reserved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ fn main() {
}
}

unsafe fn print(msg: &str) {
utils::miri_write_to_stderr(msg.as_bytes());
utils::miri_write_to_stderr("\n".as_bytes());
fn print(msg: &str) {
eprintln!("{msg}");
}

unsafe fn read_second<T>(x: &mut T, y: *mut u8) {
Expand Down
25 changes: 25 additions & 0 deletions tests/utils/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use core::fmt::{self, Write};

use super::miri_extern;

pub struct MiriStderr;

impl Write for MiriStderr {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
miri_extern::miri_write_to_stderr(s.as_bytes());
}
Ok(())
}
}

pub struct MiriStdout;

impl Write for MiriStdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
miri_extern::miri_write_to_stdout(s.as_bytes());
}
Ok(())
}
}
4 changes: 2 additions & 2 deletions tests/utils/miri_extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ extern "Rust" {
/// with a null terminator.
/// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
pub fn miri_host_to_target_path(
path: *const std::ffi::c_char,
out: *mut std::ffi::c_char,
path: *const core::ffi::c_char,
out: *mut core::ffi::c_char,
out_size: usize,
) -> usize;

Expand Down
Loading
Loading