From 9b79c7e14f59b70c75dad86e3992a6bc1ac9d243 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 | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/runtime.go b/runtime.go index 34742289eb..4a5d0668be 100644 --- a/runtime.go +++ b/runtime.go @@ -289,8 +289,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 } @@ -305,8 +305,9 @@ func (r *runtime) InstantiateModule( } var sysCtx *internalsys.Context + var err error if sysCtx, err = config.toSysContext(); err != nil { - return + return nil, err } name := config.name @@ -315,23 +316,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 +341,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.