bytecodealliance / bytecodealliance/wasmtime-go
Panic in FuncWrap with *Caller causes nil pointer dereference
- Dominant language
- Go
- Stars
- 913
- Forks
- 100
- Avg merge
- 10m
- Merged PRs (30d)
- 1
Description
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/v37@v37.0.0/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)`:
```go
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:
```go
linker := wasmtime.NewLinker(engine)
err := linker.FuncWrap("env", "host_panic", func(caller *wasmtime.Caller) int32
{
panic("some error") // This panic triggers the bug
})
```
WAT:
```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:
```go
data := getDataInStore(store)
if data != nil && data.lastPanic != nil {
lastPanic := data.lastPanic
data.lastPanic = nil
panic(lastPanic)
}
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.