LCOV - code coverage report
Current view: top level - src/wasm - module-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 846 888 95.3 %
Date: 2019-03-21 Functions: 79 79 100.0 %

          Line data    Source code
       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/objects-inl.h"
      13             : #include "src/ostreams.h"
      14             : #include "src/v8.h"
      15             : #include "src/wasm/decoder.h"
      16             : #include "src/wasm/function-body-decoder-impl.h"
      17             : #include "src/wasm/wasm-engine.h"
      18             : #include "src/wasm/wasm-limits.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : 
      24             : #define TRACE(...)                                    \
      25             :   do {                                                \
      26             :     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
      27             :   } while (false)
      28             : 
      29             : namespace {
      30             : 
      31             : constexpr char kNameString[] = "name";
      32             : constexpr char kSourceMappingURLString[] = "sourceMappingURL";
      33             : constexpr char kCompilationHintsString[] = "compilationHints";
      34             : 
      35             : template <size_t N>
      36             : constexpr size_t num_chars(const char (&)[N]) {
      37             :   return N - 1;  // remove null character at end.
      38             : }
      39             : 
      40             : const char* ExternalKindName(ImportExportKindCode kind) {
      41         656 :   switch (kind) {
      42             :     case kExternalFunction:
      43             :       return "function";
      44             :     case kExternalTable:
      45             :       return "table";
      46             :     case kExternalMemory:
      47             :       return "memory";
      48             :     case kExternalGlobal:
      49             :       return "global";
      50             :     case kExternalException:
      51             :       return "exception";
      52             :   }
      53             :   return "unknown";
      54             : }
      55             : 
      56             : }  // namespace
      57             : 
      58          31 : const char* SectionName(SectionCode code) {
      59          31 :   switch (code) {
      60             :     case kUnknownSectionCode:
      61             :       return "Unknown";
      62             :     case kTypeSectionCode:
      63           0 :       return "Type";
      64             :     case kImportSectionCode:
      65           0 :       return "Import";
      66             :     case kFunctionSectionCode:
      67           0 :       return "Function";
      68             :     case kTableSectionCode:
      69           0 :       return "Table";
      70             :     case kMemorySectionCode:
      71           0 :       return "Memory";
      72             :     case kGlobalSectionCode:
      73           2 :       return "Global";
      74             :     case kExportSectionCode:
      75           2 :       return "Export";
      76             :     case kStartSectionCode:
      77           8 :       return "Start";
      78             :     case kCodeSectionCode:
      79           1 :       return "Code";
      80             :     case kElementSectionCode:
      81           2 :       return "Element";
      82             :     case kDataSectionCode:
      83           0 :       return "Data";
      84             :     case kExceptionSectionCode:
      85          12 :       return "Exception";
      86             :     case kDataCountSectionCode:
      87           4 :       return "DataCount";
      88             :     case kNameSectionCode:
      89           0 :       return kNameString;
      90             :     case kSourceMappingURLSectionCode:
      91           0 :       return kSourceMappingURLString;
      92             :     case kCompilationHintsSectionCode:
      93           0 :       return kCompilationHintsString;
      94             :     default:
      95           0 :       return "<unknown>";
      96             :   }
      97             : }
      98             : 
      99             : namespace {
     100             : 
     101             : bool validate_utf8(Decoder* decoder, WireBytesRef string) {
     102       30116 :   return unibrow::Utf8::ValidateEncoding(
     103             :       decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
     104       15058 :       string.length());
     105             : }
     106             : 
     107      445960 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
     108      445960 :   switch (expr.kind) {
     109             :     case WasmInitExpr::kNone:
     110             :       return kWasmStmt;
     111             :     case WasmInitExpr::kGlobalIndex:
     112         297 :       return expr.val.global_index < module->globals.size()
     113             :                  ? module->globals[expr.val.global_index].type
     114         594 :                  : kWasmStmt;
     115             :     case WasmInitExpr::kI32Const:
     116             :       return kWasmI32;
     117             :     case WasmInitExpr::kI64Const:
     118             :       return kWasmI64;
     119             :     case WasmInitExpr::kF32Const:
     120             :       return kWasmF32;
     121             :     case WasmInitExpr::kF64Const:
     122             :       return kWasmF64;
     123             :     case WasmInitExpr::kRefNullConst:
     124             :       return kWasmNullRef;
     125             :     default:
     126           0 :       UNREACHABLE();
     127             :   }
     128             : }
     129             : 
     130             : // Reads a length-prefixed string, checking that it is within bounds. Returns
     131             : // the offset of the string, and the length as an out parameter.
     132      873898 : WireBytesRef consume_string(Decoder& decoder, bool validate_utf8,
     133             :                             const char* name) {
     134             :   uint32_t length = decoder.consume_u32v("string length");
     135             :   uint32_t offset = decoder.pc_offset();
     136             :   const byte* string_start = decoder.pc();
     137             :   // Consume bytes before validation to guarantee that the string is not oob.
     138      873898 :   if (length > 0) {
     139      862855 :     decoder.consume_bytes(length, name);
     140     1708293 :     if (decoder.ok() && validate_utf8 &&
     141      845427 :         !unibrow::Utf8::ValidateEncoding(string_start, length)) {
     142        8642 :       decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
     143             :     }
     144             :   }
     145      873912 :   return {offset, decoder.failed() ? 0 : length};
     146             : }
     147             : 
     148             : // An iterator over the sections in a wasm binary module.
     149             : // Automatically skips all unknown sections.
     150             : class WasmSectionIterator {
     151             :  public:
     152             :   explicit WasmSectionIterator(Decoder& decoder)
     153             :       : decoder_(decoder),
     154             :         section_code_(kUnknownSectionCode),
     155             :         section_start_(decoder.pc()),
     156      404042 :         section_end_(decoder.pc()) {
     157      404042 :     next();
     158             :   }
     159             : 
     160     1738852 :   inline bool more() const { return decoder_.ok() && decoder_.more(); }
     161             : 
     162             :   inline SectionCode section_code() const { return section_code_; }
     163             : 
     164             :   inline const byte* section_start() const { return section_start_; }
     165             : 
     166             :   inline uint32_t section_length() const {
     167         472 :     return static_cast<uint32_t>(section_end_ - section_start_);
     168             :   }
     169             : 
     170             :   inline Vector<const uint8_t> payload() const {
     171     1293875 :     return {payload_start_, payload_length()};
     172             :   }
     173             : 
     174             :   inline const byte* payload_start() const { return payload_start_; }
     175             : 
     176             :   inline uint32_t payload_length() const {
     177     2579751 :     return static_cast<uint32_t>(section_end_ - payload_start_);
     178             :   }
     179             : 
     180             :   inline const byte* section_end() const { return section_end_; }
     181             : 
     182             :   // Advances to the next section, checking that decoding the current section
     183             :   // stopped at {section_end_}.
     184     1331699 :   void advance(bool move_to_section_end = false) {
     185     1331699 :     if (move_to_section_end && decoder_.pc() < section_end_) {
     186     1330079 :       decoder_.consume_bytes(
     187     2660158 :           static_cast<uint32_t>(section_end_ - decoder_.pc()));
     188             :     }
     189     1331696 :     if (decoder_.pc() != section_end_) {
     190         472 :       const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
     191         472 :       decoder_.errorf(decoder_.pc(),
     192             :                       "section was %s than expected size "
     193             :                       "(%u bytes expected, %zu decoded)",
     194             :                       msg, section_length(),
     195         944 :                       static_cast<size_t>(decoder_.pc() - section_start_));
     196             :     }
     197     1331696 :     next();
     198     1331716 :   }
     199             : 
     200             :  private:
     201             :   Decoder& decoder_;
     202             :   SectionCode section_code_;
     203             :   const byte* section_start_;
     204             :   const byte* payload_start_;
     205             :   const byte* section_end_;
     206             : 
     207             :   // Reads the section code/name at the current position and sets up
     208             :   // the embedder fields.
     209     1735737 :   void next() {
     210     1735737 :     if (!decoder_.more()) {
     211      280857 :       section_code_ = kUnknownSectionCode;
     212      280857 :       return;
     213             :     }
     214     1454880 :     section_start_ = decoder_.pc();
     215             :     uint8_t section_code = decoder_.consume_u8("section code");
     216             :     // Read and check the section size.
     217     1454888 :     uint32_t section_length = decoder_.consume_u32v("section length");
     218             : 
     219     1454892 :     payload_start_ = decoder_.pc();
     220     1454896 :     if (decoder_.checkAvailable(section_length)) {
     221             :       // Get the limit of the section within the module.
     222     1343044 :       section_end_ = payload_start_ + section_length;
     223             :     } else {
     224             :       // The section would extend beyond the end of the module.
     225      111852 :       section_end_ = payload_start_;
     226             :     }
     227             : 
     228     1454896 :     if (section_code == kUnknownSectionCode) {
     229             :       // Check for the known "name", "sourceMappingURL", or "compilationHints"
     230             :       // section.
     231             :       section_code =
     232       34967 :           ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
     233             :       // As a side effect, the above function will forward the decoder to after
     234             :       // the identifier string.
     235       34961 :       payload_start_ = decoder_.pc();
     236     1419929 :     } else if (!IsValidSectionCode(section_code)) {
     237      110928 :       decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
     238      110928 :                       section_code);
     239             :       section_code = kUnknownSectionCode;
     240             :     }
     241     1454897 :     section_code_ = decoder_.failed() ? kUnknownSectionCode
     242     1454897 :                                       : static_cast<SectionCode>(section_code);
     243             : 
     244     1454897 :     if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
     245             :       // skip to the end of the unknown section.
     246        3848 :       uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
     247        3848 :       decoder_.consume_bytes(remaining, "section payload");
     248             :     }
     249             :   }
     250             : };
     251             : 
     252             : }  // namespace
     253             : 
     254             : // The main logic for decoding the bytes of a module.
     255      570326 : class ModuleDecoderImpl : public Decoder {
     256             :  public:
     257             :   explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
     258             :       : Decoder(nullptr, nullptr),
     259             :         enabled_features_(enabled),
     260        1056 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
     261             : 
     262      284634 :   ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start,
     263             :                     const byte* module_end, ModuleOrigin origin)
     264             :       : Decoder(module_start, module_end),
     265             :         enabled_features_(enabled),
     266      853902 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
     267      284634 :     if (end_ < start_) {
     268           0 :       error(start_, "end is less than start");
     269           0 :       end_ = start_;
     270             :     }
     271      284634 :   }
     272             : 
     273       15545 :   void onFirstError() override {
     274       15545 :     pc_ = end_;  // On error, terminate section decoding loop.
     275       15545 :   }
     276             : 
     277             :   void DumpModule(const Vector<const byte> module_bytes) {
     278             :     std::string path;
     279             :     if (FLAG_dump_wasm_module_path) {
     280             :       path = FLAG_dump_wasm_module_path;
     281             :       if (path.size() &&
     282             :           !base::OS::isDirectorySeparator(path[path.size() - 1])) {
     283             :         path += base::OS::DirectorySeparator();
     284             :       }
     285             :     }
     286             :     // File are named `HASH.{ok,failed}.wasm`.
     287             :     size_t hash = base::hash_range(module_bytes.start(), module_bytes.end());
     288             :     EmbeddedVector<char, 32> buf;
     289             :     SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed");
     290             :     std::string name(buf.start());
     291             :     if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
     292             :       if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) !=
     293             :           1) {
     294             :         OFStream os(stderr);
     295             :         os << "Error while dumping wasm file" << std::endl;
     296             :       }
     297             :       fclose(wasm_file);
     298             :     }
     299             :   }
     300             : 
     301      284695 :   void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
     302      284695 :     CHECK_NULL(module_);
     303             :     SetCounters(counters);
     304      569400 :     module_.reset(
     305      854099 :         new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
     306      284705 :     module_->initial_pages = 0;
     307      284705 :     module_->maximum_pages = 0;
     308      284705 :     module_->mem_export = false;
     309      284705 :     module_->origin = origin_;
     310      284705 :   }
     311             : 
     312      284699 :   void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
     313      284699 :     if (failed()) return;
     314      284700 :     Reset(bytes, offset);
     315             : 
     316      284694 :     const byte* pos = pc_;
     317             :     uint32_t magic_word = consume_u32("wasm magic");
     318             : #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
     319      284704 :     if (magic_word != kWasmMagic) {
     320       21729 :       errorf(pos,
     321             :              "expected magic word %02x %02x %02x %02x, "
     322             :              "found %02x %02x %02x %02x",
     323       21729 :              BYTES(kWasmMagic), BYTES(magic_word));
     324             :     }
     325             : 
     326      284704 :     pos = pc_;
     327             :     {
     328             :       uint32_t magic_version = consume_u32("wasm version");
     329      284703 :       if (magic_version != kWasmVersion) {
     330       22905 :         errorf(pos,
     331             :                "expected version %02x %02x %02x %02x, "
     332             :                "found %02x %02x %02x %02x",
     333       22905 :                BYTES(kWasmVersion), BYTES(magic_version));
     334             :       }
     335             :     }
     336             : #undef BYTES
     337             :   }
     338             : 
     339         441 :   bool CheckSectionOrder(SectionCode section_code,
     340             :                          SectionCode prev_section_code,
     341             :                          SectionCode next_section_code) {
     342         441 :     if (next_ordered_section_ > next_section_code) {
     343           3 :       errorf(pc(), "The %s section must appear before the %s section",
     344           3 :              SectionName(section_code), SectionName(next_section_code));
     345           3 :       return false;
     346             :     }
     347         438 :     if (next_ordered_section_ <= prev_section_code) {
     348         428 :       next_ordered_section_ = prev_section_code + 1;
     349             :     }
     350             :     return true;
     351             :   }
     352             : 
     353         442 :   bool CheckUnorderedSection(SectionCode section_code) {
     354         442 :     if (has_seen_unordered_section(section_code)) {
     355           1 :       errorf(pc(), "Multiple %s sections not allowed",
     356           1 :              SectionName(section_code));
     357           1 :       return false;
     358             :     }
     359             :     set_seen_unordered_section(section_code);
     360         441 :     return true;
     361             :   }
     362             : 
     363     1288904 :   void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
     364             :                      uint32_t offset, bool verify_functions = true) {
     365     1288904 :     if (failed()) return;
     366     1288909 :     Reset(bytes, offset);
     367             :     TRACE("Section: %s\n", SectionName(section_code));
     368             :     TRACE("Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()),
     369             :           static_cast<const void*>(bytes.end()));
     370             : 
     371             :     // Check if the section is out-of-order.
     372     1288916 :     if (section_code < next_ordered_section_ &&
     373             :         section_code < kFirstUnorderedSection) {
     374          12 :       errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     375          12 :       return;
     376             :     }
     377             : 
     378     1288904 :     switch (section_code) {
     379             :       case kUnknownSectionCode:
     380             :         break;
     381             :       case kDataCountSectionCode:
     382          44 :         if (!CheckUnorderedSection(section_code)) return;
     383          43 :         if (!CheckSectionOrder(section_code, kElementSectionCode,
     384             :                                kCodeSectionCode))
     385             :           return;
     386             :         break;
     387             :       case kExceptionSectionCode:
     388         398 :         if (!CheckUnorderedSection(section_code)) return;
     389         398 :         if (!CheckSectionOrder(section_code, kGlobalSectionCode,
     390             :                                kExportSectionCode))
     391             :           return;
     392             :         break;
     393             :       case kNameSectionCode:
     394             :         // TODO(titzer): report out of place name section as a warning.
     395             :         // Be lenient with placement of name section. All except first
     396             :         // occurrence are ignored.
     397             :       case kSourceMappingURLSectionCode:
     398             :         // sourceMappingURL is a custom section and currently can occur anywhere
     399             :         // in the module. In case of multiple sourceMappingURL sections, all
     400             :         // except the first occurrence are ignored.
     401             :       case kCompilationHintsSectionCode:
     402             :         // TODO(frgossen): report out of place compilation hints section as a
     403             :         // warning.
     404             :         // Be lenient with placement of compilation hints section. All except
     405             :         // first occurrence after function section and before code section are
     406             :         // ignored.
     407             :         break;
     408             :       default:
     409     1265723 :         next_ordered_section_ = section_code + 1;
     410     1265723 :         break;
     411             :     }
     412             : 
     413     1288863 :     switch (section_code) {
     414             :       case kUnknownSectionCode:
     415             :         break;
     416             :       case kTypeSectionCode:
     417      260289 :         DecodeTypeSection();
     418      260299 :         break;
     419             :       case kImportSectionCode:
     420      232106 :         DecodeImportSection();
     421      232110 :         break;
     422             :       case kFunctionSectionCode:
     423      258430 :         DecodeFunctionSection();
     424      258434 :         break;
     425             :       case kTableSectionCode:
     426        2624 :         DecodeTableSection();
     427        2624 :         break;
     428             :       case kMemorySectionCode:
     429       10972 :         DecodeMemorySection();
     430       10972 :         break;
     431             :       case kGlobalSectionCode:
     432        2827 :         DecodeGlobalSection();
     433        2827 :         break;
     434             :       case kExportSectionCode:
     435      234116 :         DecodeExportSection();
     436      234114 :         break;
     437             :       case kStartSectionCode:
     438        2762 :         DecodeStartSection();
     439        2762 :         break;
     440             :       case kCodeSectionCode:
     441      257770 :         DecodeCodeSection(verify_functions);
     442      257774 :         break;
     443             :       case kElementSectionCode:
     444        2334 :         DecodeElementSection();
     445        2334 :         break;
     446             :       case kDataSectionCode:
     447        1466 :         DecodeDataSection();
     448        1466 :         break;
     449             :       case kNameSectionCode:
     450       22665 :         DecodeNameSection();
     451       22667 :         break;
     452             :       case kSourceMappingURLSectionCode:
     453           8 :         DecodeSourceMappingURLSection();
     454           8 :         break;
     455             :       case kCompilationHintsSectionCode:
     456          57 :         if (enabled_features_.compilation_hints) {
     457          57 :           DecodeCompilationHintsSection();
     458             :         } else {
     459             :           // Ignore this section when feature was disabled. It is an optional
     460             :           // custom section anyways.
     461             :         }
     462             :         break;
     463             :       case kDataCountSectionCode:
     464          42 :         if (enabled_features_.bulk_memory) {
     465             :           DecodeDataCountSection();
     466             :         } else {
     467           2 :           errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     468             :         }
     469             :         break;
     470             :       case kExceptionSectionCode:
     471         396 :         if (enabled_features_.eh) {
     472         386 :           DecodeExceptionSection();
     473             :         } else {
     474          10 :           errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     475             :         }
     476             :         break;
     477             :       default:
     478           0 :         errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     479           0 :         return;
     480             :     }
     481             : 
     482     1288885 :     if (pc() != bytes.end()) {
     483         132 :       const char* msg = pc() < bytes.end() ? "shorter" : "longer";
     484         132 :       errorf(pc(),
     485             :              "section was %s than expected size "
     486             :              "(%zu bytes expected, %zu decoded)",
     487         264 :              msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
     488             :     }
     489             :   }
     490             : 
     491      260288 :   void DecodeTypeSection() {
     492      260288 :     uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
     493      260294 :     module_->signatures.reserve(signatures_count);
     494     1393490 :     for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
     495             :       TRACE("DecodeSignature[%d] module+%d\n", i,
     496             :             static_cast<int>(pc_ - start_));
     497      566595 :       FunctionSig* s = consume_sig(module_->signature_zone.get());
     498      566595 :       module_->signatures.push_back(s);
     499      566595 :       uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
     500      566593 :       module_->signature_ids.push_back(id);
     501             :     }
     502             :     module_->signature_map.Freeze();
     503      260301 :   }
     504             : 
     505      232106 :   void DecodeImportSection() {
     506             :     uint32_t import_table_count =
     507      232106 :         consume_count("imports count", kV8MaxWasmImports);
     508      232112 :     module_->import_table.reserve(import_table_count);
     509      704639 :     for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
     510             :       TRACE("DecodeImportTable[%d] module+%d\n", i,
     511             :             static_cast<int>(pc_ - start_));
     512             : 
     513      472533 :       module_->import_table.push_back({
     514             :           {0, 0},             // module_name
     515             :           {0, 0},             // field_name
     516             :           kExternalFunction,  // kind
     517             :           0                   // index
     518             :       });
     519             :       WasmImport* import = &module_->import_table.back();
     520      236265 :       const byte* pos = pc_;
     521      236265 :       import->module_name = consume_string(*this, true, "module name");
     522      236263 :       import->field_name = consume_string(*this, true, "field name");
     523             :       import->kind =
     524      236253 :           static_cast<ImportExportKindCode>(consume_u8("import kind"));
     525      236253 :       switch (import->kind) {
     526             :         case kExternalFunction: {
     527             :           // ===== Imported function ===========================================
     528      227354 :           import->index = static_cast<uint32_t>(module_->functions.size());
     529      227354 :           module_->num_imported_functions++;
     530      909415 :           module_->functions.push_back({nullptr,        // sig
     531      227354 :                                         import->index,  // func_index
     532             :                                         0,              // sig_index
     533             :                                         {0, 0},         // code
     534             :                                         true,           // imported
     535             :                                         false});        // exported
     536             :           WasmFunction* function = &module_->functions.back();
     537             :           function->sig_index =
     538      227353 :               consume_sig_index(module_.get(), &function->sig);
     539      227353 :           break;
     540             :         }
     541             :         case kExternalTable: {
     542             :           // ===== Imported table ==============================================
     543        1618 :           if (!AddTable(module_.get())) break;
     544        1607 :           import->index = static_cast<uint32_t>(module_->tables.size());
     545        1607 :           module_->num_imported_tables++;
     546        1607 :           module_->tables.emplace_back();
     547             :           WasmTable* table = &module_->tables.back();
     548        1607 :           table->imported = true;
     549        1607 :           ValueType type = consume_reference_type();
     550        1607 :           if (!enabled_features_.anyref) {
     551        1545 :             if (type != kWasmAnyFunc) {
     552           0 :               error(pc_ - 1, "invalid table type");
     553           0 :               break;
     554             :             }
     555             :           }
     556        1607 :           table->type = type;
     557        1607 :           uint8_t flags = validate_table_flags("element count");
     558        1607 :           consume_resizable_limits(
     559             :               "element count", "elements", FLAG_wasm_max_table_size,
     560             :               &table->initial_size, &table->has_maximum_size,
     561        1607 :               FLAG_wasm_max_table_size, &table->maximum_size, flags);
     562        1607 :           break;
     563             :         }
     564             :         case kExternalMemory: {
     565             :           // ===== Imported memory =============================================
     566        4975 :           if (!AddMemory(module_.get())) break;
     567        4951 :           uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     568        4953 :           consume_resizable_limits(
     569             :               "memory", "pages", kSpecMaxWasmMemoryPages,
     570             :               &module_->initial_pages, &module_->has_maximum_pages,
     571        4953 :               kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
     572        4961 :           break;
     573             :         }
     574             :         case kExternalGlobal: {
     575             :           // ===== Imported global =============================================
     576        2196 :           import->index = static_cast<uint32_t>(module_->globals.size());
     577        6588 :           module_->globals.push_back(
     578             :               {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
     579             :           WasmGlobal* global = &module_->globals.back();
     580        2196 :           global->type = consume_value_type();
     581        2196 :           global->mutability = consume_mutability();
     582        2196 :           if (global->mutability) {
     583         339 :             module_->num_imported_mutable_globals++;
     584             :           }
     585             :           break;
     586             :         }
     587             :         case kExternalException: {
     588             :           // ===== Imported exception ==========================================
     589         106 :           if (!enabled_features_.eh) {
     590           1 :             errorf(pos, "unknown import kind 0x%02x", import->kind);
     591           1 :             break;
     592             :           }
     593         105 :           import->index = static_cast<uint32_t>(module_->exceptions.size());
     594         105 :           WasmExceptionSig* exception_sig = nullptr;
     595         105 :           consume_exception_attribute();  // Attribute ignored for now.
     596         105 :           consume_exception_sig_index(module_.get(), &exception_sig);
     597         105 :           module_->exceptions.emplace_back(exception_sig);
     598         105 :           break;
     599             :         }
     600             :         default:
     601           0 :           errorf(pos, "unknown import kind 0x%02x", import->kind);
     602           0 :           break;
     603             :       }
     604             :     }
     605      232113 :   }
     606             : 
     607      258422 :   void DecodeFunctionSection() {
     608             :     uint32_t functions_count =
     609      258422 :         consume_count("functions count", kV8MaxWasmFunctions);
     610             :     auto counter =
     611      258426 :         SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
     612      258426 :     counter->AddSample(static_cast<int>(functions_count));
     613             :     DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
     614             :     uint32_t total_function_count =
     615      258434 :         module_->num_imported_functions + functions_count;
     616      258434 :     module_->functions.reserve(total_function_count);
     617      258430 :     module_->num_declared_functions = functions_count;
     618     1034422 :     for (uint32_t i = 0; i < functions_count; ++i) {
     619      388034 :       uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
     620     1164103 :       module_->functions.push_back({nullptr,     // sig
     621             :                                     func_index,  // func_index
     622             :                                     0,           // sig_index
     623             :                                     {0, 0},      // code
     624             :                                     false,       // imported
     625             :                                     false});     // exported
     626             :       WasmFunction* function = &module_->functions.back();
     627      388035 :       function->sig_index = consume_sig_index(module_.get(), &function->sig);
     628      388037 :       if (!ok()) return;
     629             :     }
     630             :     DCHECK_EQ(module_->functions.size(), total_function_count);
     631             :   }
     632             : 
     633        2624 :   void DecodeTableSection() {
     634             :     // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
     635             :     // implementation of AnyRef landed.
     636        2624 :     uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
     637        2624 :     uint32_t table_count = consume_count("table count", max_count);
     638             : 
     639        7900 :     for (uint32_t i = 0; ok() && i < table_count; i++) {
     640        2654 :       if (!AddTable(module_.get())) break;
     641        2638 :       module_->tables.emplace_back();
     642             :       WasmTable* table = &module_->tables.back();
     643        2638 :       table->type = consume_reference_type();
     644        2638 :       uint8_t flags = validate_table_flags("table elements");
     645        2638 :       consume_resizable_limits(
     646             :           "table elements", "elements", FLAG_wasm_max_table_size,
     647             :           &table->initial_size, &table->has_maximum_size,
     648        2638 :           FLAG_wasm_max_table_size, &table->maximum_size, flags);
     649             :     }
     650        2624 :   }
     651             : 
     652       10972 :   void DecodeMemorySection() {
     653       10972 :     uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
     654             : 
     655       32736 :     for (uint32_t i = 0; ok() && i < memory_count; i++) {
     656       10922 :       if (!AddMemory(module_.get())) break;
     657       10882 :       uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     658       10882 :       consume_resizable_limits(
     659             :           "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
     660             :           &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
     661       10882 :           &module_->maximum_pages, flags);
     662             :     }
     663       10972 :   }
     664             : 
     665        2827 :   void DecodeGlobalSection() {
     666        2827 :     uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
     667        2827 :     uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
     668        2827 :     module_->globals.reserve(imported_globals + globals_count);
     669      885195 :     for (uint32_t i = 0; ok() && i < globals_count; ++i) {
     670             :       TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
     671             :       // Add an uninitialized global and pass a pointer to it.
     672     1323552 :       module_->globals.push_back(
     673             :           {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
     674             :       WasmGlobal* global = &module_->globals.back();
     675      441184 :       DecodeGlobalInModule(module_.get(), i + imported_globals, global);
     676             :     }
     677        2827 :     if (ok()) CalculateGlobalOffsets(module_.get());
     678        2827 :   }
     679             : 
     680      234107 :   void DecodeExportSection() {
     681             :     uint32_t export_table_count =
     682      234107 :         consume_count("exports count", kV8MaxWasmExports);
     683      234112 :     module_->export_table.reserve(export_table_count);
     684      936468 :     for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
     685             :       TRACE("DecodeExportTable[%d] module+%d\n", i,
     686             :             static_cast<int>(pc_ - start_));
     687             : 
     688      702368 :       module_->export_table.push_back({
     689             :           {0, 0},             // name
     690             :           kExternalFunction,  // kind
     691             :           0                   // index
     692             :       });
     693             :       WasmExport* exp = &module_->export_table.back();
     694             : 
     695      351183 :       exp->name = consume_string(*this, true, "field name");
     696             : 
     697             :       const byte* pos = pc();
     698      351173 :       exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
     699      351173 :       switch (exp->kind) {
     700             :         case kExternalFunction: {
     701      347406 :           WasmFunction* func = nullptr;
     702             :           exp->index =
     703      347404 :               consume_func_index(module_.get(), &func, "export function index");
     704      347404 :           module_->num_exported_functions++;
     705      347404 :           if (func) func->exported = true;
     706             :           break;
     707             :         }
     708             :         case kExternalTable: {
     709         768 :           WasmTable* table = nullptr;
     710         768 :           exp->index = consume_table_index(module_.get(), &table);
     711         768 :           if (table) table->exported = true;
     712             :           break;
     713             :         }
     714             :         case kExternalMemory: {
     715             :           uint32_t index = consume_u32v("memory index");
     716             :           // TODO(titzer): This should become more regular
     717             :           // once we support multiple memories.
     718        1740 :           if (!module_->has_memory || index != 0) {
     719          24 :             error("invalid memory index != 0");
     720             :           }
     721        1740 :           module_->mem_export = true;
     722        1740 :           break;
     723             :         }
     724             :         case kExternalGlobal: {
     725        1114 :           WasmGlobal* global = nullptr;
     726        1114 :           exp->index = consume_global_index(module_.get(), &global);
     727        1114 :           if (global) {
     728        1098 :             global->exported = true;
     729             :           }
     730             :           break;
     731             :         }
     732             :         case kExternalException: {
     733         145 :           if (!enabled_features_.eh) {
     734           0 :             errorf(pos, "invalid export kind 0x%02x", exp->kind);
     735           0 :             break;
     736             :           }
     737         145 :           WasmException* exception = nullptr;
     738         145 :           exp->index = consume_exception_index(module_.get(), &exception);
     739         145 :           break;
     740             :         }
     741             :         default:
     742           0 :           errorf(pos, "invalid export kind 0x%02x", exp->kind);
     743           0 :           break;
     744             :       }
     745             :     }
     746             :     // Check for duplicate exports (except for asm.js).
     747      465654 :     if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
     748        7602 :       std::vector<WasmExport> sorted_exports(module_->export_table);
     749             : 
     750     1107862 :       auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
     751             :         // Return true if a < b.
     752      631566 :         if (a.name.length() != b.name.length()) {
     753      155270 :           return a.name.length() < b.name.length();
     754             :         }
     755      476296 :         const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
     756      476296 :         const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
     757      476296 :         return memcmp(left, right, a.name.length()) < 0;
     758        7602 :       };
     759             :       std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
     760             : 
     761             :       auto it = sorted_exports.begin();
     762             :       WasmExport* last = &*it++;
     763      237482 :       for (auto end = sorted_exports.end(); it != end; last = &*it++) {
     764             :         DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
     765      115268 :         if (!cmp_less(*last, *it)) {
     766         328 :           const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
     767         328 :           TruncatedUserString<> name(pc, it->name.length());
     768         984 :           errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
     769         328 :                  name.length(), name.start(), ExternalKindName(last->kind),
     770         656 :                  last->index, ExternalKindName(it->kind), it->index);
     771             :           break;
     772             :         }
     773             :       }
     774             :     }
     775      234112 :   }
     776             : 
     777        2762 :   void DecodeStartSection() {
     778             :     WasmFunction* func;
     779        2762 :     const byte* pos = pc_;
     780             :     module_->start_function_index =
     781        2762 :         consume_func_index(module_.get(), &func, "start function index");
     782        8246 :     if (func &&
     783        5404 :         (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
     784          64 :       error(pos, "invalid start function: non-zero parameter or return count");
     785             :     }
     786        2762 :   }
     787             : 
     788        2334 :   void DecodeElementSection() {
     789             :     uint32_t element_count =
     790        2334 :         consume_count("element count", FLAG_wasm_max_table_size);
     791             : 
     792        4648 :     if (element_count > 0 && module_->tables.size() == 0) {
     793          49 :       error(pc_, "The element section requires a table");
     794             :     }
     795        7868 :     for (uint32_t i = 0; ok() && i < element_count; ++i) {
     796             :       const byte* pos = pc();
     797             : 
     798             :       bool is_active;
     799             :       uint32_t table_index;
     800             :       WasmInitExpr offset;
     801        2899 :       consume_segment_header("table index", &is_active, &table_index, &offset);
     802        3028 :       if (failed()) return;
     803             : 
     804        2770 :       if (is_active) {
     805        5448 :         if (table_index >= module_->tables.size()) {
     806           0 :           errorf(pos, "out of bounds table index %u", table_index);
     807           0 :           break;
     808             :         }
     809        2724 :         if (module_->tables[table_index].type != kWasmAnyFunc) {
     810           2 :           errorf(pos,
     811             :                  "Invalid element segment. Table %u is not of type AnyFunc",
     812           2 :                  table_index);
     813           2 :           break;
     814             :         }
     815             :       } else {
     816          46 :         ValueType type = consume_reference_type();
     817          46 :         if (type != kWasmAnyFunc) {
     818           1 :           error(pc_ - 1, "invalid element segment type");
     819           1 :           break;
     820             :         }
     821             :       }
     822             : 
     823             :       uint32_t num_elem =
     824        2767 :           consume_count("number of elements", max_table_init_entries());
     825        2767 :       if (is_active) {
     826        2722 :         module_->elem_segments.emplace_back(table_index, offset);
     827             :       } else {
     828          45 :         module_->elem_segments.emplace_back();
     829             :       }
     830             : 
     831             :       WasmElemSegment* init = &module_->elem_segments.back();
     832       20033 :       for (uint32_t j = 0; j < num_elem; j++) {
     833             :         uint32_t index = is_active ? consume_element_func_index()
     834        8817 :                                    : consume_passive_element();
     835        8650 :         if (failed()) break;
     836        8633 :         init->entries.push_back(index);
     837             :       }
     838             :     }
     839             :   }
     840             : 
     841      257760 :   void DecodeCodeSection(bool verify_functions) {
     842             :     uint32_t pos = pc_offset();
     843      257760 :     uint32_t functions_count = consume_u32v("functions count");
     844      257764 :     CheckFunctionsCount(functions_count, pos);
     845     1031472 :     for (uint32_t i = 0; ok() && i < functions_count; ++i) {
     846             :       const byte* pos = pc();
     847             :       uint32_t size = consume_u32v("body size");
     848      386851 :       if (size > kV8MaxWasmFunctionSize) {
     849             :         errorf(pos, "size %u > maximum function size %zu", size,
     850           3 :                kV8MaxWasmFunctionSize);
     851           3 :         return;
     852             :       }
     853             :       uint32_t offset = pc_offset();
     854      386848 :       consume_bytes(size, "function body");
     855      386853 :       if (failed()) break;
     856      386852 :       DecodeFunctionBody(i, size, offset, verify_functions);
     857             :     }
     858             :   }
     859             : 
     860      257989 :   bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
     861      257989 :     if (functions_count != module_->num_declared_functions) {
     862          79 :       Reset(nullptr, nullptr, offset);
     863          79 :       errorf(nullptr, "function body count %u mismatch (%u expected)",
     864          79 :              functions_count, module_->num_declared_functions);
     865          79 :       return false;
     866             :     }
     867             :     return true;
     868             :   }
     869             : 
     870      387305 :   void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
     871             :                           bool verify_functions) {
     872             :     WasmFunction* function =
     873      387305 :         &module_->functions[index + module_->num_imported_functions];
     874      387305 :     function->code = {offset, length};
     875      387305 :     if (verify_functions) {
     876      136690 :       ModuleWireBytes bytes(start_, end_);
     877      136690 :       VerifyFunctionBody(module_->signature_zone->allocator(),
     878      136690 :                          index + module_->num_imported_functions, bytes,
     879      136690 :                          module_.get(), function);
     880             :     }
     881      387305 :   }
     882             : 
     883      267557 :   bool CheckDataSegmentsCount(uint32_t data_segments_count) {
     884      267627 :     if (has_seen_unordered_section(kDataCountSectionCode) &&
     885          70 :         data_segments_count != module_->num_declared_data_segments) {
     886           3 :       errorf(pc(), "data segments count %u mismatch (%u expected)",
     887           3 :              data_segments_count, module_->num_declared_data_segments);
     888           3 :       return false;
     889             :     }
     890             :     return true;
     891             :   }
     892             : 
     893        1466 :   void DecodeDataSection() {
     894             :     uint32_t data_segments_count =
     895        1466 :         consume_count("data segments count", kV8MaxWasmDataSegments);
     896        1466 :     if (!CheckDataSegmentsCount(data_segments_count)) return;
     897             : 
     898        1464 :     module_->data_segments.reserve(data_segments_count);
     899        4926 :     for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
     900             :       const byte* pos = pc();
     901        1881 :       if (!module_->has_memory) {
     902          65 :         error("cannot load data without memory");
     903          65 :         break;
     904             :       }
     905             :       TRACE("DecodeDataSegment[%d] module+%d\n", i,
     906             :             static_cast<int>(pc_ - start_));
     907             : 
     908             :       bool is_active;
     909             :       uint32_t memory_index;
     910             :       WasmInitExpr dest_addr;
     911             :       consume_segment_header("memory index", &is_active, &memory_index,
     912        1816 :                              &dest_addr);
     913        1816 :       if (failed()) break;
     914             : 
     915        1732 :       if (is_active && memory_index != 0) {
     916           0 :         errorf(pos, "illegal memory index %u != 0", memory_index);
     917           0 :         break;
     918             :       }
     919             : 
     920        1732 :       uint32_t source_length = consume_u32v("source size");
     921             :       uint32_t source_offset = pc_offset();
     922             : 
     923        1732 :       if (is_active) {
     924        1691 :         module_->data_segments.emplace_back(dest_addr);
     925             :       } else {
     926          41 :         module_->data_segments.emplace_back();
     927             :       }
     928             : 
     929             :       WasmDataSegment* segment = &module_->data_segments.back();
     930             : 
     931        1732 :       consume_bytes(source_length, "segment data");
     932        1732 :       if (failed()) break;
     933             : 
     934        1731 :       segment->source = {source_offset, source_length};
     935             :     }
     936             :   }
     937             : 
     938       22657 :   void DecodeNameSection() {
     939             :     // TODO(titzer): find a way to report name errors as warnings.
     940             :     // Ignore all but the first occurrence of name section.
     941       22657 :     if (!has_seen_unordered_section(kNameSectionCode)) {
     942             :       set_seen_unordered_section(kNameSectionCode);
     943             :       // Use an inner decoder so that errors don't fail the outer decoder.
     944       22657 :       Decoder inner(start_, pc_, end_, buffer_offset_);
     945             :       // Decode all name subsections.
     946             :       // Be lenient with their order.
     947       45403 :       while (inner.ok() && inner.more()) {
     948             :         uint8_t name_type = inner.consume_u8("name type");
     949       22773 :         if (name_type & 0x80) inner.error("name type if not varuint7");
     950             : 
     951             :         uint32_t name_payload_len = inner.consume_u32v("name payload length");
     952       22770 :         if (!inner.checkAvailable(name_payload_len)) break;
     953             : 
     954             :         // Decode module name, ignore the rest.
     955             :         // Function and local names will be decoded when needed.
     956       22744 :         if (name_type == NameSectionKindCode::kModule) {
     957         139 :           WireBytesRef name = consume_string(inner, false, "module name");
     958         196 :           if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
     959             :         } else {
     960       22605 :           inner.consume_bytes(name_payload_len, "name subsection payload");
     961             :         }
     962             :       }
     963             :     }
     964             :     // Skip the whole names section in the outer decoder.
     965       22655 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     966       22667 :   }
     967             : 
     968           8 :   void DecodeSourceMappingURLSection() {
     969           8 :     Decoder inner(start_, pc_, end_, buffer_offset_);
     970           8 :     WireBytesRef url = wasm::consume_string(inner, true, "module name");
     971          15 :     if (inner.ok() &&
     972             :         !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
     973             :       const byte* url_start =
     974           6 :           inner.start() + inner.GetBufferRelativeOffset(url.offset());
     975             :       module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
     976           6 :                                      url.length());
     977             :       set_seen_unordered_section(kSourceMappingURLSectionCode);
     978             :     }
     979           8 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     980           8 :   }
     981             : 
     982          57 :   void DecodeCompilationHintsSection() {
     983             :     TRACE("DecodeCompilationHints module+%d\n", static_cast<int>(pc_ - start_));
     984             : 
     985             :     // TODO(frgossen): Find a way to report compilation hint errors as warnings.
     986             :     // All except first occurrence after function section and before code
     987             :     // section are ignored.
     988             :     const bool before_function_section =
     989          57 :         next_ordered_section_ <= kFunctionSectionCode;
     990          57 :     const bool after_code_section = next_ordered_section_ > kCodeSectionCode;
     991         114 :     if (before_function_section || after_code_section ||
     992             :         has_seen_unordered_section(kCompilationHintsSectionCode)) {
     993             :       return;
     994             :     }
     995             :     set_seen_unordered_section(kCompilationHintsSectionCode);
     996             : 
     997             :     // TODO(frgossen) Propagate errors to outer decoder in experimental phase.
     998             :     // We should use an inner decoder later and propagate its errors as
     999             :     // warnings.
    1000          57 :     Decoder& decoder = *this;
    1001             :     // Decoder decoder(start_, pc_, end_, buffer_offset_);
    1002             : 
    1003             :     // Ensure exactly one compilation hint per function.
    1004             :     uint32_t hint_count = decoder.consume_u32v("compilation hint count");
    1005          57 :     if (hint_count != module_->num_declared_functions) {
    1006             :       decoder.errorf(decoder.pc(), "Expected %u compilation hints (%u found)",
    1007           0 :                      module_->num_declared_functions, hint_count);
    1008             :     }
    1009             : 
    1010             :     // Decode sequence of compilation hints.
    1011          57 :     if (decoder.ok()) module_->compilation_hints.reserve(hint_count);
    1012         239 :     for (uint32_t i = 0; decoder.ok() && i < hint_count; i++) {
    1013             :       TRACE("DecodeCompilationHints[%d] module+%d\n", i,
    1014             :             static_cast<int>(pc_ - start_));
    1015             : 
    1016             :       // Compilation hints are encoded in one byte each.
    1017             :       // +-------+-------------+------------+------------------+
    1018             :       // | 2 bit | 2 bit       | 2 bit      | 2 bit            |
    1019             :       // | ...   | Second tier | First tier | Lazy compilation |
    1020             :       // +-------+-------------+------------+------------------+
    1021             :       uint8_t hint_byte = decoder.consume_u8("compilation hint");
    1022          91 :       if (!decoder.ok()) break;
    1023             : 
    1024             :       // Decode compilation hint.
    1025             :       WasmCompilationHint hint;
    1026             :       hint.strategy =
    1027          91 :           static_cast<WasmCompilationHintStrategy>(hint_byte & 0x03);
    1028             :       hint.first_tier =
    1029          91 :           static_cast<WasmCompilationHintTier>(hint_byte >> 2 & 0x3);
    1030             :       hint.second_tier =
    1031          91 :           static_cast<WasmCompilationHintTier>(hint_byte >> 4 & 0x3);
    1032             : 
    1033             :       // Check strategy.
    1034          91 :       if (hint.strategy > WasmCompilationHintStrategy::kEager) {
    1035             :         decoder.errorf(decoder.pc(),
    1036             :                        "Invalid compilation hint %#x (unknown strategy)",
    1037           8 :                        hint_byte);
    1038             :       }
    1039             : 
    1040             :       // Ensure that the second tier never downgrades the compilation result.
    1041             :       // If first and secod tier are the same it will be invoked only once.
    1042          91 :       if (hint.second_tier < hint.first_tier &&
    1043             :           hint.second_tier != WasmCompilationHintTier::kDefault) {
    1044             :         decoder.errorf(decoder.pc(),
    1045             :                        "Invalid compilation hint %#x (forbidden downgrade)",
    1046           8 :                        hint_byte);
    1047             :       }
    1048             : 
    1049             :       // Happily accept compilation hint.
    1050          91 :       if (decoder.ok()) module_->compilation_hints.push_back(std::move(hint));
    1051             :     }
    1052             : 
    1053             :     // If section was invalid reset compilation hints.
    1054          57 :     if (decoder.failed()) {
    1055             :       module_->compilation_hints.clear();
    1056             :     }
    1057             : 
    1058             :     // @TODO(frgossen) Skip the whole compilation hints section in the outer
    1059             :     // decoder if inner decoder was used.
    1060             :     // consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
    1061             :   }
    1062             : 
    1063             :   void DecodeDataCountSection() {
    1064             :     module_->num_declared_data_segments =
    1065          40 :         consume_count("data segments count", kV8MaxWasmDataSegments);
    1066             :   }
    1067             : 
    1068         386 :   void DecodeExceptionSection() {
    1069             :     uint32_t exception_count =
    1070         386 :         consume_count("exception count", kV8MaxWasmExceptions);
    1071        1264 :     for (uint32_t i = 0; ok() && i < exception_count; ++i) {
    1072             :       TRACE("DecodeException[%d] module+%d\n", i,
    1073             :             static_cast<int>(pc_ - start_));
    1074         439 :       WasmExceptionSig* exception_sig = nullptr;
    1075         439 :       consume_exception_attribute();  // Attribute ignored for now.
    1076         439 :       consume_exception_sig_index(module_.get(), &exception_sig);
    1077         439 :       module_->exceptions.emplace_back(exception_sig);
    1078             :     }
    1079         386 :   }
    1080             : 
    1081      266112 :   bool CheckMismatchedCounts() {
    1082             :     // The declared vs. defined function count is normally checked when
    1083             :     // decoding the code section, but we have to check it here too in case the
    1084             :     // code section is absent.
    1085      266112 :     if (module_->num_declared_functions != 0) {
    1086             :       DCHECK_LT(module_->num_imported_functions, module_->functions.size());
    1087             :       // We know that the code section has been decoded if the first
    1088             :       // non-imported function has its code set.
    1089      515470 :       if (!module_->functions[module_->num_imported_functions].code.is_set()) {
    1090          22 :         errorf(pc(), "function count is %u, but code section is absent",
    1091          22 :                module_->num_declared_functions);
    1092          22 :         return false;
    1093             :       }
    1094             :     }
    1095             :     // Perform a similar check for the DataCount and Data sections, where data
    1096             :     // segments are declared but the Data section is absent.
    1097      266090 :     if (!CheckDataSegmentsCount(
    1098             :             static_cast<uint32_t>(module_->data_segments.size()))) {
    1099             :       return false;
    1100             :     }
    1101      266088 :     return true;
    1102             :   }
    1103             : 
    1104      281455 :   ModuleResult FinishDecoding(bool verify_functions = true) {
    1105      281455 :     if (ok() && CheckMismatchedCounts()) {
    1106      266089 :       CalculateGlobalOffsets(module_.get());
    1107             :     }
    1108      844374 :     ModuleResult result = toResult(std::move(module_));
    1109      281459 :     if (verify_functions && result.ok() && intermediate_error_.has_error()) {
    1110             :       // Copy error message and location.
    1111       15234 :       return ModuleResult{std::move(intermediate_error_)};
    1112             :     }
    1113             :     return result;
    1114             :   }
    1115             : 
    1116             :   // Decodes an entire module.
    1117      284346 :   ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
    1118             :                             bool verify_functions = true) {
    1119      284346 :     StartDecoding(counters, allocator);
    1120             :     uint32_t offset = 0;
    1121      284353 :     Vector<const byte> orig_bytes(start(), end() - start());
    1122      284353 :     DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
    1123      284351 :     if (failed()) {
    1124       15238 :       return FinishDecoding(verify_functions);
    1125             :     }
    1126             :     // Size of the module header.
    1127             :     offset += 8;
    1128      276732 :     Decoder decoder(start_ + offset, end_, offset);
    1129             : 
    1130             :     WasmSectionIterator section_iter(decoder);
    1131             : 
    1132     4412049 :     while (ok() && section_iter.more()) {
    1133             :       // Shift the offset by the section header length
    1134     1288765 :       offset += section_iter.payload_start() - section_iter.section_start();
    1135     1288765 :       if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
    1136     2576206 :         DecodeSection(section_iter.section_code(), section_iter.payload(),
    1137     1288103 :                       offset, verify_functions);
    1138             :       }
    1139             :       // Shift the offset by the remaining section payload
    1140     1288762 :       offset += section_iter.payload_length();
    1141     1288762 :       section_iter.advance(true);
    1142             :     }
    1143             : 
    1144             :     if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
    1145             : 
    1146      276730 :     if (decoder.failed()) {
    1147        6166 :       return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
    1148             :     }
    1149             : 
    1150      547290 :     return FinishDecoding(verify_functions);
    1151             :   }
    1152             : 
    1153             :   // Decodes a single anonymous function starting at {start_}.
    1154           1 :   FunctionResult DecodeSingleFunction(Zone* zone,
    1155             :                                       const ModuleWireBytes& wire_bytes,
    1156             :                                       const WasmModule* module,
    1157             :                                       std::unique_ptr<WasmFunction> function) {
    1158           1 :     pc_ = start_;
    1159           1 :     function->sig = consume_sig(zone);
    1160           2 :     function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
    1161             : 
    1162           1 :     if (ok())
    1163             :       VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
    1164           1 :                          function.get());
    1165             : 
    1166           1 :     if (intermediate_error_.has_error()) {
    1167           0 :       return FunctionResult{std::move(intermediate_error_)};
    1168             :     }
    1169             : 
    1170           1 :     return FunctionResult(std::move(function));
    1171             :   }
    1172             : 
    1173             :   // Decodes a single function signature at {start}.
    1174             :   FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
    1175         262 :     pc_ = start;
    1176         262 :     FunctionSig* result = consume_sig(zone);
    1177         262 :     return ok() ? result : nullptr;
    1178             :   }
    1179             : 
    1180             :   WasmInitExpr DecodeInitExpr(const byte* start) {
    1181          22 :     pc_ = start;
    1182          22 :     return consume_init_expr(nullptr, kWasmStmt);
    1183             :   }
    1184             : 
    1185         668 :   const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
    1186             : 
    1187             :   Counters* GetCounters() const {
    1188             :     DCHECK_NOT_NULL(counters_);
    1189             :     return counters_;
    1190             :   }
    1191             : 
    1192             :   void SetCounters(Counters* counters) {
    1193             :     DCHECK_NULL(counters_);
    1194      284696 :     counters_ = counters;
    1195             :   }
    1196             : 
    1197             :  private:
    1198             :   const WasmFeatures enabled_features_;
    1199             :   std::shared_ptr<WasmModule> module_;
    1200             :   Counters* counters_ = nullptr;
    1201             :   // The type section is the first section in a module.
    1202             :   uint8_t next_ordered_section_ = kFirstSectionInModule;
    1203             :   // We store next_ordered_section_ as uint8_t instead of SectionCode so that
    1204             :   // we can increment it. This static_assert should make sure that SectionCode
    1205             :   // does not get bigger than uint8_t accidentially.
    1206             :   static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
    1207             :                     sizeof(SectionCode),
    1208             :                 "type mismatch");
    1209             :   uint32_t seen_unordered_sections_ = 0;
    1210             :   static_assert(kBitsPerByte *
    1211             :                         sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
    1212             :                     kLastKnownModuleSection,
    1213             :                 "not enough bits");
    1214             :   WasmError intermediate_error_;
    1215             :   ModuleOrigin origin_;
    1216             : 
    1217             :   bool has_seen_unordered_section(SectionCode section_code) {
    1218      290720 :     return seen_unordered_sections_ & (1 << section_code);
    1219             :   }
    1220             : 
    1221             :   void set_seen_unordered_section(SectionCode section_code) {
    1222       23161 :     seen_unordered_sections_ |= 1 << section_code;
    1223             :   }
    1224             : 
    1225             :   uint32_t off(const byte* ptr) {
    1226           1 :     return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
    1227             :   }
    1228             : 
    1229             :   bool AddTable(WasmModule* module) {
    1230        4277 :     if (enabled_features_.anyref) return true;
    1231        4105 :     if (module->tables.size() > 0) {
    1232          32 :       error("At most one table is supported");
    1233             :       return false;
    1234             :     } else {
    1235             :       return true;
    1236             :     }
    1237             :   }
    1238             : 
    1239             :   bool AddMemory(WasmModule* module) {
    1240       15896 :     if (module->has_memory) {
    1241          64 :       error("At most one memory is supported");
    1242             :       return false;
    1243             :     } else {
    1244       15832 :       module->has_memory = true;
    1245             :       return true;
    1246             :     }
    1247             :   }
    1248             : 
    1249             :   // Decodes a single global entry inside a module starting at {pc_}.
    1250      441184 :   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
    1251             :                             WasmGlobal* global) {
    1252      441184 :     global->type = consume_value_type();
    1253      441184 :     global->mutability = consume_mutability();
    1254             :     const byte* pos = pc();
    1255      441184 :     global->init = consume_init_expr(module, kWasmStmt);
    1256      441184 :     if (global->init.kind == WasmInitExpr::kGlobalIndex) {
    1257          65 :       uint32_t other_index = global->init.val.global_index;
    1258          65 :       if (other_index >= index) {
    1259           0 :         errorf(pos,
    1260             :                "invalid global index in init expression, "
    1261             :                "index %u, other_index %u",
    1262           0 :                index, other_index);
    1263         130 :       } else if (module->globals[other_index].type != global->type) {
    1264           0 :         errorf(pos,
    1265             :                "type mismatch in global initialization "
    1266             :                "(from global #%u), expected %s, got %s",
    1267             :                other_index, ValueTypes::TypeName(global->type),
    1268           0 :                ValueTypes::TypeName(module->globals[other_index].type));
    1269             :       }
    1270             :     } else {
    1271      441119 :       if (!ValueTypes::IsSubType(global->type, TypeOf(module, global->init))) {
    1272         384 :         errorf(pos, "type error in global initialization, expected %s, got %s",
    1273             :                ValueTypes::TypeName(global->type),
    1274         384 :                ValueTypes::TypeName(TypeOf(module, global->init)));
    1275             :       }
    1276             :     }
    1277      441184 :   }
    1278             : 
    1279             :   // Calculate individual global offsets and total size of globals table.
    1280      268515 :   void CalculateGlobalOffsets(WasmModule* module) {
    1281             :     uint32_t untagged_offset = 0;
    1282             :     uint32_t tagged_offset = 0;
    1283             :     uint32_t num_imported_mutable_globals = 0;
    1284     1152700 :     for (WasmGlobal& global : module->globals) {
    1285      884185 :       if (global.mutability && global.imported) {
    1286         361 :         global.index = num_imported_mutable_globals++;
    1287     1767648 :       } else if (ValueTypes::IsReferenceType(global.type)) {
    1288         534 :         global.offset = tagged_offset;
    1289             :         // All entries in the tagged_globals_buffer have size 1.
    1290         534 :         tagged_offset++;
    1291             :       } else {
    1292             :         byte size =
    1293      883290 :             ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
    1294      883290 :         untagged_offset = (untagged_offset + size - 1) & ~(size - 1);  // align
    1295      883290 :         global.offset = untagged_offset;
    1296      883290 :         untagged_offset += size;
    1297             :       }
    1298             :     }
    1299      268515 :     module->untagged_globals_buffer_size = untagged_offset;
    1300      268515 :     module->tagged_globals_buffer_size = tagged_offset;
    1301      268515 :   }
    1302             : 
    1303             :   // Verifies the body (code) of a given function.
    1304      136691 :   void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
    1305             :                           const ModuleWireBytes& wire_bytes,
    1306             :                           const WasmModule* module, WasmFunction* function) {
    1307             :     WasmFunctionName func_name(function,
    1308      136691 :                                wire_bytes.GetNameOrNull(function, module));
    1309             :     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
    1310             :       StdoutStream os;
    1311             :       os << "Verifying wasm function " << func_name << std::endl;
    1312             :     }
    1313             :     FunctionBody body = {
    1314             :         function->sig, function->code.offset(),
    1315      136691 :         start_ + GetBufferRelativeOffset(function->code.offset()),
    1316      410073 :         start_ + GetBufferRelativeOffset(function->code.end_offset())};
    1317             : 
    1318             :     DecodeResult result;
    1319             :     {
    1320      136691 :       auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
    1321             :                                               wasm_decode, function_time);
    1322             : 
    1323             :       TimedHistogramScope wasm_decode_function_time_scope(time_counter);
    1324      136691 :       WasmFeatures unused_detected_features;
    1325      273382 :       result = VerifyWasmCode(allocator, enabled_features_, module,
    1326             :                               &unused_detected_features, body);
    1327             :     }
    1328             : 
    1329             :     // If the decode failed and this is the first error, set error code and
    1330             :     // location.
    1331      136691 :     if (result.failed() && intermediate_error_.empty()) {
    1332             :       // Wrap the error message from the function decoder.
    1333       15298 :       std::ostringstream error_msg;
    1334        7649 :       error_msg << "in function " << func_name << ": "
    1335             :                 << result.error().message();
    1336       15298 :       intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
    1337             :     }
    1338      136691 :   }
    1339             : 
    1340      615931 :   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
    1341      615931 :     const byte* pos = pc_;
    1342      615931 :     uint32_t sig_index = consume_u32v("signature index");
    1343     1231866 :     if (sig_index >= module->signatures.size()) {
    1344        5740 :       errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
    1345        5740 :              static_cast<int>(module->signatures.size()));
    1346        5740 :       *sig = nullptr;
    1347        5740 :       return 0;
    1348             :     }
    1349      610193 :     *sig = module->signatures[sig_index];
    1350      610193 :     return sig_index;
    1351             :   }
    1352             : 
    1353         544 :   uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
    1354         544 :     const byte* pos = pc_;
    1355         544 :     uint32_t sig_index = consume_sig_index(module, sig);
    1356         544 :     if (*sig && (*sig)->return_count() != 0) {
    1357           2 :       errorf(pos, "exception signature %u has non-void return", sig_index);
    1358           2 :       *sig = nullptr;
    1359           2 :       return 0;
    1360             :     }
    1361             :     return sig_index;
    1362             :   }
    1363             : 
    1364     2141796 :   uint32_t consume_count(const char* name, size_t maximum) {
    1365     2141796 :     const byte* p = pc_;
    1366     2141796 :     uint32_t count = consume_u32v(name);
    1367     2141811 :     if (count > maximum) {
    1368         118 :       errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
    1369         118 :       return static_cast<uint32_t>(maximum);
    1370             :     }
    1371             :     return count;
    1372             :   }
    1373             : 
    1374             :   uint32_t consume_func_index(WasmModule* module, WasmFunction** func,
    1375             :                               const char* name) {
    1376      358805 :     return consume_index(name, module->functions, func);
    1377             :   }
    1378             : 
    1379             :   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
    1380        1114 :     return consume_index("global index", module->globals, global);
    1381             :   }
    1382             : 
    1383             :   uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
    1384         768 :     return consume_index("table index", module->tables, table);
    1385             :   }
    1386             : 
    1387             :   uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
    1388         145 :     return consume_index("exception index", module->exceptions, except);
    1389             :   }
    1390             : 
    1391             :   template <typename T>
    1392      360830 :   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
    1393      360830 :     const byte* pos = pc_;
    1394      360830 :     uint32_t index = consume_u32v(name);
    1395      721670 :     if (index >= vector.size()) {
    1396         115 :       errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
    1397             :              static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
    1398         115 :       *ptr = nullptr;
    1399         115 :       return 0;
    1400             :     }
    1401      360720 :     *ptr = &vector[index];
    1402      360720 :     return index;
    1403             :   }
    1404             : 
    1405        4245 :   uint8_t validate_table_flags(const char* name) {
    1406        4245 :     uint8_t flags = consume_u8("resizable limits flags");
    1407             :     const byte* pos = pc();
    1408        4245 :     if (flags & 0xFE) {
    1409           8 :       errorf(pos - 1, "invalid %s limits flags", name);
    1410             :     }
    1411        4245 :     return flags;
    1412             :   }
    1413             : 
    1414       15833 :   uint8_t validate_memory_flags(bool* has_shared_memory) {
    1415       15833 :     uint8_t flags = consume_u8("resizable limits flags");
    1416             :     const byte* pos = pc();
    1417       15831 :     *has_shared_memory = false;
    1418       15831 :     if (enabled_features_.threads) {
    1419        1547 :       if (flags & 0xFC) {
    1420           0 :         errorf(pos - 1, "invalid memory limits flags");
    1421        1547 :       } else if (flags == 3) {
    1422             :         DCHECK_NOT_NULL(has_shared_memory);
    1423        1471 :         *has_shared_memory = true;
    1424          76 :       } else if (flags == 2) {
    1425           8 :         errorf(pos - 1,
    1426             :                "memory limits flags should have maximum defined if shared is "
    1427           8 :                "true");
    1428             :       }
    1429             :     } else {
    1430       14284 :       if (flags & 0xFE) {
    1431          16 :         errorf(pos - 1, "invalid memory limits flags");
    1432             :       }
    1433             :     }
    1434       15831 :     return flags;
    1435             :   }
    1436             : 
    1437       20080 :   void consume_resizable_limits(const char* name, const char* units,
    1438             :                                 uint32_t max_initial, uint32_t* initial,
    1439             :                                 bool* has_max, uint32_t max_maximum,
    1440             :                                 uint32_t* maximum, uint8_t flags) {
    1441             :     const byte* pos = pc();
    1442       40162 :     *initial = consume_u32v("initial size");
    1443       20082 :     *has_max = false;
    1444       20082 :     if (*initial > max_initial) {
    1445             :       errorf(pos,
    1446             :              "initial %s size (%u %s) is larger than implementation limit (%u)",
    1447          56 :              name, *initial, units, max_initial);
    1448             :     }
    1449       20083 :     if (flags & 1) {
    1450        6102 :       *has_max = true;
    1451             :       pos = pc();
    1452        6108 :       *maximum = consume_u32v("maximum size");
    1453        6108 :       if (*maximum > max_maximum) {
    1454             :         errorf(
    1455             :             pos,
    1456             :             "maximum %s size (%u %s) is larger than implementation limit (%u)",
    1457          57 :             name, *maximum, units, max_maximum);
    1458             :       }
    1459        6107 :       if (*maximum < *initial) {
    1460             :         errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
    1461          16 :                name, *maximum, units, *initial, units);
    1462             :       }
    1463             :     } else {
    1464       13981 :       *has_max = false;
    1465       13981 :       *maximum = max_initial;
    1466             :     }
    1467       20088 :   }
    1468             : 
    1469     1012855 :   bool expect_u8(const char* name, uint8_t expected) {
    1470             :     const byte* pos = pc();
    1471     1012855 :     uint8_t value = consume_u8(name);
    1472     1012856 :     if (value != expected) {
    1473         680 :       errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
    1474         680 :       return false;
    1475             :     }
    1476             :     return true;
    1477             :   }
    1478             : 
    1479      445834 :   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
    1480             :     const byte* pos = pc();
    1481      445834 :     uint8_t opcode = consume_u8("opcode");
    1482             :     WasmInitExpr expr;
    1483             :     uint32_t len = 0;
    1484      445834 :     switch (opcode) {
    1485             :       case kExprGetGlobal: {
    1486             :         GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
    1487         396 :         if (module->globals.size() <= imm.index) {
    1488          16 :           error("global index is out of bounds");
    1489          16 :           expr.kind = WasmInitExpr::kNone;
    1490          16 :           expr.val.i32_const = 0;
    1491          16 :           break;
    1492             :         }
    1493             :         WasmGlobal* global = &module->globals[imm.index];
    1494         380 :         if (global->mutability || !global->imported) {
    1495             :           error(
    1496             :               "only immutable imported globals can be used in initializer "
    1497          18 :               "expressions");
    1498          18 :           expr.kind = WasmInitExpr::kNone;
    1499          18 :           expr.val.i32_const = 0;
    1500          18 :           break;
    1501             :         }
    1502         362 :         expr.kind = WasmInitExpr::kGlobalIndex;
    1503         362 :         expr.val.global_index = imm.index;
    1504         362 :         len = imm.length;
    1505         362 :         break;
    1506             :       }
    1507             :       case kExprI32Const: {
    1508             :         ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1509        8093 :         expr.kind = WasmInitExpr::kI32Const;
    1510        8093 :         expr.val.i32_const = imm.value;
    1511        8093 :         len = imm.length;
    1512             :         break;
    1513             :       }
    1514             :       case kExprF32Const: {
    1515      436042 :         ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1516      436042 :         expr.kind = WasmInitExpr::kF32Const;
    1517      436042 :         expr.val.f32_const = imm.value;
    1518      436042 :         len = imm.length;
    1519             :         break;
    1520             :       }
    1521             :       case kExprI64Const: {
    1522             :         ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1523         316 :         expr.kind = WasmInitExpr::kI64Const;
    1524         316 :         expr.val.i64_const = imm.value;
    1525         316 :         len = imm.length;
    1526             :         break;
    1527             :       }
    1528             :       case kExprF64Const: {
    1529         575 :         ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1530         575 :         expr.kind = WasmInitExpr::kF64Const;
    1531         575 :         expr.val.f64_const = imm.value;
    1532         575 :         len = imm.length;
    1533             :         break;
    1534             :       }
    1535             :       case kExprRefNull: {
    1536         234 :         if (enabled_features_.anyref || enabled_features_.eh) {
    1537         234 :           expr.kind = WasmInitExpr::kRefNullConst;
    1538             :           len = 0;
    1539         234 :           break;
    1540             :         }
    1541             :         V8_FALLTHROUGH;
    1542             :       }
    1543             :       default: {
    1544         178 :         error("invalid opcode in initialization expression");
    1545         178 :         expr.kind = WasmInitExpr::kNone;
    1546         178 :         expr.val.i32_const = 0;
    1547             :       }
    1548             :     }
    1549      445834 :     consume_bytes(len, "init code");
    1550      445834 :     if (!expect_u8("end opcode", kExprEnd)) {
    1551         552 :       expr.kind = WasmInitExpr::kNone;
    1552             :     }
    1553      445834 :     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
    1554         213 :       errorf(pos, "type error in init expression, expected %s, got %s",
    1555             :              ValueTypes::TypeName(expected),
    1556         426 :              ValueTypes::TypeName(TypeOf(module, expr)));
    1557             :     }
    1558      445834 :     return expr;
    1559             :   }
    1560             : 
    1561             :   // Read a mutability flag
    1562      443380 :   bool consume_mutability() {
    1563      443380 :     byte val = consume_u8("mutability");
    1564      443380 :     if (val > 1) error(pc_ - 1, "invalid mutability");
    1565      443380 :     return val != 0;
    1566             :   }
    1567             : 
    1568             :   // Reads a single 8-bit integer, interpreting it as a local type.
    1569     1331210 :   ValueType consume_value_type() {
    1570     1331210 :     byte val = consume_u8("value type");
    1571             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1572     1331210 :     switch (t) {
    1573             :       case kLocalI32:
    1574             :         return kWasmI32;
    1575             :       case kLocalI64:
    1576       34564 :         return kWasmI64;
    1577             :       case kLocalF32:
    1578      707004 :         return kWasmF32;
    1579             :       case kLocalF64:
    1580      277993 :         return kWasmF64;
    1581             :       default:
    1582        3279 :         if (origin_ == kWasmOrigin) {
    1583        3279 :           switch (t) {
    1584             :             case kLocalS128:
    1585          32 :               if (enabled_features_.simd) return kWasmS128;
    1586             :               break;
    1587             :             case kLocalAnyFunc:
    1588         469 :               if (enabled_features_.anyref) return kWasmAnyFunc;
    1589             :               break;
    1590             :             case kLocalAnyRef:
    1591        2688 :               if (enabled_features_.anyref) return kWasmAnyRef;
    1592             :               break;
    1593             :             case kLocalExceptRef:
    1594          64 :               if (enabled_features_.eh) return kWasmExceptRef;
    1595             :               break;
    1596             :             default:
    1597             :               break;
    1598             :           }
    1599             :         }
    1600          48 :         error(pc_ - 1, "invalid local type");
    1601          48 :         return kWasmStmt;
    1602             :     }
    1603             :   }
    1604             : 
    1605             :   // Reads a single 8-bit integer, interpreting it as a reference type.
    1606        4291 :   ValueType consume_reference_type() {
    1607        4291 :     byte val = consume_u8("reference type");
    1608             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1609        4291 :     switch (t) {
    1610             :       case kLocalAnyFunc:
    1611             :         return kWasmAnyFunc;
    1612             :       case kLocalAnyRef:
    1613          20 :         if (!enabled_features_.anyref) {
    1614           1 :           error(pc_ - 1,
    1615           1 :                 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
    1616             :         }
    1617             :         return kWasmAnyRef;
    1618             :       default:
    1619             :         break;
    1620             :     }
    1621           2 :     error(pc_ - 1, "invalid reference type");
    1622           2 :     return kWasmStmt;
    1623             :   }
    1624             : 
    1625      566856 :   FunctionSig* consume_sig(Zone* zone) {
    1626      566856 :     if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
    1627             :     // parse parameter types
    1628             :     uint32_t param_count =
    1629      566729 :         consume_count("param count", kV8MaxWasmFunctionParams);
    1630      566727 :     if (failed()) return nullptr;
    1631             :     std::vector<ValueType> params;
    1632     1703294 :     for (uint32_t i = 0; ok() && i < param_count; ++i) {
    1633      568283 :       ValueType param = consume_value_type();
    1634      568278 :       params.push_back(param);
    1635             :     }
    1636             :     std::vector<ValueType> returns;
    1637             :     // parse return types
    1638      566729 :     const size_t max_return_count = enabled_features_.mv
    1639             :                                         ? kV8MaxWasmFunctionMultiReturns
    1640      566729 :                                         : kV8MaxWasmFunctionReturns;
    1641      566729 :     uint32_t return_count = consume_count("return count", max_return_count);
    1642      566729 :     if (failed()) return nullptr;
    1643     1205744 :     for (uint32_t i = 0; ok() && i < return_count; ++i) {
    1644      319551 :       ValueType ret = consume_value_type();
    1645      319551 :       returns.push_back(ret);
    1646             :     }
    1647             : 
    1648      566642 :     if (failed()) return nullptr;
    1649             : 
    1650             :     // FunctionSig stores the return types first.
    1651      566629 :     ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
    1652             :     uint32_t b = 0;
    1653     1205704 :     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
    1654     1703106 :     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
    1655             : 
    1656     1133246 :     return new (zone) FunctionSig(return_count, param_count, buffer);
    1657             :   }
    1658             : 
    1659             :   // Consume the attribute field of an exception.
    1660         544 :   uint32_t consume_exception_attribute() {
    1661         544 :     const byte* pos = pc_;
    1662         544 :     uint32_t attribute = consume_u32v("exception attribute");
    1663         544 :     if (attribute != kExceptionAttribute) {
    1664           1 :       errorf(pos, "exception attribute %u not supported", attribute);
    1665           1 :       return 0;
    1666             :     }
    1667             :     return attribute;
    1668             :   }
    1669             : 
    1670        4715 :   void consume_segment_header(const char* name, bool* is_active,
    1671             :                               uint32_t* index, WasmInitExpr* offset) {
    1672             :     const byte* pos = pc();
    1673             :     // In the MVP, this is a table or memory index field that must be 0, but
    1674             :     // we've repurposed it as a flags field in the bulk memory proposal.
    1675             :     uint32_t flags;
    1676        4715 :     if (enabled_features_.bulk_memory) {
    1677         128 :       flags = consume_u32v("flags");
    1678         128 :       if (failed()) return;
    1679             :     } else {
    1680             :       // Without the bulk memory proposal, we should still read the table
    1681             :       // index. This is the same as reading the `ActiveWithIndex` flag with
    1682             :       // the bulk memory proposal.
    1683             :       flags = SegmentFlags::kActiveWithIndex;
    1684             :     }
    1685             : 
    1686             :     bool read_index;
    1687             :     bool read_offset;
    1688        4715 :     if (flags == SegmentFlags::kActiveNoIndex) {
    1689          32 :       *is_active = true;
    1690             :       read_index = false;
    1691             :       read_offset = true;
    1692        4683 :     } else if (flags == SegmentFlags::kPassive) {
    1693          87 :       *is_active = false;
    1694             :       read_index = false;
    1695             :       read_offset = false;
    1696        4596 :     } else if (flags == SegmentFlags::kActiveWithIndex) {
    1697        4596 :       *is_active = true;
    1698             :       read_index = true;
    1699             :       read_offset = true;
    1700             :     } else {
    1701           0 :       errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
    1702           0 :       return;
    1703             :     }
    1704             : 
    1705        4715 :     if (read_index) {
    1706        9192 :       *index = consume_u32v(name);
    1707             :     } else {
    1708         119 :       *index = 0;
    1709             :     }
    1710             : 
    1711        4715 :     if (read_offset) {
    1712        4628 :       *offset = consume_init_expr(module_.get(), kWasmI32);
    1713             :     }
    1714             :   }
    1715             : 
    1716             :   uint32_t consume_element_func_index() {
    1717        8637 :     WasmFunction* func = nullptr;
    1718             :     uint32_t index =
    1719             :         consume_func_index(module_.get(), &func, "element function index");
    1720             :     if (failed()) return index;
    1721             :     DCHECK_NE(func, nullptr);
    1722             :     DCHECK_EQ(index, func->func_index);
    1723             :     DCHECK_NE(index, WasmElemSegment::kNullIndex);
    1724             :     return index;
    1725             :   }
    1726             : 
    1727         167 :   uint32_t consume_passive_element() {
    1728             :     uint32_t index = WasmElemSegment::kNullIndex;
    1729         167 :     uint8_t opcode = consume_u8("element opcode");
    1730         167 :     if (failed()) return index;
    1731         167 :     switch (opcode) {
    1732             :       case kExprRefNull:
    1733             :         index = WasmElemSegment::kNullIndex;
    1734             :         break;
    1735             :       case kExprRefFunc:
    1736             :         index = consume_element_func_index();
    1737         154 :         if (failed()) return index;
    1738             :         break;
    1739             :       default:
    1740           0 :         error("invalid opcode in element");
    1741           0 :         break;
    1742             :     }
    1743         167 :     expect_u8("end opcode", kExprEnd);
    1744         167 :     return index;
    1745             :   }
    1746             : };
    1747             : 
    1748      284339 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
    1749             :                               const byte* module_start, const byte* module_end,
    1750             :                               bool verify_functions, ModuleOrigin origin,
    1751             :                               Counters* counters,
    1752             :                               AccountingAllocator* allocator) {
    1753             :   auto counter =
    1754      284339 :       SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
    1755             :   TimedHistogramScope wasm_decode_module_time_scope(counter);
    1756      284351 :   size_t size = module_end - module_start;
    1757      284351 :   CHECK_LE(module_start, module_end);
    1758      284351 :   if (size >= kV8MaxWasmModuleSize) {
    1759             :     return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
    1760           0 :                                   kV8MaxWasmModuleSize, size}};
    1761             :   }
    1762             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1763             :   auto size_counter =
    1764      284351 :       SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
    1765      284351 :   size_counter->AddSample(static_cast<int>(size));
    1766             :   // Signatures are stored in zone memory, which have the same lifetime
    1767             :   // as the {module}.
    1768      568703 :   ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
    1769             :   ModuleResult result =
    1770      853039 :       decoder.DecodeModule(counters, allocator, verify_functions);
    1771             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1772             :   // TODO(titzer): this isn't accurate, since it doesn't count the data
    1773             :   // allocated on the C++ heap.
    1774             :   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
    1775      284346 :   if (result.ok()) {
    1776      258331 :     auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
    1777             :                                             module_peak_memory_bytes);
    1778      258331 :     peak_counter->AddSample(
    1779      258331 :         static_cast<int>(result.value()->signature_zone->allocation_size()));
    1780             :   }
    1781             :   return result;
    1782             : }
    1783             : 
    1784         380 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
    1785         760 :     : enabled_features_(enabled) {}
    1786             : 
    1787             : ModuleDecoder::~ModuleDecoder() = default;
    1788             : 
    1789         668 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
    1790         668 :   return impl_->shared_module();
    1791             : }
    1792             : 
    1793         352 : void ModuleDecoder::StartDecoding(Counters* counters,
    1794             :                                   AccountingAllocator* allocator,
    1795             :                                   ModuleOrigin origin) {
    1796             :   DCHECK_NULL(impl_);
    1797         352 :   impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
    1798         352 :   impl_->StartDecoding(counters, allocator);
    1799         352 : }
    1800             : 
    1801         352 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
    1802             :                                        uint32_t offset) {
    1803         704 :   impl_->DecodeModuleHeader(bytes, offset);
    1804         352 : }
    1805             : 
    1806         804 : void ModuleDecoder::DecodeSection(SectionCode section_code,
    1807             :                                   Vector<const uint8_t> bytes, uint32_t offset,
    1808             :                                   bool verify_functions) {
    1809        1608 :   impl_->DecodeSection(section_code, bytes, offset, verify_functions);
    1810         804 : }
    1811             : 
    1812         452 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
    1813             :                                        uint32_t offset, bool verify_functions) {
    1814         904 :   impl_->DecodeFunctionBody(index, length, offset, verify_functions);
    1815         452 : }
    1816             : 
    1817         228 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
    1818             :                                         uint32_t offset) {
    1819         228 :   return impl_->CheckFunctionsCount(functions_count, offset);
    1820             : }
    1821             : 
    1822         200 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
    1823         600 :   return impl_->FinishDecoding(verify_functions);
    1824             : }
    1825             : 
    1826       35029 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
    1827             :                                                   const byte* end) {
    1828       35029 :   WireBytesRef string = consume_string(decoder, true, "section name");
    1829       35039 :   if (decoder.failed() || decoder.pc() > end) {
    1830             :     return kUnknownSectionCode;
    1831             :   }
    1832             :   const byte* section_name_start =
    1833       26797 :       decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
    1834             : 
    1835             :   TRACE("  +%d  section name        : \"%.*s\"\n",
    1836             :         static_cast<int>(section_name_start - decoder.start()),
    1837             :         string.length() < 20 ? string.length() : 20, section_name_start);
    1838             : 
    1839       52396 :   if (string.length() == num_chars(kNameString) &&
    1840       25599 :       strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
    1841             :               num_chars(kNameString)) == 0) {
    1842             :     return kNameSectionCode;
    1843        1451 :   } else if (string.length() == num_chars(kSourceMappingURLString) &&
    1844         201 :              strncmp(reinterpret_cast<const char*>(section_name_start),
    1845             :                      kSourceMappingURLString,
    1846             :                      num_chars(kSourceMappingURLString)) == 0) {
    1847             :     return kSourceMappingURLSectionCode;
    1848        1419 :   } else if (string.length() == num_chars(kCompilationHintsString) &&
    1849         185 :              strncmp(reinterpret_cast<const char*>(section_name_start),
    1850             :                      kCompilationHintsString,
    1851             :                      num_chars(kCompilationHintsString)) == 0) {
    1852             :     return kCompilationHintsSectionCode;
    1853             :   }
    1854        1177 :   return kUnknownSectionCode;
    1855             : }
    1856             : 
    1857        2312 : bool ModuleDecoder::ok() { return impl_->ok(); }
    1858             : 
    1859         262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
    1860             :                                            Zone* zone, const byte* start,
    1861             :                                            const byte* end) {
    1862         524 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1863         262 :   return decoder.DecodeFunctionSignature(zone, start);
    1864             : }
    1865             : 
    1866          22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
    1867             :                                           const byte* start, const byte* end) {
    1868          44 :   AccountingAllocator allocator;
    1869          44 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1870          22 :   return decoder.DecodeInitExpr(start);
    1871             : }
    1872             : 
    1873           1 : FunctionResult DecodeWasmFunctionForTesting(
    1874             :     const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
    1875             :     const WasmModule* module, const byte* function_start,
    1876             :     const byte* function_end, Counters* counters) {
    1877           1 :   size_t size = function_end - function_start;
    1878           1 :   CHECK_LE(function_start, function_end);
    1879           1 :   auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
    1880             :                                             function_size_bytes);
    1881             :   // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
    1882           1 :   size_histogram->AddSample(static_cast<int>(size));
    1883           1 :   if (size > kV8MaxWasmFunctionSize) {
    1884             :     return FunctionResult{WasmError{0,
    1885             :                                     "size > maximum function size (%zu): %zu",
    1886           0 :                                     kV8MaxWasmFunctionSize, size}};
    1887             :   }
    1888           2 :   ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
    1889             :   decoder.SetCounters(counters);
    1890           2 :   return decoder.DecodeSingleFunction(zone, wire_bytes, module,
    1891           2 :                                       base::make_unique<WasmFunction>());
    1892             : }
    1893             : 
    1894         140 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
    1895             :                                       const byte* tables_end) {
    1896         140 :   AsmJsOffsets table;
    1897             : 
    1898             :   Decoder decoder(tables_start, tables_end);
    1899             :   uint32_t functions_count = decoder.consume_u32v("functions count");
    1900             :   // Reserve space for the entries, taking care of invalid input.
    1901         140 :   if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
    1902         140 :     table.reserve(functions_count);
    1903             :   }
    1904             : 
    1905         804 :   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
    1906             :     uint32_t size = decoder.consume_u32v("table size");
    1907         332 :     if (size == 0) {
    1908         140 :       table.emplace_back();
    1909         140 :       continue;
    1910             :     }
    1911         192 :     if (!decoder.checkAvailable(size)) {
    1912           0 :       decoder.error("illegal asm function offset table size");
    1913             :     }
    1914         192 :     const byte* table_end = decoder.pc() + size;
    1915             :     uint32_t locals_size = decoder.consume_u32v("locals size");
    1916         192 :     int function_start_position = decoder.consume_u32v("function start pos");
    1917         192 :     int last_byte_offset = locals_size;
    1918             :     int last_asm_position = function_start_position;
    1919             :     std::vector<AsmJsOffsetEntry> func_asm_offsets;
    1920         192 :     func_asm_offsets.reserve(size / 4);  // conservative estimation
    1921             :     // Add an entry for the stack check, associated with position 0.
    1922         384 :     func_asm_offsets.push_back(
    1923             :         {0, function_start_position, function_start_position});
    1924         704 :     while (decoder.ok() && decoder.pc() < table_end) {
    1925         256 :       last_byte_offset += decoder.consume_u32v("byte offset delta");
    1926             :       int call_position =
    1927         256 :           last_asm_position + decoder.consume_i32v("call position delta");
    1928             :       int to_number_position =
    1929         256 :           call_position + decoder.consume_i32v("to_number position delta");
    1930             :       last_asm_position = to_number_position;
    1931         512 :       func_asm_offsets.push_back(
    1932             :           {last_byte_offset, call_position, to_number_position});
    1933             :     }
    1934         192 :     if (decoder.pc() != table_end) {
    1935           0 :       decoder.error("broken asm offset table");
    1936             :     }
    1937             :     table.push_back(std::move(func_asm_offsets));
    1938             :   }
    1939         140 :   if (decoder.more()) decoder.error("unexpected additional bytes");
    1940             : 
    1941         420 :   return decoder.toResult(std::move(table));
    1942             : }
    1943             : 
    1944         250 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
    1945             :                                                       const byte* end) {
    1946             :   Decoder decoder(start, end);
    1947         250 :   decoder.consume_bytes(4, "wasm magic");
    1948         250 :   decoder.consume_bytes(4, "wasm version");
    1949             : 
    1950             :   std::vector<CustomSectionOffset> result;
    1951             : 
    1952         577 :   while (decoder.more()) {
    1953             :     byte section_code = decoder.consume_u8("section code");
    1954             :     uint32_t section_length = decoder.consume_u32v("section length");
    1955             :     uint32_t section_start = decoder.pc_offset();
    1956         335 :     if (section_code != 0) {
    1957             :       // Skip known sections.
    1958           2 :       decoder.consume_bytes(section_length, "section bytes");
    1959           2 :       continue;
    1960             :     }
    1961             :     uint32_t name_length = decoder.consume_u32v("name length");
    1962             :     uint32_t name_offset = decoder.pc_offset();
    1963         333 :     decoder.consume_bytes(name_length, "section name");
    1964             :     uint32_t payload_offset = decoder.pc_offset();
    1965         333 :     if (section_length < (payload_offset - section_start)) {
    1966           8 :       decoder.error("invalid section length");
    1967           8 :       break;
    1968             :     }
    1969         325 :     uint32_t payload_length = section_length - (payload_offset - section_start);
    1970         325 :     decoder.consume_bytes(payload_length);
    1971         325 :     if (decoder.failed()) break;
    1972         325 :     result.push_back({{section_start, section_length},
    1973             :                       {name_offset, name_length},
    1974             :                       {payload_offset, payload_length}});
    1975             :   }
    1976             : 
    1977         250 :   return result;
    1978             : }
    1979             : 
    1980             : namespace {
    1981             : 
    1982      127310 : bool FindNameSection(Decoder& decoder) {
    1983             :   static constexpr int kModuleHeaderSize = 8;
    1984      127310 :   decoder.consume_bytes(kModuleHeaderSize, "module header");
    1985             : 
    1986             :   WasmSectionIterator section_iter(decoder);
    1987             : 
    1988      266962 :   while (decoder.ok() && section_iter.more() &&
    1989             :          section_iter.section_code() != kNameSectionCode) {
    1990       42947 :     section_iter.advance(true);
    1991             :   }
    1992      127310 :   if (!section_iter.more()) return false;
    1993             : 
    1994             :   // Reset the decoder to not read beyond the name section end.
    1995             :   decoder.Reset(section_iter.payload(), decoder.pc_offset());
    1996        2886 :   return true;
    1997             : }
    1998             : 
    1999             : }  // namespace
    2000             : 
    2001      127290 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
    2002             :                          std::unordered_map<uint32_t, WireBytesRef>* names) {
    2003             :   DCHECK_NOT_NULL(names);
    2004             :   DCHECK(names->empty());
    2005             : 
    2006             :   Decoder decoder(module_start, module_end);
    2007      127290 :   if (!FindNameSection(decoder)) return;
    2008             : 
    2009        5748 :   while (decoder.ok() && decoder.more()) {
    2010             :     uint8_t name_type = decoder.consume_u8("name type");
    2011        2882 :     if (name_type & 0x80) break;  // no varuint7
    2012             : 
    2013             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    2014        2882 :     if (!decoder.checkAvailable(name_payload_len)) break;
    2015             : 
    2016        2882 :     if (name_type != NameSectionKindCode::kFunction) {
    2017          28 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    2018          28 :       continue;
    2019             :     }
    2020             :     uint32_t functions_count = decoder.consume_u32v("functions count");
    2021             : 
    2022       32856 :     for (; decoder.ok() && functions_count > 0; --functions_count) {
    2023             :       uint32_t function_index = decoder.consume_u32v("function index");
    2024       15001 :       WireBytesRef name = consume_string(decoder, false, "function name");
    2025             : 
    2026             :       // Be lenient with errors in the name section: Ignore non-UTF8 names. You
    2027             :       // can even assign to the same function multiple times (last valid one
    2028             :       // wins).
    2029       30002 :       if (decoder.ok() && validate_utf8(&decoder, name)) {
    2030       29986 :         names->insert(std::make_pair(function_index, name));
    2031             :       }
    2032             :     }
    2033             :   }
    2034             : }
    2035             : 
    2036          20 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
    2037             :                       LocalNames* result) {
    2038             :   DCHECK_NOT_NULL(result);
    2039             :   DCHECK(result->names.empty());
    2040             : 
    2041             :   Decoder decoder(module_start, module_end);
    2042          20 :   if (!FindNameSection(decoder)) return;
    2043             : 
    2044          44 :   while (decoder.ok() && decoder.more()) {
    2045             :     uint8_t name_type = decoder.consume_u8("name type");
    2046          24 :     if (name_type & 0x80) break;  // no varuint7
    2047             : 
    2048             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    2049          24 :     if (!decoder.checkAvailable(name_payload_len)) break;
    2050             : 
    2051          24 :     if (name_type != NameSectionKindCode::kLocal) {
    2052          20 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    2053          20 :       continue;
    2054             :     }
    2055             : 
    2056             :     uint32_t local_names_count = decoder.consume_u32v("local names count");
    2057          12 :     for (uint32_t i = 0; i < local_names_count; ++i) {
    2058             :       uint32_t func_index = decoder.consume_u32v("function index");
    2059           4 :       if (func_index > kMaxInt) continue;
    2060           4 :       result->names.emplace_back(static_cast<int>(func_index));
    2061             :       LocalNamesPerFunction& func_names = result->names.back();
    2062             :       result->max_function_index =
    2063           8 :           std::max(result->max_function_index, func_names.function_index);
    2064             :       uint32_t num_names = decoder.consume_u32v("namings count");
    2065          28 :       for (uint32_t k = 0; k < num_names; ++k) {
    2066             :         uint32_t local_index = decoder.consume_u32v("local index");
    2067          12 :         WireBytesRef name = consume_string(decoder, true, "local name");
    2068          12 :         if (!decoder.ok()) break;
    2069          12 :         if (local_index > kMaxInt) continue;
    2070             :         func_names.max_local_index =
    2071          24 :             std::max(func_names.max_local_index, static_cast<int>(local_index));
    2072          12 :         func_names.names.emplace_back(static_cast<int>(local_index), name);
    2073             :       }
    2074             :     }
    2075             :   }
    2076             : }
    2077             : 
    2078             : #undef TRACE
    2079             : 
    2080             : }  // namespace wasm
    2081             : }  // namespace internal
    2082      120216 : }  // namespace v8

Generated by: LCOV version 1.10