From 540c4a0bd91dba2bd8771031f6b5e9efd0d30832 Mon Sep 17 00:00:00 2001 From: Edman Anjos Date: Wed, 25 Dec 2024 23:58:54 +0100 Subject: [PATCH] fix: return proper nil on runtime.InstantiateModule errors (#2353) Previously InstantiateModule could return a (*wasm.ModuleInstance)(nil) instead of a proper nil value. So callers could get a nil dereference panic in code like: m, _ := r.InstantiateModule(...) if m != nil { // this check passes defer m.Close() // but this causes a panic } --- runtime.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/runtime.go b/runtime.go index 34742289eb..d6089f268f 100644 --- a/runtime.go +++ b/runtime.go @@ -9,7 +9,6 @@ import ( experimentalapi "github.com/tetratelabs/wazero/experimental" "github.com/tetratelabs/wazero/internal/expctxkeys" internalsock "github.com/tetratelabs/wazero/internal/sock" - internalsys "github.com/tetratelabs/wazero/internal/sys" "github.com/tetratelabs/wazero/internal/wasm" binaryformat "github.com/tetratelabs/wazero/internal/wasm/binary" "github.com/tetratelabs/wazero/sys" @@ -289,8 +288,8 @@ func (r *runtime) InstantiateModule( ctx context.Context, compiled CompiledModule, mConfig ModuleConfig, -) (mod api.Module, err error) { - if err = r.failIfClosed(); err != nil { +) (api.Module, error) { + if err := r.failIfClosed(); err != nil { return nil, err } @@ -304,9 +303,9 @@ func (r *runtime) InstantiateModule( } } - var sysCtx *internalsys.Context - if sysCtx, err = config.toSysContext(); err != nil { - return + sysCtx, err := config.toSysContext() + if err != nil { + return nil, err } name := config.name @@ -315,23 +314,23 @@ func (r *runtime) InstantiateModule( } // Instantiate the module. - mod, err = r.store.Instantiate(ctx, code.module, name, sysCtx, code.typeIDs) + mod, err := r.store.Instantiate(ctx, code.module, name, sysCtx, code.typeIDs) if err != nil { // If there was an error, don't leak the compiled module. if code.closeWithModule { _ = code.Close(ctx) // don't overwrite the error } - return + return nil, err } if closeNotifier, ok := ctx.Value(expctxkeys.CloseNotifierKey{}).(experimentalapi.CloseNotifier); ok { - mod.(*wasm.ModuleInstance).CloseNotifier = closeNotifier + mod.CloseNotifier = closeNotifier } // Attach the code closer so that anything afterward closes the compiled // code when closing the module. if code.closeWithModule { - mod.(*wasm.ModuleInstance).CodeCloser = code + mod.CodeCloser = code } // Now, invoke any start functions, failing at first error. @@ -340,20 +339,20 @@ func (r *runtime) InstantiateModule( if start == nil { continue } - if _, err = start.Call(ctx); err != nil { + if _, err := start.Call(ctx); err != nil { _ = mod.Close(ctx) // Don't leak the module on error. if se, ok := err.(*sys.ExitError); ok { if se.ExitCode() == 0 { // Don't err on success. - err = nil + return mod, nil } - return // Don't wrap an exit error + return nil, err // Don't wrap an exit error } err = fmt.Errorf("module[%s] function[%s] failed: %w", name, fn, err) - return + return nil, err } } - return + return mod, nil } // Close implements api.Closer embedded in Runtime.