alloc_error_handler tests: directly call handle_alloc_error; test more codepaths

This commit is contained in:
Ralf Jung 2024-04-17 09:25:26 +02:00
parent 8ad72b24f3
commit d10f61313f
9 changed files with 122 additions and 75 deletions

View file

@ -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));
}

View file

@ -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

View file

@ -0,0 +1,52 @@
//@compile-flags: -Cpanic=abort
#![feature(start, core_intrinsics)]
#![feature(alloc_error_handler)]
#![feature(allocator_api)]
#![no_std]
extern crate alloc;
use alloc::alloc::*;
extern "Rust" {
fn miri_write_to_stderr(bytes: &[u8]);
}
#[alloc_error_handler]
fn alloc_error_handler(_: Layout) -> ! {
let msg = "custom alloc error handler called!\n";
unsafe { miri_write_to_stderr(msg.as_bytes()) };
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) -> ! {
let msg = "custom panic handler called!\n";
unsafe { miri_write_to_stderr(msg.as_bytes()) };
core::intrinsics::abort();
}
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));
}

View file

@ -0,0 +1,27 @@
custom alloc error handler called!
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) -> ! {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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

View file

@ -7,28 +7,16 @@
extern crate alloc;
use alloc::alloc::*;
use alloc::boxed::Box;
use core::ptr::NonNull;
struct BadAlloc;
// 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!();
}
extern "Rust" {
fn miri_write_to_stderr(bytes: &[u8]);
}
#[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";
// The default no_std alloc_error_handler is a panic.
#[panic_handler]
fn panic_handler(_panic_info: &core::panic::PanicInfo) -> ! {
let msg = "custom panic handler called!\n";
unsafe { miri_write_to_stderr(msg.as_bytes()) };
core::intrinsics::abort(); //~ERROR: aborted
}
@ -37,11 +25,6 @@ fn alloc_error_handler(_: Layout) -> ! {
mod plumbing {
use super::*;
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
core::intrinsics::abort();
}
struct NoAlloc;
unsafe impl GlobalAlloc for NoAlloc {
@ -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));
}

View file

@ -1,4 +1,4 @@
custom alloc error handler called!
custom panic handler called!
error: abnormal termination: the program aborted execution
--> $DIR/alloc_error_handler_no_std.rs:LL:CC
|
@ -6,24 +6,17 @@ 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

View file

@ -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
}

View file

@ -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!

View file

@ -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 {
@ -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
}