Until now we had only confirmed that real, encoder-produced bytecode passes the validator. That tells us we don't false-fail, but says nothing about whether we actually catch a corrupted buffer. This commit fills that gap with a set of Rust unit tests that hand-craft minimal buffers and assert that each error category triggers exactly when expected. Coverage spans the three passes: unknown opcodes and truncated / misaligned instructions for the structural walk, operand and label out-of-range cases for the per-instruction checks, and basic block / exception handler / source map offsets for the structural metadata pass. There's also a pair of cache-pointer tests that pin the BeforeFixup vs AfterFixup behavior down: an out-of-range cache index is rejected before fixup and silently skipped after, because by then the slot holds a real pointer. To make `cargo test` work for the staticlib crate without dragging in the C++ allocator, RustAllocator falls back to the standard system allocator under cfg(test). The test harness only ever runs in cargo's test profile, so the production builds keep using the ladybird-side allocator unchanged.
41 lines
1.4 KiB
Rust
41 lines
1.4 KiB
Rust
/*
|
|
* Copyright (c) 2026-present, the Ladybird developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
// Under `cargo test`, fall back to the standard system allocator so that the
|
|
// crate's unit tests don't need to link against the C++ runtime.
|
|
#![cfg(not(test))]
|
|
|
|
use std::alloc::{GlobalAlloc, Layout};
|
|
|
|
unsafe extern "C" {
|
|
fn ladybird_rust_alloc(size: usize, alignment: usize) -> *mut u8;
|
|
fn ladybird_rust_alloc_zeroed(size: usize, alignment: usize) -> *mut u8;
|
|
fn ladybird_rust_dealloc(ptr: *mut u8, alignment: usize);
|
|
fn ladybird_rust_realloc(ptr: *mut u8, old_size: usize, new_size: usize, alignment: usize) -> *mut u8;
|
|
}
|
|
|
|
struct LadybirdAllocator;
|
|
|
|
#[global_allocator]
|
|
static LADYBIRD_ALLOCATOR: LadybirdAllocator = LadybirdAllocator;
|
|
|
|
unsafe impl GlobalAlloc for LadybirdAllocator {
|
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
|
unsafe { ladybird_rust_alloc(layout.size(), layout.align()) }
|
|
}
|
|
|
|
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
|
unsafe { ladybird_rust_alloc_zeroed(layout.size(), layout.align()) }
|
|
}
|
|
|
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
unsafe { ladybird_rust_dealloc(ptr, layout.align()) }
|
|
}
|
|
|
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
|
unsafe { ladybird_rust_realloc(ptr, layout.size(), new_size, layout.align()) }
|
|
}
|
|
}
|