diff options
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 33e737ae1..e0391a73d 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -21,6 +21,7 @@ #include "ir/eh-utils.h" #include "ir/features.h" +#include "ir/find_all.h" #include "ir/global-utils.h" #include "ir/intrinsics.h" #include "ir/local-graph.h" @@ -3017,13 +3018,6 @@ void FunctionValidator::visitFunction(Function* curr) { } } -static bool checkSegmentOffset(Expression* curr, - Address add, - Address max, - FeatureSet features) { - return Properties::isValidInConstantExpression(curr, features); -} - void FunctionValidator::validateAlignment( size_t align, Type type, Index bytes, bool isAtomic, Expression* curr) { if (isAtomic) { @@ -3235,6 +3229,7 @@ static void validateExports(Module& module, ValidationInfo& info) { } static void validateGlobals(Module& module, ValidationInfo& info) { + std::unordered_set<Global*> seen; ModuleUtils::iterDefinedGlobals(module, [&](Global* curr) { info.shouldBeTrue(curr->type.getFeatures() <= module.features, curr->name, @@ -3242,10 +3237,9 @@ static void validateGlobals(Module& module, ValidationInfo& info) { info.shouldBeTrue( curr->init != nullptr, curr->name, "global init must be non-null"); assert(curr->init); - info.shouldBeTrue( - GlobalUtils::canInitializeGlobal(curr->init, module.features), - curr->name, - "global init must be valid"); + info.shouldBeTrue(GlobalUtils::canInitializeGlobal(module, curr->init), + curr->name, + "global init must be constant"); if (!info.shouldBeSubType(curr->init->type, curr->type, @@ -3255,6 +3249,18 @@ static void validateGlobals(Module& module, ValidationInfo& info) { info.getStream(nullptr) << "(on global " << curr->name << ")\n"; } FunctionValidator(module, &info).validate(curr->init); + // If GC is enabled (which means globals can refer to other non-imported + // globals), check that globals only refer to preceeding globals. + if (module.features.hasGC() && curr->init) { + for (auto* get : FindAll<GlobalGet>(curr->init).list) { + auto* global = module.getGlobalOrNull(get->name); + info.shouldBeTrue( + global && (seen.count(global) || global->imported()), + curr->init, + "global initializer should only refer to previous globals"); + } + seen.insert(curr); + } }); } @@ -3327,12 +3333,10 @@ static void validateDataSegments(Module& module, ValidationInfo& info) { continue; } } - info.shouldBeTrue(checkSegmentOffset(segment->offset, - segment->data.size(), - memory->initial * Memory::kPageSize, - module.features), - segment->offset, - "memory segment offset should be reasonable"); + info.shouldBeTrue( + Properties::isValidConstantExpression(module, segment->offset), + segment->offset, + "memory segment offset should be constant"); 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 @@ -3425,12 +3429,10 @@ static void validateTables(Module& module, ValidationInfo& info) { Type(Type::i32), segment->offset, "element segment offset should be i32"); - info.shouldBeTrue(checkSegmentOffset(segment->offset, - segment->data.size(), - table->initial * Table::kPageSize, - module.features), - segment->offset, - "table segment offset should be reasonable"); + info.shouldBeTrue( + Properties::isValidConstantExpression(module, segment->offset), + segment->offset, + "table segment offset should be constant"); info.shouldBeTrue( Type::isSubType(segment->type, table->type), "elem", @@ -3444,22 +3446,13 @@ static void validateTables(Module& module, ValidationInfo& info) { // Avoid double checking items if (module.features.hasReferenceTypes()) { for (auto* expr : segment->data) { - if (auto* globalExpr = expr->dynCast<GlobalGet>()) { - auto* global = module.getGlobal(globalExpr->name); - info.shouldBeFalse( - global->mutable_, expr, "expected a constant expression"); - } else { - info.shouldBeTrue(expr->is<RefFunc>() || expr->is<RefNull>() || - expr->is<GlobalGet>(), - expr, - "element segment items must be one of global.get, " - "ref.func, ref.null func"); - } + info.shouldBeTrue(Properties::isValidConstantExpression(module, expr), + expr, + "element must be a constant expression"); info.shouldBeSubType(expr->type, segment->type, expr, - "element segment item expressions must return a " - "subtype of the segment type"); + "element must be a subtype of the segment type"); validator.validate(expr); } } |