test: P0-1 alloc OOB bounds check — failing test (#[ignore])

Guest alloc returning a pointer near the end of linear memory
(ptr + msg_len > memory_size) causes a Rust panic in copy_from_slice,
which poisons the actor permanently instead of dropping the message
and keeping the actor alive.

Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
Claude 2026-02-13 08:26:35 +00:00
parent b4312676a6
commit 22f6860d6d

View file

@ -277,6 +277,43 @@ fn handle_trap_drops_message_actor_survives() {
rt.tick();
}
// ── Bounds safety: alloc pointer near end of linear memory ────────────────────
#[test]
#[ignore] // BUG: actor.rs:44-46 has no bounds check — actor gets poisoned instead of surviving
fn alloc_near_end_of_memory_drops_message_actor_survives() {
// Guest alloc returns 65500 (near end of 1-page / 65536-byte memory).
// A 100-byte message means ptr+len = 65600, which exceeds memory bounds.
// The actor should drop the message and survive — same as any other
// allocation failure — rather than being permanently killed.
let wat = r#"
(module
(import "swactor" "send" (func $send (param i32 i32 i32)))
(memory (export "memory") 1)
(func (export "alloc") (param i32) (result i32)
i32.const 65500 ;; near end of 64KiB memory
)
(func (export "handle") (param i32 i32)
;; should never be reached if bounds check works
)
)
"#;
let wasm = wat::parse_str(wat).unwrap();
let engine = SharedEngine::new().unwrap();
let actor = WasmActorBuilder::new(engine, wasm).build().unwrap();
let rt = Runtime::new(RuntimeConfig::default());
let addr = rt.spawn(actor).unwrap();
// Send a message whose length exceeds the remaining space at ptr 65500
rt.send_to(addr, ByteMessage(vec![0u8; 100])).unwrap();
rt.tick();
// The actor should still be alive — send another message and tick without panic
rt.send_to(addr, ByteMessage(vec![1u8; 10])).unwrap();
rt.tick();
}
// ── Integration: WasmActor alongside a native Rust actor ─────────────────────
#[derive(Clone)]