Home | History | Annotate | Download | only in wasm
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/wasm/module-decoder.h"
      6 
      7 #include "src/base/functional.h"
      8 #include "src/base/platform/platform.h"
      9 #include "src/base/template-utils.h"
     10 #include "src/counters.h"
     11 #include "src/flags.h"
     12 #include "src/macro-assembler.h"
     13 #include "src/objects-inl.h"
     14 #include "src/ostreams.h"
     15 #include "src/v8.h"
     16 #include "src/wasm/decoder.h"
     17 #include "src/wasm/function-body-decoder-impl.h"
     18 #include "src/wasm/wasm-engine.h"
     19 #include "src/wasm/wasm-limits.h"
     20 
     21 namespace v8 {
     22 namespace internal {
     23 namespace wasm {
     24 
     25 #define TRACE(...)                                    \
     26   do {                                                \
     27     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
     28   } while (false)
     29 
     30 namespace {
     31 
     32 constexpr char kNameString[] = "name";
     33 constexpr char kExceptionString[] = "exception";
     34 constexpr char kUnknownString[] = "<unknown>";
     35 
     36 template <size_t N>
     37 constexpr size_t num_chars(const char (&)[N]) {
     38   return N - 1;  // remove null character at end.
     39 }
     40 
     41 const char* ExternalKindName(ImportExportKindCode kind) {
     42   switch (kind) {
     43     case kExternalFunction:
     44       return "function";
     45     case kExternalTable:
     46       return "table";
     47     case kExternalMemory:
     48       return "memory";
     49     case kExternalGlobal:
     50       return "global";
     51   }
     52   return "unknown";
     53 }
     54 
     55 }  // namespace
     56 
     57 const char* SectionName(SectionCode code) {
     58   switch (code) {
     59     case kUnknownSectionCode:
     60       return "Unknown";
     61     case kTypeSectionCode:
     62       return "Type";
     63     case kImportSectionCode:
     64       return "Import";
     65     case kFunctionSectionCode:
     66       return "Function";
     67     case kTableSectionCode:
     68       return "Table";
     69     case kMemorySectionCode:
     70       return "Memory";
     71     case kGlobalSectionCode:
     72       return "Global";
     73     case kExportSectionCode:
     74       return "Export";
     75     case kStartSectionCode:
     76       return "Start";
     77     case kCodeSectionCode:
     78       return "Code";
     79     case kElementSectionCode:
     80       return "Element";
     81     case kDataSectionCode:
     82       return "Data";
     83     case kNameSectionCode:
     84       return kNameString;
     85     case kExceptionSectionCode:
     86       return kExceptionString;
     87     default:
     88       return kUnknownString;
     89   }
     90 }
     91 
     92 namespace {
     93 
     94 bool validate_utf8(Decoder* decoder, WireBytesRef string) {
     95   return unibrow::Utf8::ValidateEncoding(
     96       decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
     97       string.length());
     98 }
     99 
    100 ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
    101   switch (expr.kind) {
    102     case WasmInitExpr::kNone:
    103       return kWasmStmt;
    104     case WasmInitExpr::kGlobalIndex:
    105       return expr.val.global_index < module->globals.size()
    106                  ? module->globals[expr.val.global_index].type
    107                  : kWasmStmt;
    108     case WasmInitExpr::kI32Const:
    109       return kWasmI32;
    110     case WasmInitExpr::kI64Const:
    111       return kWasmI64;
    112     case WasmInitExpr::kF32Const:
    113       return kWasmF32;
    114     case WasmInitExpr::kF64Const:
    115       return kWasmF64;
    116     case WasmInitExpr::kAnyRefConst:
    117       return kWasmAnyRef;
    118     default:
    119       UNREACHABLE();
    120   }
    121 }
    122 
    123 // Reads a length-prefixed string, checking that it is within bounds. Returns
    124 // the offset of the string, and the length as an out parameter.
    125 WireBytesRef consume_string(Decoder& decoder, bool validate_utf8,
    126                             const char* name) {
    127   uint32_t length = decoder.consume_u32v("string length");
    128   uint32_t offset = decoder.pc_offset();
    129   const byte* string_start = decoder.pc();
    130   // Consume bytes before validation to guarantee that the string is not oob.
    131   if (length > 0) {
    132     decoder.consume_bytes(length, name);
    133     if (decoder.ok() && validate_utf8 &&
    134         !unibrow::Utf8::ValidateEncoding(string_start, length)) {
    135       decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
    136     }
    137   }
    138   return {offset, decoder.failed() ? 0 : length};
    139 }
    140 
    141 // An iterator over the sections in a wasm binary module.
    142 // Automatically skips all unknown sections.
    143 class WasmSectionIterator {
    144  public:
    145   explicit WasmSectionIterator(Decoder& decoder)
    146       : decoder_(decoder),
    147         section_code_(kUnknownSectionCode),
    148         section_start_(decoder.pc()),
    149         section_end_(decoder.pc()) {
    150     next();
    151   }
    152 
    153   inline bool more() const { return decoder_.ok() && decoder_.more(); }
    154 
    155   inline SectionCode section_code() const { return section_code_; }
    156 
    157   inline const byte* section_start() const { return section_start_; }
    158 
    159   inline uint32_t section_length() const {
    160     return static_cast<uint32_t>(section_end_ - section_start_);
    161   }
    162 
    163   inline Vector<const uint8_t> payload() const {
    164     return {payload_start_, payload_length()};
    165   }
    166 
    167   inline const byte* payload_start() const { return payload_start_; }
    168 
    169   inline uint32_t payload_length() const {
    170     return static_cast<uint32_t>(section_end_ - payload_start_);
    171   }
    172 
    173   inline const byte* section_end() const { return section_end_; }
    174 
    175   // Advances to the next section, checking that decoding the current section
    176   // stopped at {section_end_}.
    177   void advance(bool move_to_section_end = false) {
    178     if (move_to_section_end && decoder_.pc() < section_end_) {
    179       decoder_.consume_bytes(
    180           static_cast<uint32_t>(section_end_ - decoder_.pc()));
    181     }
    182     if (decoder_.pc() != section_end_) {
    183       const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
    184       decoder_.errorf(decoder_.pc(),
    185                       "section was %s than expected size "
    186                       "(%u bytes expected, %zu decoded)",
    187                       msg, section_length(),
    188                       static_cast<size_t>(decoder_.pc() - section_start_));
    189     }
    190     next();
    191   }
    192 
    193  private:
    194   Decoder& decoder_;
    195   SectionCode section_code_;
    196   const byte* section_start_;
    197   const byte* payload_start_;
    198   const byte* section_end_;
    199 
    200   // Reads the section code/name at the current position and sets up
    201   // the embedder fields.
    202   void next() {
    203     if (!decoder_.more()) {
    204       section_code_ = kUnknownSectionCode;
    205       return;
    206     }
    207     section_start_ = decoder_.pc();
    208     uint8_t section_code = decoder_.consume_u8("section code");
    209     // Read and check the section size.
    210     uint32_t section_length = decoder_.consume_u32v("section length");
    211 
    212     payload_start_ = decoder_.pc();
    213     if (decoder_.checkAvailable(section_length)) {
    214       // Get the limit of the section within the module.
    215       section_end_ = payload_start_ + section_length;
    216     } else {
    217       // The section would extend beyond the end of the module.
    218       section_end_ = payload_start_;
    219     }
    220 
    221     if (section_code == kUnknownSectionCode) {
    222       // Check for the known "name" section.
    223       section_code =
    224           ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
    225       // As a side effect, the above function will forward the decoder to after
    226       // the identifier string.
    227       payload_start_ = decoder_.pc();
    228     } else if (!IsValidSectionCode(section_code)) {
    229       decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
    230                       section_code);
    231       section_code = kUnknownSectionCode;
    232     }
    233     section_code_ = decoder_.failed() ? kUnknownSectionCode
    234                                       : static_cast<SectionCode>(section_code);
    235 
    236     if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
    237       // skip to the end of the unknown section.
    238       uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
    239       decoder_.consume_bytes(remaining, "section payload");
    240     }
    241   }
    242 };
    243 
    244 }  // namespace
    245 
    246 // The main logic for decoding the bytes of a module.
    247 class ModuleDecoderImpl : public Decoder {
    248  public:
    249   explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
    250       : Decoder(nullptr, nullptr),
    251         enabled_features_(enabled),
    252         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
    253 
    254   ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start,
    255                     const byte* module_end, ModuleOrigin origin)
    256       : Decoder(module_start, module_end),
    257         enabled_features_(enabled),
    258         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
    259     if (end_ < start_) {
    260       error(start_, "end is less than start");
    261       end_ = start_;
    262     }
    263   }
    264 
    265   virtual void onFirstError() {
    266     pc_ = end_;  // On error, terminate section decoding loop.
    267   }
    268 
    269   void DumpModule(const Vector<const byte> module_bytes) {
    270     std::string path;
    271     if (FLAG_dump_wasm_module_path) {
    272       path = FLAG_dump_wasm_module_path;
    273       if (path.size() &&
    274           !base::OS::isDirectorySeparator(path[path.size() - 1])) {
    275         path += base::OS::DirectorySeparator();
    276       }
    277     }
    278     // File are named `HASH.{ok,failed}.wasm`.
    279     size_t hash = base::hash_range(module_bytes.start(), module_bytes.end());
    280     EmbeddedVector<char, 32> buf;
    281     SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed");
    282     std::string name(buf.start());
    283     if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
    284       if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) !=
    285           1) {
    286         OFStream os(stderr);
    287         os << "Error while dumping wasm file" << std::endl;
    288       }
    289       fclose(wasm_file);
    290     }
    291   }
    292 
    293   void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
    294     CHECK_NULL(module_);
    295     SetCounters(counters);
    296     module_.reset(
    297         new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
    298     module_->initial_pages = 0;
    299     module_->maximum_pages = 0;
    300     module_->mem_export = false;
    301     module_->origin = origin_;
    302   }
    303 
    304   void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
    305     if (failed()) return;
    306     Reset(bytes, offset);
    307 
    308     const byte* pos = pc_;
    309     uint32_t magic_word = consume_u32("wasm magic");
    310 #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
    311     if (magic_word != kWasmMagic) {
    312       errorf(pos,
    313              "expected magic word %02x %02x %02x %02x, "
    314              "found %02x %02x %02x %02x",
    315              BYTES(kWasmMagic), BYTES(magic_word));
    316     }
    317 
    318     pos = pc_;
    319     {
    320       uint32_t magic_version = consume_u32("wasm version");
    321       if (magic_version != kWasmVersion) {
    322         errorf(pos,
    323                "expected version %02x %02x %02x %02x, "
    324                "found %02x %02x %02x %02x",
    325                BYTES(kWasmVersion), BYTES(magic_version));
    326       }
    327     }
    328 #undef BYTES
    329   }
    330 
    331   void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
    332                      uint32_t offset, bool verify_functions = true) {
    333     if (failed()) return;
    334     Reset(bytes, offset);
    335     TRACE("Section: %s\n", SectionName(section_code));
    336     TRACE("Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()),
    337           static_cast<const void*>(bytes.end()));
    338 
    339     // Check if the section is out-of-order.
    340     if (section_code < next_section_) {
    341       errorf(pc(), "unexpected section: %s", SectionName(section_code));
    342       return;
    343     }
    344 
    345     switch (section_code) {
    346       case kUnknownSectionCode:
    347         break;
    348       case kExceptionSectionCode:
    349         // Note: kExceptionSectionCode > kCodeSectionCode, but must appear
    350         // before the code section. Hence, treat it as a special case.
    351         if (++number_of_exception_sections > 1) {
    352           errorf(pc(), "Multiple exception sections not allowed");
    353           return;
    354         } else if (next_section_ >= kCodeSectionCode) {
    355           errorf(pc(), "Exception section must appear before the code section");
    356           return;
    357         }
    358         break;
    359       default:
    360         next_section_ = section_code;
    361         ++next_section_;
    362         break;
    363     }
    364 
    365     switch (section_code) {
    366       case kUnknownSectionCode:
    367         break;
    368       case kTypeSectionCode:
    369         DecodeTypeSection();
    370         break;
    371       case kImportSectionCode:
    372         DecodeImportSection();
    373         break;
    374       case kFunctionSectionCode:
    375         DecodeFunctionSection();
    376         break;
    377       case kTableSectionCode:
    378         DecodeTableSection();
    379         break;
    380       case kMemorySectionCode:
    381         DecodeMemorySection();
    382         break;
    383       case kGlobalSectionCode:
    384         DecodeGlobalSection();
    385         break;
    386       case kExportSectionCode:
    387         DecodeExportSection();
    388         break;
    389       case kStartSectionCode:
    390         DecodeStartSection();
    391         break;
    392       case kCodeSectionCode:
    393         DecodeCodeSection(verify_functions);
    394         break;
    395       case kElementSectionCode:
    396         DecodeElementSection();
    397         break;
    398       case kDataSectionCode:
    399         DecodeDataSection();
    400         break;
    401       case kNameSectionCode:
    402         DecodeNameSection();
    403         break;
    404       case kExceptionSectionCode:
    405         if (enabled_features_.eh) {
    406           DecodeExceptionSection();
    407         } else {
    408           errorf(pc(), "unexpected section: %s", SectionName(section_code));
    409         }
    410         break;
    411       default:
    412         errorf(pc(), "unexpected section: %s", SectionName(section_code));
    413         return;
    414     }
    415 
    416     if (pc() != bytes.end()) {
    417       const char* msg = pc() < bytes.end() ? "shorter" : "longer";
    418       errorf(pc(),
    419              "section was %s than expected size "
    420              "(%zu bytes expected, %zu decoded)",
    421              msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
    422     }
    423   }
    424 
    425   void DecodeTypeSection() {
    426     uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
    427     module_->signatures.reserve(signatures_count);
    428     for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
    429       TRACE("DecodeSignature[%d] module+%d\n", i,
    430             static_cast<int>(pc_ - start_));
    431       FunctionSig* s = consume_sig(module_->signature_zone.get());
    432       module_->signatures.push_back(s);
    433       uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
    434       module_->signature_ids.push_back(id);
    435     }
    436     module_->signature_map.Freeze();
    437   }
    438 
    439   void DecodeImportSection() {
    440     uint32_t import_table_count =
    441         consume_count("imports count", kV8MaxWasmImports);
    442     module_->import_table.reserve(import_table_count);
    443     for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
    444       TRACE("DecodeImportTable[%d] module+%d\n", i,
    445             static_cast<int>(pc_ - start_));
    446 
    447       module_->import_table.push_back({
    448           {0, 0},             // module_name
    449           {0, 0},             // field_name
    450           kExternalFunction,  // kind
    451           0                   // index
    452       });
    453       WasmImport* import = &module_->import_table.back();
    454       const byte* pos = pc_;
    455       import->module_name = consume_string(*this, true, "module name");
    456       import->field_name = consume_string(*this, true, "field name");
    457       import->kind =
    458           static_cast<ImportExportKindCode>(consume_u8("import kind"));
    459       switch (import->kind) {
    460         case kExternalFunction: {
    461           // ===== Imported function =======================================
    462           import->index = static_cast<uint32_t>(module_->functions.size());
    463           module_->num_imported_functions++;
    464           module_->functions.push_back({nullptr,        // sig
    465                                         import->index,  // func_index
    466                                         0,              // sig_index
    467                                         {0, 0},         // code
    468                                         true,           // imported
    469                                         false});        // exported
    470           WasmFunction* function = &module_->functions.back();
    471           function->sig_index =
    472               consume_sig_index(module_.get(), &function->sig);
    473           break;
    474         }
    475         case kExternalTable: {
    476           // ===== Imported table ==========================================
    477           if (!AddTable(module_.get())) break;
    478           import->index = static_cast<uint32_t>(module_->tables.size());
    479           module_->tables.emplace_back();
    480           WasmTable* table = &module_->tables.back();
    481           table->imported = true;
    482           ValueType type = consume_reference_type();
    483           if (!enabled_features_.anyref) {
    484             if (type != kWasmAnyFunc) {
    485               error(pc_ - 1, "invalid table type");
    486               break;
    487             }
    488           }
    489           table->type = type;
    490           uint8_t flags = validate_table_flags("element count");
    491           consume_resizable_limits(
    492               "element count", "elements", FLAG_wasm_max_table_size,
    493               &table->initial_size, &table->has_maximum_size,
    494               FLAG_wasm_max_table_size, &table->maximum_size, flags);
    495           break;
    496         }
    497         case kExternalMemory: {
    498           // ===== Imported memory =========================================
    499           if (!AddMemory(module_.get())) break;
    500           uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
    501           consume_resizable_limits(
    502               "memory", "pages", FLAG_wasm_max_mem_pages,
    503               &module_->initial_pages, &module_->has_maximum_pages,
    504               kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
    505           break;
    506         }
    507         case kExternalGlobal: {
    508           // ===== Imported global =========================================
    509           import->index = static_cast<uint32_t>(module_->globals.size());
    510           module_->globals.push_back(
    511               {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
    512           WasmGlobal* global = &module_->globals.back();
    513           global->type = consume_value_type();
    514           global->mutability = consume_mutability();
    515           if (global->mutability) {
    516             if (enabled_features_.mut_global) {
    517               module_->num_imported_mutable_globals++;
    518             } else {
    519               error("mutable globals cannot be imported");
    520             }
    521           }
    522           break;
    523         }
    524         default:
    525           errorf(pos, "unknown import kind 0x%02x", import->kind);
    526           break;
    527       }
    528     }
    529   }
    530 
    531   void DecodeFunctionSection() {
    532     uint32_t functions_count =
    533         consume_count("functions count", kV8MaxWasmFunctions);
    534     auto counter =
    535         SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
    536     counter->AddSample(static_cast<int>(functions_count));
    537     DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
    538     uint32_t total_function_count =
    539         module_->num_imported_functions + functions_count;
    540     module_->functions.reserve(total_function_count);
    541     module_->num_declared_functions = functions_count;
    542     for (uint32_t i = 0; i < functions_count; ++i) {
    543       uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
    544       module_->functions.push_back({nullptr,     // sig
    545                                     func_index,  // func_index
    546                                     0,           // sig_index
    547                                     {0, 0},      // code
    548                                     false,       // imported
    549                                     false});     // exported
    550       WasmFunction* function = &module_->functions.back();
    551       function->sig_index = consume_sig_index(module_.get(), &function->sig);
    552       if (!ok()) return;
    553     }
    554     DCHECK_EQ(module_->functions.size(), total_function_count);
    555   }
    556 
    557   void DecodeTableSection() {
    558     // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
    559     // implementation of AnyRef landed.
    560     uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
    561     uint32_t table_count = consume_count("table count", max_count);
    562 
    563     for (uint32_t i = 0; ok() && i < table_count; i++) {
    564       if (!AddTable(module_.get())) break;
    565       module_->tables.emplace_back();
    566       WasmTable* table = &module_->tables.back();
    567       table->type = consume_reference_type();
    568       uint8_t flags = validate_table_flags("table elements");
    569       consume_resizable_limits(
    570           "table elements", "elements", FLAG_wasm_max_table_size,
    571           &table->initial_size, &table->has_maximum_size,
    572           FLAG_wasm_max_table_size, &table->maximum_size, flags);
    573     }
    574   }
    575 
    576   void DecodeMemorySection() {
    577     uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
    578 
    579     for (uint32_t i = 0; ok() && i < memory_count; i++) {
    580       if (!AddMemory(module_.get())) break;
    581       uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
    582       consume_resizable_limits(
    583           "memory", "pages", FLAG_wasm_max_mem_pages, &module_->initial_pages,
    584           &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
    585           &module_->maximum_pages, flags);
    586     }
    587   }
    588 
    589   void DecodeGlobalSection() {
    590     uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
    591     uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
    592     module_->globals.reserve(imported_globals + globals_count);
    593     for (uint32_t i = 0; ok() && i < globals_count; ++i) {
    594       TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
    595       // Add an uninitialized global and pass a pointer to it.
    596       module_->globals.push_back(
    597           {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
    598       WasmGlobal* global = &module_->globals.back();
    599       DecodeGlobalInModule(module_.get(), i + imported_globals, global);
    600     }
    601     if (ok()) CalculateGlobalOffsets(module_.get());
    602   }
    603 
    604   void DecodeExportSection() {
    605     uint32_t export_table_count =
    606         consume_count("exports count", kV8MaxWasmExports);
    607     module_->export_table.reserve(export_table_count);
    608     for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
    609       TRACE("DecodeExportTable[%d] module+%d\n", i,
    610             static_cast<int>(pc_ - start_));
    611 
    612       module_->export_table.push_back({
    613           {0, 0},             // name
    614           kExternalFunction,  // kind
    615           0                   // index
    616       });
    617       WasmExport* exp = &module_->export_table.back();
    618 
    619       exp->name = consume_string(*this, true, "field name");
    620 
    621       const byte* pos = pc();
    622       exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
    623       switch (exp->kind) {
    624         case kExternalFunction: {
    625           WasmFunction* func = nullptr;
    626           exp->index = consume_func_index(module_.get(), &func);
    627           module_->num_exported_functions++;
    628           if (func) func->exported = true;
    629           break;
    630         }
    631         case kExternalTable: {
    632           WasmTable* table = nullptr;
    633           exp->index = consume_table_index(module_.get(), &table);
    634           if (table) table->exported = true;
    635           break;
    636         }
    637         case kExternalMemory: {
    638           uint32_t index = consume_u32v("memory index");
    639           // TODO(titzer): This should become more regular
    640           // once we support multiple memories.
    641           if (!module_->has_memory || index != 0) {
    642             error("invalid memory index != 0");
    643           }
    644           module_->mem_export = true;
    645           break;
    646         }
    647         case kExternalGlobal: {
    648           WasmGlobal* global = nullptr;
    649           exp->index = consume_global_index(module_.get(), &global);
    650           if (global) {
    651             if (!enabled_features_.mut_global && global->mutability) {
    652               error("mutable globals cannot be exported");
    653             }
    654             global->exported = true;
    655           }
    656           break;
    657         }
    658         default:
    659           errorf(pos, "invalid export kind 0x%02x", exp->kind);
    660           break;
    661       }
    662     }
    663     // Check for duplicate exports (except for asm.js).
    664     if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
    665       std::vector<WasmExport> sorted_exports(module_->export_table);
    666 
    667       auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
    668         // Return true if a < b.
    669         if (a.name.length() != b.name.length()) {
    670           return a.name.length() < b.name.length();
    671         }
    672         const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
    673         const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
    674         return memcmp(left, right, a.name.length()) < 0;
    675       };
    676       std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
    677 
    678       auto it = sorted_exports.begin();
    679       WasmExport* last = &*it++;
    680       for (auto end = sorted_exports.end(); it != end; last = &*it++) {
    681         DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
    682         if (!cmp_less(*last, *it)) {
    683           const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
    684           TruncatedUserString<> name(pc, it->name.length());
    685           errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
    686                  name.length(), name.start(), ExternalKindName(last->kind),
    687                  last->index, ExternalKindName(it->kind), it->index);
    688           break;
    689         }
    690       }
    691     }
    692   }
    693 
    694   void DecodeStartSection() {
    695     WasmFunction* func;
    696     const byte* pos = pc_;
    697     module_->start_function_index = consume_func_index(module_.get(), &func);
    698     if (func &&
    699         (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
    700       error(pos, "invalid start function: non-zero parameter or return count");
    701     }
    702   }
    703 
    704   void DecodeElementSection() {
    705     uint32_t element_count =
    706         consume_count("element count", FLAG_wasm_max_table_size);
    707 
    708     if (element_count > 0 && module_->tables.size() == 0) {
    709       error(pc_, "The element section requires a table");
    710     }
    711     for (uint32_t i = 0; ok() && i < element_count; ++i) {
    712       const byte* pos = pc();
    713       uint32_t table_index = consume_u32v("table index");
    714       if (!enabled_features_.anyref && table_index != 0) {
    715         errorf(pos, "illegal table index %u != 0", table_index);
    716       }
    717       if (table_index >= module_->tables.size()) {
    718         errorf(pos, "out of bounds table index %u", table_index);
    719         break;
    720       }
    721       if (module_->tables[table_index].type != kWasmAnyFunc) {
    722         errorf(pos, "Invalid element segment. Table %u is not of type AnyFunc",
    723                table_index);
    724         break;
    725       }
    726       WasmInitExpr offset = consume_init_expr(module_.get(), kWasmI32);
    727       uint32_t num_elem =
    728           consume_count("number of elements", kV8MaxWasmTableEntries);
    729       module_->table_inits.emplace_back(table_index, offset);
    730       WasmTableInit* init = &module_->table_inits.back();
    731       for (uint32_t j = 0; j < num_elem; j++) {
    732         WasmFunction* func = nullptr;
    733         uint32_t index = consume_func_index(module_.get(), &func);
    734         DCHECK_IMPLIES(ok(), func != nullptr);
    735         if (!ok()) break;
    736         DCHECK_EQ(index, func->func_index);
    737         init->entries.push_back(index);
    738       }
    739     }
    740   }
    741 
    742   void DecodeCodeSection(bool verify_functions) {
    743     uint32_t pos = pc_offset();
    744     uint32_t functions_count = consume_u32v("functions count");
    745     CheckFunctionsCount(functions_count, pos);
    746     for (uint32_t i = 0; ok() && i < functions_count; ++i) {
    747       const byte* pos = pc();
    748       uint32_t size = consume_u32v("body size");
    749       if (size > kV8MaxWasmFunctionSize) {
    750         errorf(pos, "size %u > maximum function size %zu", size,
    751                kV8MaxWasmFunctionSize);
    752         return;
    753       }
    754       uint32_t offset = pc_offset();
    755       consume_bytes(size, "function body");
    756       if (failed()) break;
    757       DecodeFunctionBody(i, size, offset, verify_functions);
    758     }
    759   }
    760 
    761   bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
    762     if (functions_count != module_->num_declared_functions) {
    763       Reset(nullptr, nullptr, offset);
    764       errorf(nullptr, "function body count %u mismatch (%u expected)",
    765              functions_count, module_->num_declared_functions);
    766       return false;
    767     }
    768     return true;
    769   }
    770 
    771   void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
    772                           bool verify_functions) {
    773     WasmFunction* function =
    774         &module_->functions[index + module_->num_imported_functions];
    775     function->code = {offset, length};
    776     if (verify_functions) {
    777       ModuleWireBytes bytes(start_, end_);
    778       VerifyFunctionBody(module_->signature_zone->allocator(),
    779                          index + module_->num_imported_functions, bytes,
    780                          module_.get(), function);
    781     }
    782   }
    783 
    784   void DecodeDataSection() {
    785     uint32_t data_segments_count =
    786         consume_count("data segments count", kV8MaxWasmDataSegments);
    787     module_->data_segments.reserve(data_segments_count);
    788     for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
    789       if (!module_->has_memory) {
    790         error("cannot load data without memory");
    791         break;
    792       }
    793       TRACE("DecodeDataSegment[%d] module+%d\n", i,
    794             static_cast<int>(pc_ - start_));
    795       module_->data_segments.push_back({
    796           WasmInitExpr(),  // dest_addr
    797           {0, 0}           // source
    798       });
    799       WasmDataSegment* segment = &module_->data_segments.back();
    800       DecodeDataSegmentInModule(module_.get(), segment);
    801     }
    802   }
    803 
    804   void DecodeNameSection() {
    805     // TODO(titzer): find a way to report name errors as warnings.
    806     // Use an inner decoder so that errors don't fail the outer decoder.
    807     Decoder inner(start_, pc_, end_, buffer_offset_);
    808     // Decode all name subsections.
    809     // Be lenient with their order.
    810     while (inner.ok() && inner.more()) {
    811       uint8_t name_type = inner.consume_u8("name type");
    812       if (name_type & 0x80) inner.error("name type if not varuint7");
    813 
    814       uint32_t name_payload_len = inner.consume_u32v("name payload length");
    815       if (!inner.checkAvailable(name_payload_len)) break;
    816 
    817       // Decode module name, ignore the rest.
    818       // Function and local names will be decoded when needed.
    819       if (name_type == NameSectionKindCode::kModule) {
    820         WireBytesRef name = consume_string(inner, false, "module name");
    821         if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
    822       } else {
    823         inner.consume_bytes(name_payload_len, "name subsection payload");
    824       }
    825     }
    826     // Skip the whole names section in the outer decoder.
    827     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
    828   }
    829 
    830   void DecodeExceptionSection() {
    831     uint32_t exception_count =
    832         consume_count("exception count", kV8MaxWasmExceptions);
    833     for (uint32_t i = 0; ok() && i < exception_count; ++i) {
    834       TRACE("DecodeExceptionSignature[%d] module+%d\n", i,
    835             static_cast<int>(pc_ - start_));
    836       module_->exceptions.emplace_back(
    837           consume_exception_sig(module_->signature_zone.get()));
    838     }
    839   }
    840 
    841   ModuleResult FinishDecoding(bool verify_functions = true) {
    842     if (ok()) {
    843       CalculateGlobalOffsets(module_.get());
    844     }
    845     ModuleResult result = toResult(std::move(module_));
    846     if (verify_functions && result.ok()) {
    847       // Copy error code and location.
    848       result.MoveErrorFrom(intermediate_result_);
    849     }
    850     return result;
    851   }
    852 
    853   // Decodes an entire module.
    854   ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
    855                             bool verify_functions = true) {
    856     StartDecoding(counters, allocator);
    857     uint32_t offset = 0;
    858     Vector<const byte> orig_bytes(start(), end() - start());
    859     DecodeModuleHeader(Vector<const uint8_t>(start(), end() - start()), offset);
    860     if (failed()) {
    861       return FinishDecoding(verify_functions);
    862     }
    863     // Size of the module header.
    864     offset += 8;
    865     Decoder decoder(start_ + offset, end_, offset);
    866 
    867     WasmSectionIterator section_iter(decoder);
    868 
    869     while (ok() && section_iter.more()) {
    870       // Shift the offset by the section header length
    871       offset += section_iter.payload_start() - section_iter.section_start();
    872       if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
    873         DecodeSection(section_iter.section_code(), section_iter.payload(),
    874                       offset, verify_functions);
    875       }
    876       // Shift the offset by the remaining section payload
    877       offset += section_iter.payload_length();
    878       section_iter.advance(true);
    879     }
    880 
    881     if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
    882 
    883     if (decoder.failed()) {
    884       return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
    885     }
    886 
    887     return FinishDecoding(verify_functions);
    888   }
    889 
    890   // Decodes a single anonymous function starting at {start_}.
    891   FunctionResult DecodeSingleFunction(Zone* zone,
    892                                       const ModuleWireBytes& wire_bytes,
    893                                       const WasmModule* module,
    894                                       std::unique_ptr<WasmFunction> function) {
    895     pc_ = start_;
    896     function->sig = consume_sig(zone);
    897     function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
    898 
    899     if (ok())
    900       VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
    901                          function.get());
    902 
    903     FunctionResult result(std::move(function));
    904     // Copy error code and location.
    905     result.MoveErrorFrom(intermediate_result_);
    906     return result;
    907   }
    908 
    909   // Decodes a single function signature at {start}.
    910   FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
    911     pc_ = start;
    912     FunctionSig* result = consume_sig(zone);
    913     return ok() ? result : nullptr;
    914   }
    915 
    916   WasmInitExpr DecodeInitExpr(const byte* start) {
    917     pc_ = start;
    918     return consume_init_expr(nullptr, kWasmStmt);
    919   }
    920 
    921   const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
    922 
    923   Counters* GetCounters() const {
    924     DCHECK_NOT_NULL(counters_);
    925     return counters_;
    926   }
    927 
    928   void SetCounters(Counters* counters) {
    929     DCHECK_NULL(counters_);
    930     counters_ = counters;
    931   }
    932 
    933  private:
    934   const WasmFeatures enabled_features_;
    935   std::shared_ptr<WasmModule> module_;
    936   Counters* counters_ = nullptr;
    937   // The type section is the first section in a module.
    938   uint8_t next_section_ = kFirstSectionInModule;
    939   uint32_t number_of_exception_sections = 0;
    940   // We store next_section_ as uint8_t instead of SectionCode so that we can
    941   // increment it. This static_assert should make sure that SectionCode does not
    942   // get bigger than uint8_t accidentially.
    943   static_assert(sizeof(ModuleDecoderImpl::next_section_) == sizeof(SectionCode),
    944                 "type mismatch");
    945   Result<bool> intermediate_result_;
    946   ModuleOrigin origin_;
    947 
    948   uint32_t off(const byte* ptr) {
    949     return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
    950   }
    951 
    952   bool AddTable(WasmModule* module) {
    953     if (enabled_features_.anyref) return true;
    954     if (module->tables.size() > 0) {
    955       error("At most one table is supported");
    956       return false;
    957     } else {
    958       return true;
    959     }
    960   }
    961 
    962   bool AddMemory(WasmModule* module) {
    963     if (module->has_memory) {
    964       error("At most one memory is supported");
    965       return false;
    966     } else {
    967       module->has_memory = true;
    968       return true;
    969     }
    970   }
    971 
    972   // Decodes a single global entry inside a module starting at {pc_}.
    973   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
    974                             WasmGlobal* global) {
    975     global->type = consume_value_type();
    976     global->mutability = consume_mutability();
    977     const byte* pos = pc();
    978     global->init = consume_init_expr(module, kWasmStmt);
    979     if (global->init.kind == WasmInitExpr::kGlobalIndex) {
    980       uint32_t other_index = global->init.val.global_index;
    981       if (other_index >= index) {
    982         errorf(pos,
    983                "invalid global index in init expression, "
    984                "index %u, other_index %u",
    985                index, other_index);
    986       } else if (module->globals[other_index].type != global->type) {
    987         errorf(pos,
    988                "type mismatch in global initialization "
    989                "(from global #%u), expected %s, got %s",
    990                other_index, ValueTypes::TypeName(global->type),
    991                ValueTypes::TypeName(module->globals[other_index].type));
    992       }
    993     } else {
    994       if (global->type != TypeOf(module, global->init)) {
    995         errorf(pos, "type error in global initialization, expected %s, got %s",
    996                ValueTypes::TypeName(global->type),
    997                ValueTypes::TypeName(TypeOf(module, global->init)));
    998       }
    999     }
   1000   }
   1001 
   1002   // Decodes a single data segment entry inside a module starting at {pc_}.
   1003   void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
   1004     expect_u8("linear memory index", 0);
   1005     segment->dest_addr = consume_init_expr(module, kWasmI32);
   1006     uint32_t source_length = consume_u32v("source size");
   1007     uint32_t source_offset = pc_offset();
   1008 
   1009     consume_bytes(source_length, "segment data");
   1010     if (failed()) return;
   1011 
   1012     segment->source = {source_offset, source_length};
   1013   }
   1014 
   1015   // Calculate individual global offsets and total size of globals table.
   1016   void CalculateGlobalOffsets(WasmModule* module) {
   1017     uint32_t offset = 0;
   1018     uint32_t num_imported_mutable_globals = 0;
   1019     if (module->globals.size() == 0) {
   1020       module->globals_buffer_size = 0;
   1021       return;
   1022     }
   1023     for (WasmGlobal& global : module->globals) {
   1024       byte size = ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
   1025       if (global.mutability && global.imported) {
   1026         DCHECK(enabled_features_.mut_global);
   1027         global.index = num_imported_mutable_globals++;
   1028       } else {
   1029         offset = (offset + size - 1) & ~(size - 1);  // align
   1030         global.offset = offset;
   1031         offset += size;
   1032       }
   1033     }
   1034     module->globals_buffer_size = offset;
   1035   }
   1036 
   1037   // Verifies the body (code) of a given function.
   1038   void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
   1039                           const ModuleWireBytes& wire_bytes,
   1040                           const WasmModule* module, WasmFunction* function) {
   1041     WasmFunctionName func_name(function,
   1042                                wire_bytes.GetNameOrNull(function, module));
   1043     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
   1044       StdoutStream os;
   1045       os << "Verifying wasm function " << func_name << std::endl;
   1046     }
   1047     FunctionBody body = {
   1048         function->sig, function->code.offset(),
   1049         start_ + GetBufferRelativeOffset(function->code.offset()),
   1050         start_ + GetBufferRelativeOffset(function->code.end_offset())};
   1051 
   1052     DecodeResult result;
   1053     {
   1054       auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
   1055                                               wasm_decode, function_time);
   1056 
   1057       TimedHistogramScope wasm_decode_function_time_scope(time_counter);
   1058       WasmFeatures unused_detected_features;
   1059       result = VerifyWasmCode(allocator, enabled_features_, module,
   1060                               &unused_detected_features, body);
   1061     }
   1062 
   1063     if (result.failed()) {
   1064       // Wrap the error message from the function decoder.
   1065       std::ostringstream wrapped;
   1066       wrapped << "in function " << func_name << ": " << result.error_msg();
   1067       result.error(result.error_offset(), wrapped.str());
   1068 
   1069       // Set error code and location, if this is the first error.
   1070       if (intermediate_result_.ok()) {
   1071         intermediate_result_.MoveErrorFrom(result);
   1072       }
   1073     }
   1074   }
   1075 
   1076   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
   1077     const byte* pos = pc_;
   1078     uint32_t sig_index = consume_u32v("signature index");
   1079     if (sig_index >= module->signatures.size()) {
   1080       errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
   1081              static_cast<int>(module->signatures.size()));
   1082       *sig = nullptr;
   1083       return 0;
   1084     }
   1085     *sig = module->signatures[sig_index];
   1086     return sig_index;
   1087   }
   1088 
   1089   uint32_t consume_count(const char* name, size_t maximum) {
   1090     const byte* p = pc_;
   1091     uint32_t count = consume_u32v(name);
   1092     if (count > maximum) {
   1093       errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
   1094       return static_cast<uint32_t>(maximum);
   1095     }
   1096     return count;
   1097   }
   1098 
   1099   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
   1100     return consume_index("function index", module->functions, func);
   1101   }
   1102 
   1103   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
   1104     return consume_index("global index", module->globals, global);
   1105   }
   1106 
   1107   uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
   1108     return consume_index("table index", module->tables, table);
   1109   }
   1110 
   1111   template <typename T>
   1112   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
   1113     const byte* pos = pc_;
   1114     uint32_t index = consume_u32v(name);
   1115     if (index >= vector.size()) {
   1116       errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
   1117              static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
   1118       *ptr = nullptr;
   1119       return 0;
   1120     }
   1121     *ptr = &vector[index];
   1122     return index;
   1123   }
   1124 
   1125   uint8_t validate_table_flags(const char* name) {
   1126     uint8_t flags = consume_u8("resizable limits flags");
   1127     const byte* pos = pc();
   1128     if (flags & 0xFE) {
   1129       errorf(pos - 1, "invalid %s limits flags", name);
   1130     }
   1131     return flags;
   1132   }
   1133 
   1134   uint8_t validate_memory_flags(bool* has_shared_memory) {
   1135     uint8_t flags = consume_u8("resizable limits flags");
   1136     const byte* pos = pc();
   1137     *has_shared_memory = false;
   1138     if (enabled_features_.threads) {
   1139       if (flags & 0xFC) {
   1140         errorf(pos - 1, "invalid memory limits flags");
   1141       } else if (flags == 3) {
   1142         DCHECK_NOT_NULL(has_shared_memory);
   1143         *has_shared_memory = true;
   1144       } else if (flags == 2) {
   1145         errorf(pos - 1,
   1146                "memory limits flags should have maximum defined if shared is "
   1147                "true");
   1148       }
   1149     } else {
   1150       if (flags & 0xFE) {
   1151         errorf(pos - 1, "invalid memory limits flags");
   1152       }
   1153     }
   1154     return flags;
   1155   }
   1156 
   1157   void consume_resizable_limits(const char* name, const char* units,
   1158                                 uint32_t max_initial, uint32_t* initial,
   1159                                 bool* has_max, uint32_t max_maximum,
   1160                                 uint32_t* maximum, uint8_t flags) {
   1161     const byte* pos = pc();
   1162     *initial = consume_u32v("initial size");
   1163     *has_max = false;
   1164     if (*initial > max_initial) {
   1165       errorf(pos,
   1166              "initial %s size (%u %s) is larger than implementation limit (%u)",
   1167              name, *initial, units, max_initial);
   1168     }
   1169     if (flags & 1) {
   1170       *has_max = true;
   1171       pos = pc();
   1172       *maximum = consume_u32v("maximum size");
   1173       if (*maximum > max_maximum) {
   1174         errorf(
   1175             pos,
   1176             "maximum %s size (%u %s) is larger than implementation limit (%u)",
   1177             name, *maximum, units, max_maximum);
   1178       }
   1179       if (*maximum < *initial) {
   1180         errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
   1181                name, *maximum, units, *initial, units);
   1182       }
   1183     } else {
   1184       *has_max = false;
   1185       *maximum = max_initial;
   1186     }
   1187   }
   1188 
   1189   bool expect_u8(const char* name, uint8_t expected) {
   1190     const byte* pos = pc();
   1191     uint8_t value = consume_u8(name);
   1192     if (value != expected) {
   1193       errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
   1194       return false;
   1195     }
   1196     return true;
   1197   }
   1198 
   1199   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
   1200     const byte* pos = pc();
   1201     uint8_t opcode = consume_u8("opcode");
   1202     WasmInitExpr expr;
   1203     unsigned len = 0;
   1204     switch (opcode) {
   1205       case kExprGetGlobal: {
   1206         GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
   1207         if (module->globals.size() <= imm.index) {
   1208           error("global index is out of bounds");
   1209           expr.kind = WasmInitExpr::kNone;
   1210           expr.val.i32_const = 0;
   1211           break;
   1212         }
   1213         WasmGlobal* global = &module->globals[imm.index];
   1214         if (global->mutability || !global->imported) {
   1215           error(
   1216               "only immutable imported globals can be used in initializer "
   1217               "expressions");
   1218           expr.kind = WasmInitExpr::kNone;
   1219           expr.val.i32_const = 0;
   1220           break;
   1221         }
   1222         expr.kind = WasmInitExpr::kGlobalIndex;
   1223         expr.val.global_index = imm.index;
   1224         len = imm.length;
   1225         break;
   1226       }
   1227       case kExprI32Const: {
   1228         ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
   1229         expr.kind = WasmInitExpr::kI32Const;
   1230         expr.val.i32_const = imm.value;
   1231         len = imm.length;
   1232         break;
   1233       }
   1234       case kExprF32Const: {
   1235         ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
   1236         expr.kind = WasmInitExpr::kF32Const;
   1237         expr.val.f32_const = imm.value;
   1238         len = imm.length;
   1239         break;
   1240       }
   1241       case kExprI64Const: {
   1242         ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
   1243         expr.kind = WasmInitExpr::kI64Const;
   1244         expr.val.i64_const = imm.value;
   1245         len = imm.length;
   1246         break;
   1247       }
   1248       case kExprF64Const: {
   1249         ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
   1250         expr.kind = WasmInitExpr::kF64Const;
   1251         expr.val.f64_const = imm.value;
   1252         len = imm.length;
   1253         break;
   1254       }
   1255       case kExprRefNull: {
   1256         if (enabled_features_.anyref) {
   1257           expr.kind = WasmInitExpr::kAnyRefConst;
   1258           len = 0;
   1259           break;
   1260         }
   1261         V8_FALLTHROUGH;
   1262       }
   1263       default: {
   1264         error("invalid opcode in initialization expression");
   1265         expr.kind = WasmInitExpr::kNone;
   1266         expr.val.i32_const = 0;
   1267       }
   1268     }
   1269     consume_bytes(len, "init code");
   1270     if (!expect_u8("end opcode", kExprEnd)) {
   1271       expr.kind = WasmInitExpr::kNone;
   1272     }
   1273     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
   1274       errorf(pos, "type error in init expression, expected %s, got %s",
   1275              ValueTypes::TypeName(expected),
   1276              ValueTypes::TypeName(TypeOf(module, expr)));
   1277     }
   1278     return expr;
   1279   }
   1280 
   1281   // Read a mutability flag
   1282   bool consume_mutability() {
   1283     byte val = consume_u8("mutability");
   1284     if (val > 1) error(pc_ - 1, "invalid mutability");
   1285     return val != 0;
   1286   }
   1287 
   1288   // Reads a single 8-bit integer, interpreting it as a local type.
   1289   ValueType consume_value_type() {
   1290     byte val = consume_u8("value type");
   1291     ValueTypeCode t = static_cast<ValueTypeCode>(val);
   1292     switch (t) {
   1293       case kLocalI32:
   1294         return kWasmI32;
   1295       case kLocalI64:
   1296         return kWasmI64;
   1297       case kLocalF32:
   1298         return kWasmF32;
   1299       case kLocalF64:
   1300         return kWasmF64;
   1301       default:
   1302         if (origin_ == kWasmOrigin) {
   1303           switch (t) {
   1304             case kLocalS128:
   1305               if (enabled_features_.simd) return kWasmS128;
   1306               break;
   1307             case kLocalAnyFunc:
   1308               if (enabled_features_.anyref) return kWasmAnyFunc;
   1309               break;
   1310             case kLocalAnyRef:
   1311               if (enabled_features_.anyref) return kWasmAnyRef;
   1312               break;
   1313             default:
   1314               break;
   1315           }
   1316         }
   1317         error(pc_ - 1, "invalid local type");
   1318         return kWasmStmt;
   1319     }
   1320   }
   1321 
   1322   // Reads a single 8-bit integer, interpreting it as a reference type.
   1323   ValueType consume_reference_type() {
   1324     byte val = consume_u8("reference type");
   1325     ValueTypeCode t = static_cast<ValueTypeCode>(val);
   1326     switch (t) {
   1327       case kLocalAnyFunc:
   1328         return kWasmAnyFunc;
   1329       case kLocalAnyRef:
   1330         if (!enabled_features_.anyref) {
   1331           error(pc_ - 1,
   1332                 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
   1333         }
   1334         return kWasmAnyRef;
   1335       default:
   1336         break;
   1337     }
   1338     error(pc_ - 1, "invalid reference type");
   1339     return kWasmStmt;
   1340   }
   1341 
   1342   FunctionSig* consume_sig(Zone* zone) {
   1343     constexpr bool has_return_values = true;
   1344     return consume_sig_internal(zone, has_return_values);
   1345   }
   1346 
   1347   WasmExceptionSig* consume_exception_sig(Zone* zone) {
   1348     constexpr bool has_return_values = true;
   1349     return consume_sig_internal(zone, !has_return_values);
   1350   }
   1351 
   1352  private:
   1353   FunctionSig* consume_sig_internal(Zone* zone, bool has_return_values) {
   1354     if (has_return_values && !expect_u8("type form", kWasmFunctionTypeCode))
   1355       return nullptr;
   1356     // parse parameter types
   1357     uint32_t param_count =
   1358         consume_count("param count", kV8MaxWasmFunctionParams);
   1359     if (failed()) return nullptr;
   1360     std::vector<ValueType> params;
   1361     for (uint32_t i = 0; ok() && i < param_count; ++i) {
   1362       ValueType param = consume_value_type();
   1363       params.push_back(param);
   1364     }
   1365     std::vector<ValueType> returns;
   1366     uint32_t return_count = 0;
   1367     if (has_return_values) {
   1368       // parse return types
   1369       const size_t max_return_count = enabled_features_.mv
   1370                                           ? kV8MaxWasmFunctionMultiReturns
   1371                                           : kV8MaxWasmFunctionReturns;
   1372       return_count = consume_count("return count", max_return_count);
   1373       if (failed()) return nullptr;
   1374       for (uint32_t i = 0; ok() && i < return_count; ++i) {
   1375         ValueType ret = consume_value_type();
   1376         returns.push_back(ret);
   1377       }
   1378     }
   1379 
   1380     if (failed()) return nullptr;
   1381 
   1382     // FunctionSig stores the return types first.
   1383     ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
   1384     uint32_t b = 0;
   1385     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
   1386     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
   1387 
   1388     return new (zone) FunctionSig(return_count, param_count, buffer);
   1389   }
   1390 };
   1391 
   1392 ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
   1393                               const byte* module_start, const byte* module_end,
   1394                               bool verify_functions, ModuleOrigin origin,
   1395                               Counters* counters,
   1396                               AccountingAllocator* allocator) {
   1397   auto counter =
   1398       SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
   1399   TimedHistogramScope wasm_decode_module_time_scope(counter);
   1400   size_t size = module_end - module_start;
   1401   if (module_start > module_end) return ModuleResult::Error("start > end");
   1402   if (size >= kV8MaxWasmModuleSize)
   1403     return ModuleResult::Error("size > maximum module size: %zu", size);
   1404   // TODO(bradnelson): Improve histogram handling of size_t.
   1405   auto size_counter =
   1406       SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
   1407   size_counter->AddSample(static_cast<int>(size));
   1408   // Signatures are stored in zone memory, which have the same lifetime
   1409   // as the {module}.
   1410   ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
   1411   ModuleResult result =
   1412       decoder.DecodeModule(counters, allocator, verify_functions);
   1413   // TODO(bradnelson): Improve histogram handling of size_t.
   1414   // TODO(titzer): this isn't accurate, since it doesn't count the data
   1415   // allocated on the C++ heap.
   1416   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
   1417   if (result.ok()) {
   1418     auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
   1419                                             module_peak_memory_bytes);
   1420     peak_counter->AddSample(
   1421         static_cast<int>(result.val->signature_zone->allocation_size()));
   1422   }
   1423   return result;
   1424 }
   1425 
   1426 ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
   1427     : enabled_features_(enabled) {}
   1428 
   1429 ModuleDecoder::~ModuleDecoder() = default;
   1430 
   1431 const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
   1432   return impl_->shared_module();
   1433 }
   1434 
   1435 void ModuleDecoder::StartDecoding(Counters* counters,
   1436                                   AccountingAllocator* allocator,
   1437                                   ModuleOrigin origin) {
   1438   DCHECK_NULL(impl_);
   1439   impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
   1440   impl_->StartDecoding(counters, allocator);
   1441 }
   1442 
   1443 void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
   1444                                        uint32_t offset) {
   1445   impl_->DecodeModuleHeader(bytes, offset);
   1446 }
   1447 
   1448 void ModuleDecoder::DecodeSection(SectionCode section_code,
   1449                                   Vector<const uint8_t> bytes, uint32_t offset,
   1450                                   bool verify_functions) {
   1451   impl_->DecodeSection(section_code, bytes, offset, verify_functions);
   1452 }
   1453 
   1454 void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
   1455                                        uint32_t offset, bool verify_functions) {
   1456   impl_->DecodeFunctionBody(index, length, offset, verify_functions);
   1457 }
   1458 
   1459 bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
   1460                                         uint32_t offset) {
   1461   return impl_->CheckFunctionsCount(functions_count, offset);
   1462 }
   1463 
   1464 ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
   1465   return impl_->FinishDecoding(verify_functions);
   1466 }
   1467 
   1468 SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
   1469                                                   const byte* end) {
   1470   WireBytesRef string = consume_string(decoder, true, "section name");
   1471   if (decoder.failed() || decoder.pc() > end) {
   1472     return kUnknownSectionCode;
   1473   }
   1474   const byte* section_name_start =
   1475       decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
   1476 
   1477   TRACE("  +%d  section name        : \"%.*s\"\n",
   1478         static_cast<int>(section_name_start - decoder.start()),
   1479         string.length() < 20 ? string.length() : 20, section_name_start);
   1480 
   1481   if (string.length() == num_chars(kNameString) &&
   1482       strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
   1483               num_chars(kNameString)) == 0) {
   1484     return kNameSectionCode;
   1485   }
   1486   return kUnknownSectionCode;
   1487 }
   1488 
   1489 bool ModuleDecoder::ok() { return impl_->ok(); }
   1490 
   1491 FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
   1492                                            Zone* zone, const byte* start,
   1493                                            const byte* end) {
   1494   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
   1495   return decoder.DecodeFunctionSignature(zone, start);
   1496 }
   1497 
   1498 WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
   1499                                           const byte* start, const byte* end) {
   1500   AccountingAllocator allocator;
   1501   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
   1502   return decoder.DecodeInitExpr(start);
   1503 }
   1504 
   1505 FunctionResult DecodeWasmFunctionForTesting(
   1506     const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
   1507     const WasmModule* module, const byte* function_start,
   1508     const byte* function_end, Counters* counters) {
   1509   size_t size = function_end - function_start;
   1510   if (function_start > function_end)
   1511     return FunctionResult::Error("start > end");
   1512   auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
   1513                                             function_size_bytes);
   1514   // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
   1515   size_histogram->AddSample(static_cast<int>(size));
   1516   if (size > kV8MaxWasmFunctionSize)
   1517     return FunctionResult::Error("size > maximum function size: %zu", size);
   1518   ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
   1519   decoder.SetCounters(counters);
   1520   return decoder.DecodeSingleFunction(zone, wire_bytes, module,
   1521                                       base::make_unique<WasmFunction>());
   1522 }
   1523 
   1524 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
   1525                                       const byte* tables_end) {
   1526   AsmJsOffsets table;
   1527 
   1528   Decoder decoder(tables_start, tables_end);
   1529   uint32_t functions_count = decoder.consume_u32v("functions count");
   1530   // Reserve space for the entries, taking care of invalid input.
   1531   if (functions_count < static_cast<unsigned>(tables_end - tables_start)) {
   1532     table.reserve(functions_count);
   1533   }
   1534 
   1535   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
   1536     uint32_t size = decoder.consume_u32v("table size");
   1537     if (size == 0) {
   1538       table.emplace_back();
   1539       continue;
   1540     }
   1541     if (!decoder.checkAvailable(size)) {
   1542       decoder.error("illegal asm function offset table size");
   1543     }
   1544     const byte* table_end = decoder.pc() + size;
   1545     uint32_t locals_size = decoder.consume_u32v("locals size");
   1546     int function_start_position = decoder.consume_u32v("function start pos");
   1547     int last_byte_offset = locals_size;
   1548     int last_asm_position = function_start_position;
   1549     std::vector<AsmJsOffsetEntry> func_asm_offsets;
   1550     func_asm_offsets.reserve(size / 4);  // conservative estimation
   1551     // Add an entry for the stack check, associated with position 0.
   1552     func_asm_offsets.push_back(
   1553         {0, function_start_position, function_start_position});
   1554     while (decoder.ok() && decoder.pc() < table_end) {
   1555       last_byte_offset += decoder.consume_u32v("byte offset delta");
   1556       int call_position =
   1557           last_asm_position + decoder.consume_i32v("call position delta");
   1558       int to_number_position =
   1559           call_position + decoder.consume_i32v("to_number position delta");
   1560       last_asm_position = to_number_position;
   1561       func_asm_offsets.push_back(
   1562           {last_byte_offset, call_position, to_number_position});
   1563     }
   1564     if (decoder.pc() != table_end) {
   1565       decoder.error("broken asm offset table");
   1566     }
   1567     table.push_back(std::move(func_asm_offsets));
   1568   }
   1569   if (decoder.more()) decoder.error("unexpected additional bytes");
   1570 
   1571   return decoder.toResult(std::move(table));
   1572 }
   1573 
   1574 std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
   1575                                                       const byte* end) {
   1576   Decoder decoder(start, end);
   1577   decoder.consume_bytes(4, "wasm magic");
   1578   decoder.consume_bytes(4, "wasm version");
   1579 
   1580   std::vector<CustomSectionOffset> result;
   1581 
   1582   while (decoder.more()) {
   1583     byte section_code = decoder.consume_u8("section code");
   1584     uint32_t section_length = decoder.consume_u32v("section length");
   1585     uint32_t section_start = decoder.pc_offset();
   1586     if (section_code != 0) {
   1587       // Skip known sections.
   1588       decoder.consume_bytes(section_length, "section bytes");
   1589       continue;
   1590     }
   1591     uint32_t name_length = decoder.consume_u32v("name length");
   1592     uint32_t name_offset = decoder.pc_offset();
   1593     decoder.consume_bytes(name_length, "section name");
   1594     uint32_t payload_offset = decoder.pc_offset();
   1595     if (section_length < (payload_offset - section_start)) {
   1596       decoder.error("invalid section length");
   1597       break;
   1598     }
   1599     uint32_t payload_length = section_length - (payload_offset - section_start);
   1600     decoder.consume_bytes(payload_length);
   1601     if (decoder.failed()) break;
   1602     result.push_back({{section_start, section_length},
   1603                       {name_offset, name_length},
   1604                       {payload_offset, payload_length}});
   1605   }
   1606 
   1607   return result;
   1608 }
   1609 
   1610 namespace {
   1611 
   1612 bool FindSection(Decoder& decoder, SectionCode section_code) {
   1613   static constexpr int kModuleHeaderSize = 8;
   1614   decoder.consume_bytes(kModuleHeaderSize, "module header");
   1615 
   1616   WasmSectionIterator section_iter(decoder);
   1617 
   1618   while (decoder.ok() && section_iter.more() &&
   1619          section_iter.section_code() != kNameSectionCode) {
   1620     section_iter.advance(true);
   1621   }
   1622   if (!section_iter.more()) return false;
   1623 
   1624   // Reset the decoder to not read beyond the name section end.
   1625   decoder.Reset(section_iter.payload(), decoder.pc_offset());
   1626   return true;
   1627 }
   1628 
   1629 }  // namespace
   1630 
   1631 void DecodeFunctionNames(const byte* module_start, const byte* module_end,
   1632                          std::unordered_map<uint32_t, WireBytesRef>* names) {
   1633   DCHECK_NOT_NULL(names);
   1634   DCHECK(names->empty());
   1635 
   1636   Decoder decoder(module_start, module_end);
   1637   if (!FindSection(decoder, kNameSectionCode)) return;
   1638 
   1639   while (decoder.ok() && decoder.more()) {
   1640     uint8_t name_type = decoder.consume_u8("name type");
   1641     if (name_type & 0x80) break;  // no varuint7
   1642 
   1643     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
   1644     if (!decoder.checkAvailable(name_payload_len)) break;
   1645 
   1646     if (name_type != NameSectionKindCode::kFunction) {
   1647       decoder.consume_bytes(name_payload_len, "name subsection payload");
   1648       continue;
   1649     }
   1650     uint32_t functions_count = decoder.consume_u32v("functions count");
   1651 
   1652     for (; decoder.ok() && functions_count > 0; --functions_count) {
   1653       uint32_t function_index = decoder.consume_u32v("function index");
   1654       WireBytesRef name = consume_string(decoder, false, "function name");
   1655 
   1656       // Be lenient with errors in the name section: Ignore non-UTF8 names. You
   1657       // can even assign to the same function multiple times (last valid one
   1658       // wins).
   1659       if (decoder.ok() && validate_utf8(&decoder, name)) {
   1660         names->insert(std::make_pair(function_index, name));
   1661       }
   1662     }
   1663   }
   1664 }
   1665 
   1666 void DecodeLocalNames(const byte* module_start, const byte* module_end,
   1667                       LocalNames* result) {
   1668   DCHECK_NOT_NULL(result);
   1669   DCHECK(result->names.empty());
   1670 
   1671   Decoder decoder(module_start, module_end);
   1672   if (!FindSection(decoder, kNameSectionCode)) return;
   1673 
   1674   while (decoder.ok() && decoder.more()) {
   1675     uint8_t name_type = decoder.consume_u8("name type");
   1676     if (name_type & 0x80) break;  // no varuint7
   1677 
   1678     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
   1679     if (!decoder.checkAvailable(name_payload_len)) break;
   1680 
   1681     if (name_type != NameSectionKindCode::kLocal) {
   1682       decoder.consume_bytes(name_payload_len, "name subsection payload");
   1683       continue;
   1684     }
   1685 
   1686     uint32_t local_names_count = decoder.consume_u32v("local names count");
   1687     for (uint32_t i = 0; i < local_names_count; ++i) {
   1688       uint32_t func_index = decoder.consume_u32v("function index");
   1689       if (func_index > kMaxInt) continue;
   1690       result->names.emplace_back(static_cast<int>(func_index));
   1691       LocalNamesPerFunction& func_names = result->names.back();
   1692       result->max_function_index =
   1693           std::max(result->max_function_index, func_names.function_index);
   1694       uint32_t num_names = decoder.consume_u32v("namings count");
   1695       for (uint32_t k = 0; k < num_names; ++k) {
   1696         uint32_t local_index = decoder.consume_u32v("local index");
   1697         WireBytesRef name = consume_string(decoder, true, "local name");
   1698         if (!decoder.ok()) break;
   1699         if (local_index > kMaxInt) continue;
   1700         func_names.max_local_index =
   1701             std::max(func_names.max_local_index, static_cast<int>(local_index));
   1702         func_names.names.emplace_back(static_cast<int>(local_index), name);
   1703       }
   1704     }
   1705   }
   1706 }
   1707 
   1708 #undef TRACE
   1709 
   1710 }  // namespace wasm
   1711 }  // namespace internal
   1712 }  // namespace v8
   1713