| Index: src/wasm/module-decoder.cc
|
| diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc
|
| index 6d4b03666017261231039eee0c3b554a8d9843a6..2c5bea4869df21470b5f583af6c71ea22370c5d5 100644
|
| --- a/src/wasm/module-decoder.cc
|
| +++ b/src/wasm/module-decoder.cc
|
| @@ -51,7 +51,7 @@ class ModuleDecoder : public Decoder {
|
| module->mem_external = false;
|
| module->origin = origin_;
|
|
|
| - bool sections[kMaxModuleSectionCode] = {false};
|
| + bool sections[(size_t)WasmSection::Code::Max] = {false};
|
|
|
| const byte* pos = pc_;
|
| uint32_t magic_word = consume_u32("wasm magic");
|
| @@ -77,33 +77,48 @@ class ModuleDecoder : public Decoder {
|
| // Decode the module sections.
|
| while (pc_ < limit_) {
|
| TRACE("DecodeSection\n");
|
| - uint8_t section_u8 = consume_u8("section");
|
| + pos = pc_;
|
| +
|
| + int length;
|
| + uint32_t section_length = consume_u32v(&length, "section size");
|
| +
|
| + int section_string_leb_length = 0;
|
| + uint32_t section_string_length = 0;
|
| + WasmSection::Code section = consume_section_name(
|
| + §ion_string_leb_length, §ion_string_length);
|
| + uint32_t string_and_leb_length =
|
| + section_string_leb_length + section_string_length;
|
| + if (string_and_leb_length > section_length) {
|
| + error(pos, pos,
|
| + "section string of size %u longer than total section bytes %u",
|
| + string_and_leb_length, section_length);
|
| + break;
|
| + }
|
|
|
| - if (section_u8 >= kMaxModuleSectionCode) {
|
| + if (section == WasmSection::Code::Max) {
|
| // Skip unknown section.
|
| - int length;
|
| - uint32_t section_bytes = consume_u32v(&length, "section size");
|
| - consume_bytes(section_bytes);
|
| + uint32_t skip = section_length - string_and_leb_length;
|
| + TRACE("skipping %u bytes from unknown section\n", skip);
|
| + consume_bytes(skip);
|
| continue;
|
| }
|
|
|
| // Each section should appear at most once.
|
| - auto section = static_cast<WasmSectionDeclCode>(section_u8);
|
| CheckForPreviousSection(sections, section, false);
|
| - sections[section] = true;
|
| + sections[(size_t)section] = true;
|
|
|
| switch (section) {
|
| - case kDeclEnd:
|
| + case WasmSection::Code::End:
|
| // Terminate section decoding.
|
| limit_ = pc_;
|
| break;
|
| - case kDeclMemory:
|
| + case WasmSection::Code::Memory:
|
| int length;
|
| module->min_mem_pages = consume_u32v(&length, "min memory");
|
| module->max_mem_pages = consume_u32v(&length, "max memory");
|
| module->mem_export = consume_u8("export memory") != 0;
|
| break;
|
| - case kDeclSignatures: {
|
| + case WasmSection::Code::Signatures: {
|
| int length;
|
| uint32_t signatures_count = consume_u32v(&length, "signatures count");
|
| module->signatures.reserve(SafeReserve(signatures_count));
|
| @@ -117,9 +132,10 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclFunctionSignatures: {
|
| + case WasmSection::Code::FunctionSignatures: {
|
| // Functions require a signature table first.
|
| - CheckForPreviousSection(sections, kDeclSignatures, true);
|
| + CheckForPreviousSection(sections, WasmSection::Code::Signatures,
|
| + true);
|
| int length;
|
| uint32_t functions_count = consume_u32v(&length, "functions count");
|
| module->functions.reserve(SafeReserve(functions_count));
|
| @@ -131,9 +147,10 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclFunctionBodies: {
|
| + case WasmSection::Code::FunctionBodies: {
|
| // Function bodies should follow signatures.
|
| - CheckForPreviousSection(sections, kDeclFunctionSignatures, true);
|
| + CheckForPreviousSection(sections,
|
| + WasmSection::Code::FunctionSignatures, true);
|
| int length;
|
| const byte* pos = pc_;
|
| uint32_t functions_count = consume_u32v(&length, "functions count");
|
| @@ -159,9 +176,10 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclFunctions: {
|
| + case WasmSection::Code::Functions: {
|
| // Functions require a signature table first.
|
| - CheckForPreviousSection(sections, kDeclSignatures, true);
|
| + CheckForPreviousSection(sections, WasmSection::Code::Signatures,
|
| + true);
|
| int length;
|
| uint32_t functions_count = consume_u32v(&length, "functions count");
|
| module->functions.reserve(SafeReserve(functions_count));
|
| @@ -194,9 +212,10 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclNames: {
|
| + case WasmSection::Code::Names: {
|
| // Names correspond to functions.
|
| - CheckForPreviousSection(sections, kDeclFunctionSignatures, true);
|
| + CheckForPreviousSection(sections,
|
| + WasmSection::Code::FunctionSignatures, true);
|
| int length;
|
| const byte* pos = pc_;
|
| uint32_t functions_count = consume_u32v(&length, "functions count");
|
| @@ -223,7 +242,7 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclGlobals: {
|
| + case WasmSection::Code::Globals: {
|
| int length;
|
| uint32_t globals_count = consume_u32v(&length, "globals count");
|
| module->globals.reserve(SafeReserve(globals_count));
|
| @@ -238,7 +257,7 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclDataSegments: {
|
| + case WasmSection::Code::DataSegments: {
|
| int length;
|
| uint32_t data_segments_count =
|
| consume_u32v(&length, "data segments count");
|
| @@ -254,7 +273,7 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclFunctionTable: {
|
| + case WasmSection::Code::FunctionTable: {
|
| // An indirect function table requires functions first.
|
| CheckForFunctions(module, section);
|
| int length;
|
| @@ -275,7 +294,7 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclStartFunction: {
|
| + case WasmSection::Code::StartFunction: {
|
| // Declares a start function for a module.
|
| CheckForFunctions(module, section);
|
| if (module->start_function_index >= 0) {
|
| @@ -291,9 +310,10 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclImportTable: {
|
| + case WasmSection::Code::ImportTable: {
|
| // Declares an import table.
|
| - CheckForPreviousSection(sections, kDeclSignatures, true);
|
| + CheckForPreviousSection(sections, WasmSection::Code::Signatures,
|
| + true);
|
| int length;
|
| uint32_t import_table_count =
|
| consume_u32v(&length, "import table count");
|
| @@ -319,7 +339,7 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kDeclExportTable: {
|
| + case WasmSection::Code::ExportTable: {
|
| // Declares an export table.
|
| CheckForFunctions(module, section);
|
| int length;
|
| @@ -341,7 +361,7 @@ class ModuleDecoder : public Decoder {
|
| }
|
| break;
|
| }
|
| - case kMaxModuleSectionCode:
|
| + case WasmSection::Code::Max:
|
| UNREACHABLE(); // Already skipped unknown sections.
|
| }
|
| }
|
| @@ -355,41 +375,23 @@ class ModuleDecoder : public Decoder {
|
| return count < kMaxReserve ? count : kMaxReserve;
|
| }
|
|
|
| - const char* SectionName(WasmSectionDeclCode section) {
|
| - switch (section) {
|
| - case kDeclMemory:
|
| - return "memory";
|
| - case kDeclSignatures:
|
| - return "signatures";
|
| - case kDeclFunctions:
|
| - return "function declaration";
|
| - case kDeclGlobals:
|
| - return "global variable";
|
| - case kDeclDataSegments:
|
| - return "data segment";
|
| - case kDeclFunctionTable:
|
| - return "function table";
|
| - default:
|
| - return "";
|
| - }
|
| - }
|
| -
|
| - void CheckForFunctions(WasmModule* module, WasmSectionDeclCode section) {
|
| + void CheckForFunctions(WasmModule* module, WasmSection::Code section) {
|
| if (module->functions.size() == 0) {
|
| error(pc_ - 1, nullptr, "functions must appear before section %s",
|
| - SectionName(section));
|
| + WasmSection::getName(section));
|
| }
|
| }
|
|
|
| - void CheckForPreviousSection(bool* sections, WasmSectionDeclCode section,
|
| + void CheckForPreviousSection(bool* sections, WasmSection::Code section,
|
| bool present) {
|
| - if (section >= kMaxModuleSectionCode) return;
|
| - if (sections[section] == present) return;
|
| - const char* name = SectionName(section);
|
| + if (section >= WasmSection::Code::Max) return;
|
| + if (sections[(size_t)section] == present) return;
|
| if (present) {
|
| - error(pc_ - 1, nullptr, "required %s section missing", name);
|
| + error(pc_ - 1, nullptr, "required %s section missing",
|
| + WasmSection::getName(section));
|
| } else {
|
| - error(pc_ - 1, nullptr, "%s section already present", name);
|
| + error(pc_ - 1, nullptr, "%s section already present",
|
| + WasmSection::getName(section));
|
| }
|
| }
|
|
|
| @@ -606,6 +608,30 @@ class ModuleDecoder : public Decoder {
|
| return func_index;
|
| }
|
|
|
| + // Reads a section name.
|
| + WasmSection::Code consume_section_name(int* string_leb_length,
|
| + uint32_t* string_length) {
|
| + *string_length = consume_u32v(string_leb_length, "name length");
|
| + const byte* start = pc_;
|
| + consume_bytes(*string_length);
|
| + if (failed()) {
|
| + TRACE("Section name of length %u couldn't be read\n", *string_length);
|
| + return WasmSection::Code::Max;
|
| + }
|
| + // TODO(jfb) Linear search, it may be better to do a common-prefix search.
|
| + for (WasmSection::Code i = WasmSection::begin(); i != WasmSection::end();
|
| + i = WasmSection::next(i)) {
|
| + if (WasmSection::getNameLength(i) == *string_length &&
|
| + 0 == memcmp(WasmSection::getName(i), start, *string_length)) {
|
| + return i;
|
| + }
|
| + }
|
| + TRACE("Unknown section: '");
|
| + for (uint32_t i = 0; i != *string_length; ++i) TRACE("%c", *(start + i));
|
| + TRACE("'\n");
|
| + return WasmSection::Code::Max;
|
| + }
|
| +
|
| // Reads a single 8-bit integer, interpreting it as a local type.
|
| LocalType consume_local_type() {
|
| byte val = consume_u8("local type");
|
|
|