RightNow-AI/openfang · error · SandboxError
host_call: request out of bounds
Error message
host_call: request out of bounds
What it means
The WASM guest module called the host function openfang.host_call with a (request_ptr, request_len) pair whose byte range [ptr, ptr+len) extends past the end of the guest's linear memory. The host refuses to read out-of-bounds memory rather than trap or read garbage, so it fails the call with this error. It is a guest-side ABI/pointer bug surfaced through the host.
Source
Thrown at crates/openfang-runtime/src/sandbox.rs:307
linker
.func_wrap(
"openfang",
"host_call",
|mut caller: Caller<'_, GuestState>,
request_ptr: i32,
request_len: i32|
-> Result<i64, Error> {
// Read request from guest memory
let memory = caller
.get_export("memory")
.and_then(|e| e.into_memory())
.ok_or_else(|| format_err!("no memory export"))?;
let data = memory.data(&caller);
let start = request_ptr as usize;
let end = start + request_len as usize;
if end > data.len() {
bail!("host_call: request out of bounds");
}
let request_bytes = data[start..end].to_vec();
// Parse request
let request: serde_json::Value = serde_json::from_slice(&request_bytes)?;
let method = request
.get("method")
.and_then(|m| m.as_str())
.unwrap_or("")
.to_string();
let params = request
.get("params")
.cloned()
.unwrap_or(serde_json::Value::Null);
// Dispatch to capability-checked handler
let response = host_functions::dispatch(caller.data(), &method, ¶ms);
View on GitHub (pinned to acf2587e46)
Solutions
- Fix the guest code so the pointer/length describe a valid in-bounds region: verify ptr and len are the exact values returned by the guest alloc call for the serialized request buffer
- Check that request_len is a byte length (use the serialized JSON's len(), not an element count) and that the buffer was not freed or overwritten before calling host_call
- Ensure the guest module exports a 'memory' export whose size actually covers the buffer (call memory.grow if needed before writing)
- Add a guest-side bounds assertion (ptr + len <= memory size) before invoking host_call so the failure is caught inside the module with better diagnostics
- Rebuild the guest to the current openfang guest ABI and re-run; stale prebuilt .wasm binaries often carry old struct layouts
Example fix
// before (guest Rust, len in elements)
let ptr = alloc(request.len() as i32);
host_call(ptr as i32, request.len() as i32);
// after (len in bytes of the serialized buffer)
let bytes = serde_json::to_vec(&request).unwrap();
let ptr = alloc(bytes.len() as i32);
unsafe { core::slice::from_raw_parts_mut(ptr as *mut u8, bytes.len()) }.copy_from_slice(&bytes);
host_call(ptr as i32, bytes.len() as i32); Defensive patterns
Strategy: try-catch
Validate before calling
// guest-side, before calling host_call let mem_size = memory.size(&store) as usize * 65536; let (start, len) = (request_ptr as usize, request_len as usize); assert!(start.checked_add(len).is_some() && start + len <= mem_size, "request buffer out of bounds");
Type guard
fn in_bounds(ptr: i32, len: i32, mem_len: usize) -> bool {
ptr >= 0 && len >= 0 && (ptr as u64) + (len as u64) <= mem_len as u64
} Try / catch
// guest module call, catch the trap/error from host_call
match sandbox.call(&input) {
Err(e) if e.to_string().contains("request out of bounds") => {
eprintln!("guest ABI bug: bad request_ptr/request_len: {e}");
// recompile/fix guest, do not retry blindly
}
r => r?,
} Prevention
- Always pass byte lengths (buf.len()), never element or char counts
- Use the allocator's returned pointer immediately; never cache pointers across allocations
- Assert ptr + len <= memory size in the guest before every host_call
- Pin the guest ABI version and rebuild guests whenever the host runtime changes
- Enable debug logging on the sandbox during development to surface pointer/length values
When it happens
Trigger: Calling host_call with a pointer or length computed incorrectly in the guest: wrong endianness or negative i32 cast to usize, a stale pointer into a region already freed/reclaimed by the guest allocator, an oversized request_len, or a guest module whose memory shrinks via memory.grow/replace semantics.
Common situations: Hand-written guest bindings in Rust/C/WASM modules; a custom allocator returning bogus pointers (e.g. forgetting to grow memory before alloc); passing a length in bytes vs elements; forgetting the 4GB usize cast wraps for negative pointers; guests built against a different ABI version than the host linker expects.
Related errors
AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02).
Data as JSON: /api/errors/7f4d2a166f388fa0.
Report an issue: GitHub.