Skip to content
Open
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
36 changes: 36 additions & 0 deletions crates/spacewasm_util/tests/page_null.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//! A page allocation that fails must be reported as an error, not handed back as
//! a successful allocation based at address zero.
//!
//! This rests on the real system allocator returning NULL, which Miri does not
//! model, so it is excluded there like the other integration tests.
#![cfg(not(miri))]

use spacewasm::{Allocator, PageAllocator};
use spacewasm_util::RustSystemAllocator;
use std::alloc::Layout;

/// Under `isize::MAX` so `Layout` accepts it, but far beyond the address space of
/// either pointer width, so the request cannot be satisfied and the system
/// allocator returns NULL.
const UNSATISFIABLE_PAGE: usize = 1usize << (usize::BITS - 2);

#[test]
fn failed_page_allocation_is_reported_as_an_error() {
let page_layout = Layout::from_size_align(UNSATISFIABLE_PAGE, 8).unwrap();

// Guard against a platform that somehow satisfies the request: without a real
// failure there is nothing to observe, so leave rather than assert.
let probe = unsafe { std::alloc::alloc(page_layout) };
if !probe.is_null() {
unsafe { std::alloc::dealloc(probe, page_layout) };
eprintln!("skipped: the system satisfied a {UNSATISFIABLE_PAGE:#x} byte request");
return;
}

let page_alloc: PageAllocator<RustSystemAllocator, 4> =
PageAllocator::new(RustSystemAllocator, UNSATISFIABLE_PAGE);

if let Ok(ptr) = unsafe { page_alloc.alloc(Layout::from_size_align(16, 8).unwrap()) } {
panic!("reported success with {ptr:p} after the page could not be allocated");
}
}
7 changes: 6 additions & 1 deletion tests/util/spectest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,12 @@ unsafe impl Allocator for SpecTestAllocator {
AllocPhase::Loading { freed: false } | AllocPhase::Unchecked => {}
});

unsafe { Ok(std::alloc::alloc(layout)) }
let ptr = unsafe { std::alloc::alloc(layout) };
if ptr.is_null() {
Err(AllocError::AllocationFailed)
} else {
Ok(ptr)
}
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
Expand Down