From 532ff7e87a951ae40241833713eae963193e1f2d Mon Sep 17 00:00:00 2001 From: Yi LIU Date: Wed, 11 Feb 2026 18:27:25 +0800 Subject: [PATCH] Fix crash in interpreter when instantiating modules with imported globals instantiate() iterated all globals without checking imported(), causing ExpressionIterator to be constructed with a null init expression. This triggered an assertion failure in PostWalker::walk(). Skip imported globals during instantiation, matching the pattern used by walkModule(). --- src/interpreter/interpreter.cpp | 3 +++ test/gtest/interpreter.cpp | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/interpreter/interpreter.cpp b/src/interpreter/interpreter.cpp index 8007f011dcc..6c97c82f729 100644 --- a/src/interpreter/interpreter.cpp +++ b/src/interpreter/interpreter.cpp @@ -293,6 +293,9 @@ Result<> Interpreter::addInstance(std::shared_ptr wasm) { Result<> Interpreter::instantiate(Instance& instance) { for (auto& global : instance.wasm->globals) { + if (global->imported()) { + continue; + } store.callStack.emplace_back(instance, ExpressionIterator(global->init)); auto results = run(); assert(results.size() == 1); diff --git a/test/gtest/interpreter.cpp b/test/gtest/interpreter.cpp index ca1beb6c564..9008224ee31 100644 --- a/test/gtest/interpreter.cpp +++ b/test/gtest/interpreter.cpp @@ -943,6 +943,54 @@ TEST(InterpreterTest, GlobalI32) { EXPECT_EQ(results, expected); } +TEST(InterpreterTest, ImportedGlobalI32) { + auto wasm = std::make_shared(); + Builder builder(*wasm); + + auto importedGlobal = + builder.makeGlobal("g", Type::i32, nullptr, Builder::Immutable); + importedGlobal->module = "env"; + importedGlobal->base = "g"; + wasm->addGlobal(std::move(importedGlobal)); + + Interpreter interpreter; + auto result = interpreter.addInstance(wasm); + EXPECT_FALSE(result.getErr()); +} + +TEST(InterpreterTest, MixedImportedAndLocalGlobals) { + auto wasm = std::make_shared(); + Builder builder(*wasm); + IRBuilder irBuilder(*wasm); + + auto importedGlobal = + builder.makeGlobal("imported", Type::i32, nullptr, Builder::Immutable); + importedGlobal->module = "env"; + importedGlobal->base = "imported"; + wasm->addGlobal(std::move(importedGlobal)); + + wasm->addGlobal(builder.makeGlobal("local", + Type::i32, + builder.makeConst(Literal(int32_t(42))), + Builder::Mutable)); + + ASSERT_FALSE( + irBuilder.makeBlock(Name{}, Signature(Type::none, Type::i32)).getErr()); + ASSERT_FALSE(irBuilder.makeGlobalGet("local").getErr()); + ASSERT_FALSE(irBuilder.visitEnd().getErr()); + + auto expr = irBuilder.build(); + ASSERT_FALSE(expr.getErr()); + + Interpreter interpreter; + auto result = interpreter.addInstance(wasm); + ASSERT_FALSE(result.getErr()); + + auto results = interpreter.runTest(*expr); + std::vector expected{Literal(int32_t(42))}; + EXPECT_EQ(results, expected); +} + TEST(InterpreterTest, GlobalInitI32) { auto wasm = std::make_shared(); Builder builder(*wasm);