diff options
-rw-r--r-- | scripts/test/shared.py | 3 | ||||
-rw-r--r-- | src/parser/wast-parser.cpp | 2 | ||||
-rw-r--r-- | src/wasm-binary.h | 2 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 33 | ||||
-rw-r--r-- | test/spec/binary.wast | 191 |
5 files changed, 26 insertions, 205 deletions
diff --git a/scripts/test/shared.py b/scripts/test/shared.py index 0e7062437..665ad6b7c 100644 --- a/scripts/test/shared.py +++ b/scripts/test/shared.py @@ -417,9 +417,6 @@ SPEC_TESTS_TO_SKIP = [ 'type.wast', 'unreached-invalid.wast', - # WAST parser error - 'binary.wast', - # Test invalid 'elem.wast', ] diff --git a/src/parser/wast-parser.cpp b/src/parser/wast-parser.cpp index 9473da9fb..137ef0df1 100644 --- a/src/parser/wast-parser.cpp +++ b/src/parser/wast-parser.cpp @@ -77,6 +77,8 @@ Result<WASTModule> wastModule(Lexer& in, bool maybeInvalid = false) { if (!in.takeSExprStart("module"sv)) { return in.err("expected module"); } + // TODO: use ID? + [[maybe_unused]] auto id = in.takeID(); QuotedModuleType type; if (in.takeKeyword("quote"sv)) { type = QuotedModuleType::Text; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index f7d57f5c9..3870ccf7f 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1583,7 +1583,7 @@ public: void readVars(); std::map<Export*, Index> exportIndices; - std::vector<Export*> exportOrder; + std::vector<std::unique_ptr<Export>> exportOrder; void readExports(); // The strings in the strings section (which are referred to by StringConst). diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 524f4b98c..01b3602eb 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -23,6 +23,7 @@ #include "ir/type-updating.h" #include "support/bits.h" #include "support/debug.h" +#include "support/stdckdint.h" #include "support/string.h" #include "wasm-binary.h" #include "wasm-debug.h" @@ -2688,10 +2689,10 @@ void WasmBinaryReader::readFunctions() { } endOfFunction = pos + size; - auto* func = new Function; + auto func = std::make_unique<Function>(); func->name = Name::fromInt(i); func->type = getTypeByFunctionIndex(numImports + i); - currFunction = func; + currFunction = func.get(); if (DWARF) { func->funcLocation = BinaryLocations::FunctionLocations{ @@ -2755,21 +2756,29 @@ void WasmBinaryReader::readFunctions() { } } - TypeUpdating::handleNonDefaultableLocals(func, wasm); + TypeUpdating::handleNonDefaultableLocals(func.get(), wasm); std::swap(func->epilogLocation, debugLocation); currFunction = nullptr; debugLocation.clear(); - wasm.addFunction(func); + wasm.addFunction(std::move(func)); } BYN_TRACE(" end function bodies\n"); } void WasmBinaryReader::readVars() { + uint32_t totalVars = 0; size_t numLocalTypes = getU32LEB(); for (size_t t = 0; t < numLocalTypes; t++) { auto num = getU32LEB(); + // The core spec allows up to 2^32 locals, but to avoid allocation failures, + // we additionally impose a much smaller limit, matching the JS embedding. + if (std::ckd_add(&totalVars, totalVars, num) || + totalVars > WebLimitations::MaxFunctionLocals) { + throwError("too many locals"); + } auto type = getConcreteType(); + while (num > 0) { currFunction->vars.push_back(type); num--; @@ -2784,15 +2793,15 @@ void WasmBinaryReader::readExports() { std::unordered_set<Name> names; for (size_t i = 0; i < num; i++) { BYN_TRACE("read one\n"); - auto curr = new Export; + auto curr = std::make_unique<Export>(); curr->name = getInlineString(); if (!names.emplace(curr->name).second) { throwError("duplicate export name"); } curr->kind = (ExternalKind)getU32LEB(); auto index = getU32LEB(); - exportIndices[curr] = index; - exportOrder.push_back(curr); + exportIndices[curr.get()] = index; + exportOrder.push_back(std::move(curr)); } } @@ -3235,6 +3244,10 @@ void WasmBinaryReader::validateBinary() { if (hasDataCount && wasm.dataSegments.size() != dataCount) { throwError("Number of segments does not agree with DataCount section"); } + + if (functionTypes.size() != wasm.functions.size()) { + throwError("function section without code section"); + } } void WasmBinaryReader::processNames() { @@ -3244,8 +3257,8 @@ void WasmBinaryReader::processNames() { wasm.start = getFunctionName(startIndex); } - for (auto* curr : exportOrder) { - auto index = exportIndices[curr]; + for (auto& curr : exportOrder) { + auto index = exportIndices[curr.get()]; switch (curr->kind) { case ExternalKind::Function: { curr->value = getFunctionName(index); @@ -3266,7 +3279,7 @@ void WasmBinaryReader::processNames() { default: throwError("bad export kind"); } - wasm.addExport(curr); + wasm.addExport(std::move(curr)); } for (auto& [index, refs] : functionRefs) { diff --git a/test/spec/binary.wast b/test/spec/binary.wast index e748bbe8c..e7bca9b11 100644 --- a/test/spec/binary.wast +++ b/test/spec/binary.wast @@ -138,197 +138,6 @@ "zero flag expected" ) -;; memory.grow reserved byte equal to zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\09\01" ;; Code section - - ;; function 0 - "\07\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\01" ;; memory.grow reserved byte is not equal to zero! - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; memory.grow reserved byte should not be a "long" LEB128 zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0a\01" ;; Code section - - ;; function 0 - "\08\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; Same as above for 3, 4, and 5-byte zero encodings. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0b\01" ;; Code section - - ;; function 0 - "\09\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0c\01" ;; Code section - - ;; function 0 - "\0a\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\80\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0d\01" ;; Code section - - ;; function 0 - "\0b\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\80\80\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; memory.size reserved byte equal to zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\07\01" ;; Code section - - ;; function 0 - "\05\00" - "\3f" ;; memory.size - "\01" ;; memory.size reserved byte is not equal to zero! - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; memory.size reserved byte should not be a "long" LEB128 zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\08\01" ;; Code section - - ;; function 0 - "\06\00" - "\3f" ;; memory.size - "\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; Same as above for 3, 4, and 5-byte zero encodings. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\09\01" ;; Code section - - ;; function 0 - "\07\00" - "\3f" ;; memory.size - "\80\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0a\01" ;; Code section - - ;; function 0 - "\08\00" - "\3f" ;; memory.size - "\80\80\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0b\01" ;; Code section - - ;; function 0 - "\09\00" - "\3f" ;; memory.size - "\80\80\80\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - ;; No more than 2^32 locals. (assert_malformed (module binary |