wasmtime-go icon indicating copy to clipboard operation
wasmtime-go copied to clipboard

Panic in FuncWrap with *Caller causes nil pointer dereference

Open alterstep opened this issue 2 months ago • 1 comments

When a host function defined using linker.FuncWrap() with a *Caller parameter panics, wasmtime-go crashes with a nil pointer dereference in func.go instead of properly propagating the panic.

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x28 pc=0x...]

goroutine 1 [running]:
github.com/bytecodealliance/wasmtime-go/v37.enterWasm(...)
        github.com/bytecodealliance/wasmtime-go/[email protected]/func.go:539

Or in some cases, the panic occurs at line 539 but with the original panic message rather than being properly handled.

The code attempts to access data.lastPanic where data is returned from getDataInStore(store):

if data.lastPanic != nil {
    lastPanic := data.lastPanic  // line 537
    data.lastPanic = nil
    panic(lastPanic)              // line 539
}

When a panic occurs in a FuncWrap function with a *Caller parameter, getDataInStore(store) returns nil, causing a nil pointer dereference when attempting to access data.lastPanic.

Simple host function definition that reproduces the bug:

linker := wasmtime.NewLinker(engine)
err := linker.FuncWrap("env", "host_panic", func(caller *wasmtime.Caller) int32
 {
    panic("some error") // This panic triggers the bug
})

WAT:

(module
  ;; Import host function that will panic
  (import "env" "host_panic" (func $host_panic (result i32)))

  ;; Export a test function that calls the host function
  (func (export "test") (result i32)
    ;; Call the host function that will panic
    call $host_panic
  )
)

This bug makes it impossible to use Go's standard panic/recover mechanism for error handling in host functions when using wasmtime-go with the *Caller parameter.

Maybe the code should check if data is nil before dereferencing:

data := getDataInStore(store)
if data != nil && data.lastPanic != nil {
    lastPanic := data.lastPanic
    data.lastPanic = nil
    panic(lastPanic)
}

alterstep avatar Oct 15 '25 06:10 alterstep

Given the passing tests on https://github.com/bytecodealliance/wasmtime-go/pull/257 I don't think it's as simple as "panic in FuncWrap is the issue". Can you provide a more complete reproduction?

alexcrichton avatar Oct 15 '25 15:10 alexcrichton