runtime: give clear error when a wasmexport function is called before module initializationย #71240
Open
Description
Go version
go version go1.24rc1 linux/arm64
Output of go env
in your module/workspace:
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE='on'
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/.jbdevcontainer/go-build'
GODEBUG=''
GOENV='/.jbdevcontainer/config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3652802248=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/IdeaProjects/wasm-1-24/go.mod'
GOMODCACHE='/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/.jbdevcontainer/config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.24rc1'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
I'm trying to call simple wasm exported Go function from wasmtime
and wazero
runtimes.
wasm.go
GOOS=wasip1 GOARCH=wasm go build -o out.wasm -buildmode=c-shared ./wasm/
//go:build wasm
package main
import "fmt"
//go:wasmexport SuperFunction
func SuperFunction(x, y int32) int32 {
return x + y
} // OK
func main() {
}
wasmtime_main.go
package main
import (
"context"
_ "embed"
"fmt"
"log"
"os"
"unsafe"
"github.com/bytecodealliance/wasmtime-go"
)
func memoryLimit(megabytes uint32) uint32 {
const wazeroPageSize = 64
kilobytes := megabytes * 1024
return kilobytes / wazeroPageSize
}
//go:embed out.wasm
var wasmModule []byte
func main() {
// Almost all operations in wasmtime require a contextual `store`
// argument to share, so create that first
engine := wasmtime.NewEngine()
//store.SetWasi()
// Once we have our binary `wasm` we can compile that into a `*Module`
// which represents compiled JIT code.
module, err := wasmtime.NewModule(engine, wasmModule)
if err != nil {
log.Fatal(err)
}
// Create a linker with WASI functions defined within it
linker := wasmtime.NewLinker(engine)
err = linker.DefineWasi()
if err != nil {
log.Fatal(err)
}
// Configure WASI imports to write stdout into a file, and then create
// a `Store` using this wasi configuration.
wasiConfig := wasmtime.NewWasiConfig()
store := wasmtime.NewStore(engine)
store.SetWasi(wasiConfig)
instance, err := linker.Instantiate(store, module)
if err != nil {
log.Fatal(err)
}
// After we've instantiated we can lookup our `run` function and call
// it.
run := instance.GetFunc(store, "SuperFunction")
_, err = run.Call(store, 96, 55)
if err != nil {
log.Fatal(err)
}
}
wazero_main.go
package main
import (
"context"
_ "embed"
"fmt"
"log"
"os"
"unsafe"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)
func main() {
ctx := context.Background()
runtime := wazero.NewRuntimeWithConfig(
ctx,
wazero.
NewRuntimeConfig().
WithCoreFeatures(api.CoreFeaturesV2).
WithMemoryLimitPages(memoryLimit(256)),
)
_, err := wasi_snapshot_preview1.Instantiate(ctx, runtime)
if err != nil {
panic(err)
}
builder := runtime.NewHostModuleBuilder("env")
wasi_snapshot_preview1.NewFunctionExporter().ExportFunctions(builder)
_, err = builder.Instantiate(ctx)
if err != nil {
panic(err)
}
compiledModule, err := runtime.CompileModule(ctx, wasmModule)
if err != nil {
panic(fmt.Errorf("can't compile WASM module: %w", err))
}
mod, err := runtime.InstantiateModule(
ctx,
compiledModule,
wazero.
NewModuleConfig().
WithStdout(os.Stdout).
WithStderr(os.Stderr),
)
if err != nil {
panic(fmt.Errorf("can't instantiate module: %w", err))
}
funcName := "SuperFunction"
targetFunc := mod.ExportedFunction(funcName)
if targetFunc == nil {
panic(fmt.Errorf("target function not found: %s", funcName))
}
mod.Memory().Grow(2)
res, err := targetFunc.Call(ctx, 96, 55)
//res, err := targetFunc.Call(ctx)
fmt.Println(res, err)
fmt.Println(targetFunc.Definition().DebugName())
fmt.Println(targetFunc.Definition().Name())
fmt.Println(targetFunc.Definition().ParamTypes())
fmt.Println(targetFunc.Definition().ParamNames())
}
What did you see happen?
I got out of bounds memory access
on wazero
and wasmtime
runtime
What did you expect to see?
I expect function execution without any error.
Metadata
Assignees
Labels
Type
Projects
Status
No status