ladybird/Libraries/RustAllocator.rs
Andreas Kling 306060b448 LibJS: Add negative tests for the bytecode validator
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.
2026-05-03 08:43:19 +02:00

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()) }
}
}