summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-03-16 12:01:26 -0700
committerGitHub <noreply@github.com>2021-03-16 12:01:26 -0700
commit661ae32122f9f0ba70b03b2d76a41274ce5e4bb2 (patch)
tree9aab38236630e923b9d2fa7acaf70dae0d1c0415
parent5fea332e1e6cf2b00334b617bb1bf399e9394592 (diff)
downloadbinaryen-661ae32122f9f0ba70b03b2d76a41274ce5e4bb2.tar.gz
binaryen-661ae32122f9f0ba70b03b2d76a41274ce5e4bb2.tar.bz2
binaryen-661ae32122f9f0ba70b03b2d76a41274ce5e4bb2.zip
Validate code in global data structures (#3694)
This validation is almost never needed, but it starts to get interesting with GC, where a global initializer can be an rtt.sub which must be valid. No tests here as testing requires a further GC fix in a later PR.
-rw-r--r--src/wasm/wasm-validator.cpp17
1 files changed, 14 insertions, 3 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 80b7eb874..a057f34b9 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -201,13 +201,21 @@ struct ValidationInfo {
struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> {
bool isFunctionParallel() override { return true; }
- Pass* create() override { return new FunctionValidator(&info); }
+ Pass* create() override { return new FunctionValidator(*getModule(), &info); }
bool modifiesBinaryenIR() override { return false; }
ValidationInfo& info;
- FunctionValidator(ValidationInfo* info) : info(*info) {}
+ FunctionValidator(Module& wasm, ValidationInfo* info) : info(*info) {
+ setModule(&wasm);
+ }
+
+ // Validate the entire module.
+ void validate(PassRunner* runner) { run(runner, getModule()); }
+
+ // Validate a specific expression.
+ void validate(Expression* curr) { walk(curr); }
std::unordered_map<Name, std::unordered_set<Type>> breakTypes;
std::unordered_set<Name> delegateTargetNames;
@@ -2710,6 +2718,7 @@ static void validateGlobals(Module& module, ValidationInfo& info) {
!info.quiet) {
info.getStream(nullptr) << "(on global " << curr->name << ")\n";
}
+ FunctionValidator(module, &info).validate(curr->init);
});
}
@@ -2775,6 +2784,7 @@ static void validateMemory(Module& module, ValidationInfo& info) {
segment.data.size(),
"segment size should fit in memory (end)");
}
+ FunctionValidator(module, &info).validate(segment.offset);
}
// If the memory is imported we don't actually know its initial size.
// Specifically wasm dll's import a zero sized memory which is perfectly
@@ -2809,6 +2819,7 @@ static void validateTables(Module& module, ValidationInfo& info) {
table->initial * Table::kPageSize),
segment->offset,
"table segment offset should be reasonable");
+ FunctionValidator(module, &info).validate(segment->offset);
}
for (auto name : segment->data) {
info.shouldBeTrue(
@@ -2879,7 +2890,7 @@ bool WasmValidator::validate(Module& module, Flags flags) {
info.quiet = (flags & Quiet) != 0;
// parallel wasm logic validation
PassRunner runner(&module);
- FunctionValidator(&info).run(&runner, &module);
+ FunctionValidator(module, &info).validate(&runner);
// validate globally
if (info.validateGlobally) {
validateImports(module, info);