Skip to content

Commit 986e7cb

Browse files
Revert "Stub out all imports in ctor-eval" (#8137)
Reverts #8115 This causes the fuzzer to fail when an import is repeated: #8115 (comment). Will revert and re-introduce this later with a fix.
1 parent acd28ee commit 986e7cb

File tree

3 files changed

+68
-90
lines changed

3 files changed

+68
-90
lines changed

src/tools/wasm-ctor-eval.cpp

Lines changed: 60 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -115,79 +115,63 @@ class EvallingModuleRunner : public ModuleRunnerBase<EvallingModuleRunner> {
115115
}
116116
};
117117

118-
// Build artificial modules based on a module's imports, so that the
118+
// Build an artificial `env` module based on a module's imports, so that the
119119
// interpreter can use correct object instances. It initializes usable global
120120
// imports, and fills the rest with fake values since those are dangerous to
121-
// use. Imported globals can't be read anyway; see
122-
// `EvallingModuleRunner::visitGlobalGet`.
123-
// Note: wasi_ modules have stubs generated but won't be called due to the
124-
// special handling in `CtorEvalExternalInterface::getImportedFunction`. We
125-
// still generate the stubs to ensure the link-time validation passes.
126-
std::vector<std::unique_ptr<Module>> buildStubModules(Module& wasm) {
127-
std::map<Name, std::unique_ptr<Module>> modules;
128-
129-
ModuleUtils::iterImports(
130-
wasm,
131-
[&modules](std::variant<Memory*, Table*, Global*, Function*, Tag*> import) {
132-
Importable* importable =
133-
std::visit([](auto* i) -> Importable* { return i; }, import);
134-
135-
auto [it, inserted] = modules.try_emplace(importable->module, nullptr);
136-
if (inserted) {
137-
it->second = std::make_unique<Module>();
138-
it->second->name = importable->module;
139-
}
140-
Module* module = it->second.get();
141-
142-
struct Visitor {
143-
Module* module;
144-
void operator()(Memory* memory) {
145-
auto* copied = ModuleUtils::copyMemory(memory, *module);
146-
copied->module = Name();
147-
copied->base = Name();
148-
module->addExport(Builder(*module).makeExport(
149-
memory->base, copied->name, ExternalKind::Memory));
150-
}
151-
void operator()(Table* table) {
152-
// create tables with similar initial and max values
153-
auto* copied = ModuleUtils::copyTable(table, *module);
154-
copied->module = Name();
155-
copied->base = Name();
156-
module->addExport(Builder(*module).makeExport(
157-
table->base, copied->name, ExternalKind::Table));
158-
}
159-
void operator()(Global* global) {
160-
auto* copied = ModuleUtils::copyGlobal(global, *module);
161-
copied->module = Name();
162-
copied->base = Name();
163-
164-
Builder builder(*module);
165-
copied->init = builder.makeConst(Literal::makeZero(global->type));
166-
module->addExport(builder.makeExport(
167-
global->base, copied->name, ExternalKind::Global));
168-
}
169-
void operator()(Function* func) {
170-
Builder builder(*module);
171-
auto* copied = ModuleUtils::copyFunction(func, *module);
172-
copied->module = Name();
173-
copied->base = Name();
174-
copied->body = builder.makeUnreachable();
175-
module->addExport(builder.makeExport(
176-
func->base, copied->name, ExternalKind::Function));
177-
}
178-
void operator()(Tag* tag) {
179-
// no-op
180-
}
181-
};
182-
std::visit(Visitor{module}, import);
183-
});
121+
// use. we will fail if dangerous globals are used.
122+
std::unique_ptr<Module> buildEnvModule(Module& wasm) {
123+
auto env = std::make_unique<Module>();
124+
env->name = "env";
125+
126+
// create empty functions with similar signature
127+
ModuleUtils::iterImportedFunctions(wasm, [&](Function* func) {
128+
if (func->module == env->name) {
129+
Builder builder(*env);
130+
auto* copied = ModuleUtils::copyFunction(func, *env);
131+
copied->module = Name();
132+
copied->base = Name();
133+
copied->body = builder.makeUnreachable();
134+
env->addExport(
135+
builder.makeExport(func->base, copied->name, ExternalKind::Function));
136+
}
137+
});
138+
139+
// create tables with similar initial and max values
140+
ModuleUtils::iterImportedTables(wasm, [&](Table* table) {
141+
if (table->module == env->name) {
142+
auto* copied = ModuleUtils::copyTable(table, *env);
143+
copied->module = Name();
144+
copied->base = Name();
145+
env->addExport(Builder(*env).makeExport(
146+
table->base, copied->name, ExternalKind::Table));
147+
}
148+
});
149+
150+
ModuleUtils::iterImportedGlobals(wasm, [&](Global* global) {
151+
if (global->module == env->name) {
152+
auto* copied = ModuleUtils::copyGlobal(global, *env);
153+
copied->module = Name();
154+
copied->base = Name();
155+
156+
Builder builder(*env);
157+
copied->init = builder.makeConst(Literal::makeZero(global->type));
158+
env->addExport(
159+
builder.makeExport(global->base, copied->name, ExternalKind::Global));
160+
}
161+
});
162+
163+
// create an exported memory with the same initial and max size
164+
ModuleUtils::iterImportedMemories(wasm, [&](Memory* memory) {
165+
if (memory->module == env->name) {
166+
auto* copied = ModuleUtils::copyMemory(memory, *env);
167+
copied->module = Name();
168+
copied->base = Name();
169+
env->addExport(Builder(*env).makeExport(
170+
memory->base, copied->name, ExternalKind::Memory));
171+
}
172+
});
184173

185-
std::vector<std::unique_ptr<Module>> modulesVector;
186-
modulesVector.reserve(modules.size());
187-
for (auto& [_, ptr] : modules) {
188-
modulesVector.push_back(std::move(ptr));
189-
}
190-
return modulesVector;
174+
return env;
191175
}
192176

193177
// Whether to ignore external input to the program as it runs. If set, we will
@@ -1372,16 +1356,12 @@ void evalCtors(Module& wasm,
13721356

13731357
std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances;
13741358

1375-
// stubModules and interfaces must be kept alive since they are referenced in
1376-
// linkedInstances.
1377-
std::vector<std::unique_ptr<Module>> stubModules = buildStubModules(wasm);
1378-
std::vector<std::unique_ptr<CtorEvalExternalInterface>> interfaces;
1379-
1380-
for (auto& module : stubModules) {
1381-
interfaces.push_back(std::make_unique<CtorEvalExternalInterface>());
1382-
linkedInstances[module->name] =
1383-
std::make_shared<EvallingModuleRunner>(*module, interfaces.back().get());
1384-
}
1359+
// build and link the env module
1360+
auto envModule = buildEnvModule(wasm);
1361+
CtorEvalExternalInterface envInterface;
1362+
auto envInstance =
1363+
std::make_shared<EvallingModuleRunner>(*envModule, &envInterface);
1364+
linkedInstances[envModule->name] = envInstance;
13851365

13861366
CtorEvalExternalInterface interface(linkedInstances);
13871367
try {
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
(module
22
(import "import" "global" (global $imported i32))
3-
(func $use-global (export "use-global") (result i32)
4-
(global.get $imported)
3+
(func $test1 (export "test1")
4+
;; This should be safe to eval in theory, but the imported global stops us,
5+
;; so this function will not be optimized out.
6+
;; TODO: perhaps if we never use that global that is ok?
57
)
6-
;; The imported global isn't used in the ctor,
7-
;; so we're free to remove it completely.
8-
(func $test1 (export "test1"))
98
)
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
(module
2-
(type $0 (func (result i32)))
3-
(import "import" "global" (global $imported i32))
4-
(export "use-global" (func $use-global))
5-
(func $use-global (type $0) (result i32)
6-
(global.get $imported)
2+
(type $0 (func))
3+
(export "test1" (func $test1))
4+
(func $test1 (type $0)
5+
(nop)
76
)
87
)

0 commit comments

Comments
 (0)