fix(wasmguest): frame empty InvokeResponse as (ptr,0), not packed 0
A successful hook whose response message has no set fields (LoadResponse, UnloadResponse) proto-marshals to zero bytes. bn_invoke's `len==0 → return 0` shortcut collided with the "callee could not produce an envelope" sentinel, so every successful empty-response hook — notably HOOK_LOAD — looked like an INTERNAL failure and got the instance discarded. Frame the empty case as (ptr, 0) with a real 1-byte-backed pointer instead; the host reads zero bytes into a valid empty InvokeResponse. Surfaced by the WO-WZ-003 end-to-end capability test (first exercise of LOAD). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
dc621e6d96
commit
5f4fa9db0f
@ -77,10 +77,19 @@ func bnInvoke(hookID uint32, ptr uint32, length uint32) uint64 {
|
||||
// bn_invoke returns). Release it whether or not the host calls bn_free.
|
||||
delete(pinned, ptr)
|
||||
|
||||
lastResponse = resp
|
||||
// A logically-empty InvokeResponse (Error nil + empty payload — e.g.
|
||||
// LoadResponse/UnloadResponse) proto-marshals to ZERO bytes. That is a
|
||||
// valid success envelope, not the "couldn't produce an envelope" sentinel,
|
||||
// so frame it as (ptr, 0) with a real pointer. Returning packed 0 here
|
||||
// would make the host mistake every empty-response hook (notably a
|
||||
// successful LOAD) for an INTERNAL failure and discard the instance. A
|
||||
// 1-byte backing keeps the pointer valid while the reported length stays 0
|
||||
// (the host reads zero bytes → an empty InvokeResponse, which is correct).
|
||||
if len(resp) == 0 {
|
||||
return 0
|
||||
lastResponse = []byte{0}
|
||||
return uint64(bufPtr(lastResponse)) << 32
|
||||
}
|
||||
lastResponse = resp
|
||||
return uint64(bufPtr(resp))<<32 | uint64(uint32(len(resp)))
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user