{"record":{"id":"02cb78a14e1da8f1","repo":"RightNow-AI/openfang","slug":"host-log-pointer-out-of-bounds","errorCode":null,"errorMessage":"host_log: pointer out of bounds","messagePattern":"host_log: pointer out of bounds","errorType":"validation","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"crates/openfang-runtime/src/sandbox.rs","lineNumber":376,"sourceCode":"        linker\n            .func_wrap(\n                \"openfang\",\n                \"host_log\",\n                |mut caller: Caller<'_, GuestState>,\n                 level: i32,\n                 msg_ptr: i32,\n                 msg_len: i32|\n                 -> Result<(), Error> {\n                    let memory = caller\n                        .get_export(\"memory\")\n                        .and_then(|e| e.into_memory())\n                        .ok_or_else(|| format_err!(\"no memory export\"))?;\n\n                    let data = memory.data(&caller);\n                    let start = msg_ptr as usize;\n                    let end = start + msg_len as usize;\n                    if end > data.len() {\n                        bail!(\"host_log: pointer out of bounds\");\n                    }\n                    let msg = std::str::from_utf8(&data[start..end]).unwrap_or(\"<invalid utf8>\");\n                    let agent_id = &caller.data().agent_id;\n\n                    match level {\n                        0 => tracing::trace!(agent = %agent_id, \"[wasm] {msg}\"),\n                        1 => tracing::debug!(agent = %agent_id, \"[wasm] {msg}\"),\n                        2 => tracing::info!(agent = %agent_id, \"[wasm] {msg}\"),\n                        3 => tracing::warn!(agent = %agent_id, \"[wasm] {msg}\"),\n                        _ => tracing::error!(agent = %agent_id, \"[wasm] {msg}\"),\n                    }\n                    Ok(())\n                },\n            )\n            .map_err(|e| SandboxError::Compilation(e.to_string()))?;\n\n        Ok(())\n    }","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/sandbox.rs#L358-L394","documentation":"The guest module called openfang.host_log with (msg_ptr, msg_len) whose byte range falls outside the guest's linear memory. Since host_log requires no capability check, this bounds check is the main safety gate; the host rejects the call rather than reading invalid memory. Like the host_call bounds error, it points at a guest-side pointer/length bug.","triggerScenarios":"Logging a string whose pointer or length is computed incorrectly (length in chars/elements instead of bytes, off-by-one on the NUL terminator, stale pointer after reallocation), negative i32 pointer, or logging from a buffer allocated by a buggy guest allocator.","commonSituations":"Passing C strings with strlen computed after moving the buffer; logging a slice of a vector that was freed; guests written in C where char is fine but the wasm32 pointer was truncated; formatting macros writing a longer message than the reserved buffer.","solutions":["Ensure msg_ptr/msg_len reference a live in-bounds byte buffer: compute msg_len with .len() in bytes on the exact slice you wrote to guest memory","Verify the buffer was not freed or reallocated between writing it and calling host_log","Check the pointer/length are i32-safe (no negatives, no overflow when cast to usize inside the host)","If using a helper library for host logging, update it to the current openfang ABI version","Temporarily log via a fixed-size static buffer in the guest to isolate whether the allocator or the length computation is at fault"],"exampleFix":"// before (guest)\nlet msg = \"agent started\";\nhost_log(2, msg.as_ptr() as i32, msg.chars().count() as i32);\n// after\nlet msg = b\"agent started\";\nhost_log(2, msg.as_ptr() as i32, msg.len() as i32);","handlingStrategy":"validation","validationCode":"// guest-side, before calling host_log\nlet mem_size = memory.size() * 65536;\nassert!(msg_ptr >= 0 && msg_len >= 0 && (msg_ptr as usize) + (msg_len as usize) <= mem_size, \"log buffer out of bounds\");","typeGuard":"fn log_slice_ok(ptr: i32, len: i32, mem_len: usize) -> bool {\n    ptr >= 0 && len >= 0 && (ptr as u64) + (len as u64) <= mem_len as u64\n}","tryCatchPattern":"match sandbox.call(&input) {\n    Err(e) if e.to_string().contains(\"host_log: pointer out of bounds\") => {\n        eprintln!(\"guest logging bug: bad msg_ptr/msg_len: {e}\");\n        Err(e)\n    }\n    other => other,\n}","preventionTips":["Compute log message lengths in bytes with .len() on a byte slice, not chars().count()","Write the log message into guest memory immediately before calling host_log","Wrap host_log in a guest-side helper that does the bounds check once","Never log from freed or reallocated buffers","Keep log messages within a fixed, bounded buffer size"],"tags":["wasm","wasmtime","logging","memory-bounds"],"backgroundTag":"wasm-guest-memory-out-of-bounds","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}