LCOV - code coverage report
Current view: top level - src/wasm - module-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 853 895 95.3 %
Date: 2019-04-17 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       30236 :   return unibrow::Utf8::ValidateEncoding(
     103             :       decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
     104       15118 :       string.length());
     105             : }
     106             : 
     107      445984 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
     108      445984 :   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      876100 : 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      876104 :   if (length > 0) {
     139      865064 :     decoder.consume_bytes(length, name);
     140     1712636 :     if (decoder.ok() && validate_utf8 &&
     141      847574 :         !unibrow::Utf8::ValidateEncoding(string_start, length)) {
     142        8642 :       decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
     143             :     }
     144             :   }
     145      876101 :   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      404609 :         section_end_(decoder.pc()) {
     157      404609 :     next();
     158             :   }
     159             : 
     160     1743515 :   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     1297803 :     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     2587464 :     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     1335787 :   void advance(bool move_to_section_end = false) {
     185     1335787 :     if (move_to_section_end && decoder_.pc() < section_end_) {
     186     1334175 :       decoder_.consume_bytes(
     187     2668350 :           static_cast<uint32_t>(section_end_ - decoder_.pc()));
     188             :     }
     189     1335786 :     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     1335786 :     next();
     198     1335794 :   }
     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     1740388 :   void next() {
     210     1740388 :     if (!decoder_.more()) {
     211      281441 :       section_code_ = kUnknownSectionCode;
     212      281441 :       return;
     213             :     }
     214     1458947 :     section_start_ = decoder_.pc();
     215             :     uint8_t section_code = decoder_.consume_u8("section code");
     216             :     // Read and check the section size.
     217     1458945 :     uint32_t section_length = decoder_.consume_u32v("section length");
     218             : 
     219     1458954 :     payload_start_ = decoder_.pc();
     220     1458959 :     if (decoder_.checkAvailable(section_length)) {
     221             :       // Get the limit of the section within the module.
     222     1347171 :       section_end_ = payload_start_ + section_length;
     223             :     } else {
     224             :       // The section would extend beyond the end of the module.
     225      111788 :       section_end_ = payload_start_;
     226             :     }
     227             : 
     228     1458959 :     if (section_code == kUnknownSectionCode) {
     229             :       // Check for the known "name", "sourceMappingURL", or "compilationHints"
     230             :       // section.
     231             :       section_code =
     232       35902 :           ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
     233             :       // As a side effect, the above function will forward the decoder to after
     234             :       // the identifier string.
     235       35895 :       payload_start_ = decoder_.pc();
     236     1423057 :     } else if (!IsValidSectionCode(section_code)) {
     237      110904 :       decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
     238      110904 :                       section_code);
     239             :       section_code = kUnknownSectionCode;
     240             :     }
     241     1458955 :     section_code_ = decoder_.failed() ? kUnknownSectionCode
     242     1458955 :                                       : static_cast<SectionCode>(section_code);
     243             : 
     244     1458955 :     if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
     245             :       // skip to the end of the unknown section.
     246        3840 :       uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
     247        3840 :       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      571731 : class ModuleDecoderImpl : public Decoder {
     256             :  public:
     257             :   explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
     258             :       : Decoder(nullptr, nullptr),
     259             :         enabled_features_(enabled),
     260        1224 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
     261             : 
     262      285256 :   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      855768 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
     267      285256 :     if (end_ < start_) {
     268           0 :       error(start_, "end is less than start");
     269           0 :       end_ = start_;
     270             :     }
     271      285256 :   }
     272             : 
     273       15569 :   void onFirstError() override {
     274       15569 :     pc_ = end_;  // On error, terminate section decoding loop.
     275       15569 :   }
     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      285375 :   void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
     302      285375 :     CHECK_NULL(module_);
     303             :     SetCounters(counters);
     304      570756 :     module_.reset(
     305      856133 :         new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
     306      285379 :     module_->initial_pages = 0;
     307      285379 :     module_->maximum_pages = 0;
     308      285379 :     module_->mem_export = false;
     309      285379 :     module_->origin = origin_;
     310      285379 :   }
     311             : 
     312      285376 :   void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
     313      285376 :     if (failed()) return;
     314      285378 :     Reset(bytes, offset);
     315             : 
     316      285374 :     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      285377 :     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      285377 :     pos = pc_;
     327             :     {
     328             :       uint32_t magic_version = consume_u32("wasm version");
     329      285378 :       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         657 :   bool CheckSectionOrder(SectionCode section_code,
     340             :                          SectionCode prev_section_code,
     341             :                          SectionCode next_section_code) {
     342         657 :     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         654 :     if (next_ordered_section_ <= prev_section_code) {
     348         636 :       next_ordered_section_ = prev_section_code + 1;
     349             :     }
     350             :     return true;
     351             :   }
     352             : 
     353         658 :   bool CheckUnorderedSection(SectionCode section_code) {
     354         658 :     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         657 :     return true;
     361             :   }
     362             : 
     363     1292992 :   void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
     364             :                      uint32_t offset, bool verify_functions = true) {
     365     1292992 :     if (failed()) return;
     366     1292996 :     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     1293002 :     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     1292990 :     switch (section_code) {
     379             :       case kUnknownSectionCode:
     380             :         break;
     381             :       case kDataCountSectionCode:
     382          52 :         if (!CheckUnorderedSection(section_code)) return;
     383          51 :         if (!CheckSectionOrder(section_code, kElementSectionCode,
     384             :                                kCodeSectionCode))
     385             :           return;
     386             :         break;
     387             :       case kExceptionSectionCode:
     388         606 :         if (!CheckUnorderedSection(section_code)) return;
     389         606 :         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     1268595 :         next_ordered_section_ = section_code + 1;
     410     1268595 :         break;
     411             :     }
     412             : 
     413     1292982 :     switch (section_code) {
     414             :       case kUnknownSectionCode:
     415             :         break;
     416             :       case kTypeSectionCode:
     417      261017 :         DecodeTypeSection();
     418      261020 :         break;
     419             :       case kImportSectionCode:
     420      232264 :         DecodeImportSection();
     421      232261 :         break;
     422             :       case kFunctionSectionCode:
     423      259180 :         DecodeFunctionSection();
     424      259176 :         break;
     425             :       case kTableSectionCode:
     426        2576 :         DecodeTableSection();
     427        2576 :         break;
     428             :       case kMemorySectionCode:
     429       10941 :         DecodeMemorySection();
     430       10941 :         break;
     431             :       case kGlobalSectionCode:
     432        2923 :         DecodeGlobalSection();
     433        2923 :         break;
     434             :       case kExportSectionCode:
     435      234871 :         DecodeExportSection();
     436      234870 :         break;
     437             :       case kStartSectionCode:
     438        2774 :         DecodeStartSection();
     439        2774 :         break;
     440             :       case kCodeSectionCode:
     441      258458 :         DecodeCodeSection(verify_functions);
     442      258457 :         break;
     443             :       case kElementSectionCode:
     444        2246 :         DecodeElementSection();
     445        2246 :         break;
     446             :       case kDataSectionCode:
     447        1346 :         DecodeDataSection();
     448        1346 :         break;
     449             :       case kNameSectionCode:
     450       23578 :         DecodeNameSection();
     451       23573 :         break;
     452             :       case kSourceMappingURLSectionCode:
     453           8 :         DecodeSourceMappingURLSection();
     454           8 :         break;
     455             :       case kCompilationHintsSectionCode:
     456         145 :         if (enabled_features_.compilation_hints) {
     457         137 :           DecodeCompilationHintsSection();
     458             :         } else {
     459             :           // Ignore this section when feature was disabled. It is an optional
     460             :           // custom section anyways.
     461           8 :           consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     462             :         }
     463             :         break;
     464             :       case kDataCountSectionCode:
     465          50 :         if (enabled_features_.bulk_memory) {
     466             :           DecodeDataCountSection();
     467             :         } else {
     468           2 :           errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     469             :         }
     470             :         break;
     471             :       case kExceptionSectionCode:
     472         604 :         if (enabled_features_.eh) {
     473         594 :           DecodeExceptionSection();
     474             :         } else {
     475          10 :           errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     476             :         }
     477             :         break;
     478             :       default:
     479           0 :         errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     480           0 :         return;
     481             :     }
     482             : 
     483     1292971 :     if (pc() != bytes.end()) {
     484         132 :       const char* msg = pc() < bytes.end() ? "shorter" : "longer";
     485         132 :       errorf(pc(),
     486             :              "section was %s than expected size "
     487             :              "(%zu bytes expected, %zu decoded)",
     488         264 :              msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
     489             :     }
     490             :   }
     491             : 
     492      261015 :   void DecodeTypeSection() {
     493      261015 :     uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
     494      261020 :     module_->signatures.reserve(signatures_count);
     495     1396356 :     for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
     496             :       TRACE("DecodeSignature[%d] module+%d\n", i,
     497             :             static_cast<int>(pc_ - start_));
     498      567667 :       FunctionSig* s = consume_sig(module_->signature_zone.get());
     499      567667 :       module_->signatures.push_back(s);
     500      567667 :       uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
     501      567666 :       module_->signature_ids.push_back(id);
     502             :     }
     503             :     module_->signature_map.Freeze();
     504      261022 :   }
     505             : 
     506      232258 :   void DecodeImportSection() {
     507             :     uint32_t import_table_count =
     508      232258 :         consume_count("imports count", kV8MaxWasmImports);
     509      232262 :     module_->import_table.reserve(import_table_count);
     510      705383 :     for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
     511             :       TRACE("DecodeImportTable[%d] module+%d\n", i,
     512             :             static_cast<int>(pc_ - start_));
     513             : 
     514      473124 :       module_->import_table.push_back({
     515             :           {0, 0},             // module_name
     516             :           {0, 0},             // field_name
     517             :           kExternalFunction,  // kind
     518             :           0                   // index
     519             :       });
     520             :       WasmImport* import = &module_->import_table.back();
     521      236563 :       const byte* pos = pc_;
     522      236563 :       import->module_name = consume_string(*this, true, "module name");
     523      236559 :       import->field_name = consume_string(*this, true, "field name");
     524             :       import->kind =
     525      236558 :           static_cast<ImportExportKindCode>(consume_u8("import kind"));
     526      236558 :       switch (import->kind) {
     527             :         case kExternalFunction: {
     528             :           // ===== Imported function ===========================================
     529      227674 :           import->index = static_cast<uint32_t>(module_->functions.size());
     530      227674 :           module_->num_imported_functions++;
     531      910696 :           module_->functions.push_back({nullptr,        // sig
     532      227674 :                                         import->index,  // func_index
     533             :                                         0,              // sig_index
     534             :                                         {0, 0},         // code
     535             :                                         true,           // imported
     536             :                                         false});        // exported
     537             :           WasmFunction* function = &module_->functions.back();
     538             :           function->sig_index =
     539      227674 :               consume_sig_index(module_.get(), &function->sig);
     540      227674 :           break;
     541             :         }
     542             :         case kExternalTable: {
     543             :           // ===== Imported table ==============================================
     544        1564 :           if (!AddTable(module_.get())) break;
     545        1551 :           import->index = static_cast<uint32_t>(module_->tables.size());
     546        1551 :           module_->num_imported_tables++;
     547        1551 :           module_->tables.emplace_back();
     548             :           WasmTable* table = &module_->tables.back();
     549        1551 :           table->imported = true;
     550        1551 :           ValueType type = consume_reference_type();
     551        1551 :           if (!enabled_features_.anyref) {
     552        1489 :             if (type != kWasmAnyFunc) {
     553           0 :               error(pc_ - 1, "invalid table type");
     554           0 :               break;
     555             :             }
     556             :           }
     557        1551 :           table->type = type;
     558        1551 :           uint8_t flags = validate_table_flags("element count");
     559        1551 :           consume_resizable_limits(
     560             :               "element count", "elements", FLAG_wasm_max_table_size,
     561             :               &table->initial_size, &table->has_maximum_size,
     562        1551 :               FLAG_wasm_max_table_size, &table->maximum_size, flags);
     563        1551 :           break;
     564             :         }
     565             :         case kExternalMemory: {
     566             :           // ===== Imported memory =============================================
     567        4879 :           if (!AddMemory(module_.get())) break;
     568        4855 :           uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     569        4858 :           consume_resizable_limits(
     570             :               "memory", "pages", kSpecMaxWasmMemoryPages,
     571             :               &module_->initial_pages, &module_->has_maximum_pages,
     572        4858 :               kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
     573        4860 :           break;
     574             :         }
     575             :         case kExternalGlobal: {
     576             :           // ===== Imported global =============================================
     577        2332 :           import->index = static_cast<uint32_t>(module_->globals.size());
     578        6996 :           module_->globals.push_back(
     579             :               {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
     580             :           WasmGlobal* global = &module_->globals.back();
     581        2332 :           global->type = consume_value_type();
     582        2332 :           global->mutability = consume_mutability();
     583        2332 :           if (global->mutability) {
     584         419 :             module_->num_imported_mutable_globals++;
     585             :           }
     586             :           break;
     587             :         }
     588             :         case kExternalException: {
     589             :           // ===== Imported exception ==========================================
     590         106 :           if (!enabled_features_.eh) {
     591           1 :             errorf(pos, "unknown import kind 0x%02x", import->kind);
     592           1 :             break;
     593             :           }
     594         105 :           import->index = static_cast<uint32_t>(module_->exceptions.size());
     595         105 :           WasmExceptionSig* exception_sig = nullptr;
     596         105 :           consume_exception_attribute();  // Attribute ignored for now.
     597         105 :           consume_exception_sig_index(module_.get(), &exception_sig);
     598         105 :           module_->exceptions.emplace_back(exception_sig);
     599         105 :           break;
     600             :         }
     601             :         default:
     602           0 :           errorf(pos, "unknown import kind 0x%02x", import->kind);
     603           0 :           break;
     604             :       }
     605             :     }
     606      232262 :   }
     607             : 
     608      259173 :   void DecodeFunctionSection() {
     609             :     uint32_t functions_count =
     610      259173 :         consume_count("functions count", kV8MaxWasmFunctions);
     611             :     auto counter =
     612      259177 :         SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
     613      259177 :     counter->AddSample(static_cast<int>(functions_count));
     614             :     DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
     615             :     uint32_t total_function_count =
     616      259179 :         module_->num_imported_functions + functions_count;
     617      259179 :     module_->functions.reserve(total_function_count);
     618      259179 :     module_->num_declared_functions = functions_count;
     619     1036173 :     for (uint32_t i = 0; i < functions_count; ++i) {
     620      388540 :       uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
     621     1165620 :       module_->functions.push_back({nullptr,     // sig
     622             :                                     func_index,  // func_index
     623             :                                     0,           // sig_index
     624             :                                     {0, 0},      // code
     625             :                                     false,       // imported
     626             :                                     false});     // exported
     627             :       WasmFunction* function = &module_->functions.back();
     628      388540 :       function->sig_index = consume_sig_index(module_.get(), &function->sig);
     629      388539 :       if (!ok()) return;
     630             :     }
     631             :     DCHECK_EQ(module_->functions.size(), total_function_count);
     632             :   }
     633             : 
     634        2576 :   void DecodeTableSection() {
     635             :     // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
     636             :     // implementation of AnyRef landed.
     637        2576 :     uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
     638        2576 :     uint32_t table_count = consume_count("table count", max_count);
     639             : 
     640        7756 :     for (uint32_t i = 0; ok() && i < table_count; i++) {
     641        2606 :       if (!AddTable(module_.get())) break;
     642        2590 :       module_->tables.emplace_back();
     643             :       WasmTable* table = &module_->tables.back();
     644        2590 :       table->type = consume_reference_type();
     645        2590 :       uint8_t flags = validate_table_flags("table elements");
     646        2590 :       consume_resizable_limits(
     647             :           "table elements", "elements", FLAG_wasm_max_table_size,
     648             :           &table->initial_size, &table->has_maximum_size,
     649        2590 :           FLAG_wasm_max_table_size, &table->maximum_size, flags);
     650             :     }
     651        2576 :   }
     652             : 
     653       10941 :   void DecodeMemorySection() {
     654       10941 :     uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
     655             : 
     656       32643 :     for (uint32_t i = 0; ok() && i < memory_count; i++) {
     657       10891 :       if (!AddMemory(module_.get())) break;
     658       10851 :       uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     659       10851 :       consume_resizable_limits(
     660             :           "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
     661             :           &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
     662       10851 :           &module_->maximum_pages, flags);
     663             :     }
     664       10941 :   }
     665             : 
     666        2923 :   void DecodeGlobalSection() {
     667        2923 :     uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
     668        2923 :     uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
     669        2923 :     module_->globals.reserve(imported_globals + globals_count);
     670      885755 :     for (uint32_t i = 0; ok() && i < globals_count; ++i) {
     671             :       TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
     672             :       // Add an uninitialized global and pass a pointer to it.
     673     1324248 :       module_->globals.push_back(
     674             :           {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
     675             :       WasmGlobal* global = &module_->globals.back();
     676      441416 :       DecodeGlobalInModule(module_.get(), i + imported_globals, global);
     677             :     }
     678        2923 :     if (ok()) CalculateGlobalOffsets(module_.get());
     679        2923 :   }
     680             : 
     681      234866 :   void DecodeExportSection() {
     682             :     uint32_t export_table_count =
     683      234866 :         consume_count("exports count", kV8MaxWasmExports);
     684      234868 :     module_->export_table.reserve(export_table_count);
     685      938312 :     for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
     686             :       TRACE("DecodeExportTable[%d] module+%d\n", i,
     687             :             static_cast<int>(pc_ - start_));
     688             : 
     689      703449 :       module_->export_table.push_back({
     690             :           {0, 0},             // name
     691             :           kExternalFunction,  // kind
     692             :           0                   // index
     693             :       });
     694             :       WasmExport* exp = &module_->export_table.back();
     695             : 
     696      351725 :       exp->name = consume_string(*this, true, "field name");
     697             : 
     698             :       const byte* pos = pc();
     699      351721 :       exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
     700      351721 :       switch (exp->kind) {
     701             :         case kExternalFunction: {
     702      347871 :           WasmFunction* func = nullptr;
     703             :           exp->index =
     704      347870 :               consume_func_index(module_.get(), &func, "export function index");
     705      347870 :           module_->num_exported_functions++;
     706      347870 :           if (func) func->exported = true;
     707             :           break;
     708             :         }
     709             :         case kExternalTable: {
     710         744 :           WasmTable* table = nullptr;
     711         744 :           exp->index = consume_table_index(module_.get(), &table);
     712         744 :           if (table) table->exported = true;
     713             :           break;
     714             :         }
     715             :         case kExternalMemory: {
     716             :           uint32_t index = consume_u32v("memory index");
     717             :           // TODO(titzer): This should become more regular
     718             :           // once we support multiple memories.
     719        1719 :           if (!module_->has_memory || index != 0) {
     720          24 :             error("invalid memory index != 0");
     721             :           }
     722        1719 :           module_->mem_export = true;
     723        1719 :           break;
     724             :         }
     725             :         case kExternalGlobal: {
     726        1242 :           WasmGlobal* global = nullptr;
     727        1242 :           exp->index = consume_global_index(module_.get(), &global);
     728        1242 :           if (global) {
     729        1226 :             global->exported = true;
     730             :           }
     731             :           break;
     732             :         }
     733             :         case kExternalException: {
     734         145 :           if (!enabled_features_.eh) {
     735           0 :             errorf(pos, "invalid export kind 0x%02x", exp->kind);
     736           0 :             break;
     737             :           }
     738         145 :           WasmException* exception = nullptr;
     739         145 :           exp->index = consume_exception_index(module_.get(), &exception);
     740         145 :           break;
     741             :         }
     742             :         default:
     743           0 :           errorf(pos, "invalid export kind 0x%02x", exp->kind);
     744           0 :           break;
     745             :       }
     746             :     }
     747             :     // Check for duplicate exports (except for asm.js).
     748      467154 :     if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
     749        7623 :       std::vector<WasmExport> sorted_exports(module_->export_table);
     750             : 
     751     1103102 :       auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
     752             :         // Return true if a < b.
     753      628375 :         if (a.name.length() != b.name.length()) {
     754      153648 :           return a.name.length() < b.name.length();
     755             :         }
     756      474727 :         const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
     757      474727 :         const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
     758      474727 :         return memcmp(left, right, a.name.length()) < 0;
     759        7623 :       };
     760             :       std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
     761             : 
     762             :       auto it = sorted_exports.begin();
     763             :       WasmExport* last = &*it++;
     764      237079 :       for (auto end = sorted_exports.end(); it != end; last = &*it++) {
     765             :         DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
     766      115056 :         if (!cmp_less(*last, *it)) {
     767         328 :           const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
     768         328 :           TruncatedUserString<> name(pc, it->name.length());
     769         984 :           errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
     770         328 :                  name.length(), name.start(), ExternalKindName(last->kind),
     771         656 :                  last->index, ExternalKindName(it->kind), it->index);
     772             :           break;
     773             :         }
     774             :       }
     775             :     }
     776      234868 :   }
     777             : 
     778        2774 :   void DecodeStartSection() {
     779             :     WasmFunction* func;
     780        2774 :     const byte* pos = pc_;
     781             :     module_->start_function_index =
     782        2774 :         consume_func_index(module_.get(), &func, "start function index");
     783        8282 :     if (func &&
     784        5428 :         (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
     785          64 :       error(pos, "invalid start function: non-zero parameter or return count");
     786             :     }
     787        2774 :   }
     788             : 
     789        2246 :   void DecodeElementSection() {
     790             :     uint32_t element_count =
     791        2246 :         consume_count("element count", FLAG_wasm_max_table_size);
     792             : 
     793        4472 :     if (element_count > 0 && module_->tables.size() == 0) {
     794          49 :       error(pc_, "The element section requires a table");
     795             :     }
     796        7588 :     for (uint32_t i = 0; ok() && i < element_count; ++i) {
     797             :       const byte* pos = pc();
     798             : 
     799             :       bool is_active;
     800             :       uint32_t table_index;
     801             :       WasmInitExpr offset;
     802        2803 :       consume_segment_header("table index", &is_active, &table_index, &offset);
     803        2932 :       if (failed()) return;
     804             : 
     805        2674 :       if (is_active) {
     806        5304 :         if (table_index >= module_->tables.size()) {
     807           0 :           errorf(pos, "out of bounds table index %u", table_index);
     808           0 :           break;
     809             :         }
     810        2652 :         if (module_->tables[table_index].type != kWasmAnyFunc) {
     811           2 :           errorf(pos,
     812             :                  "Invalid element segment. Table %u is not of type AnyFunc",
     813           2 :                  table_index);
     814           2 :           break;
     815             :         }
     816             :       } else {
     817          22 :         ValueType type = consume_reference_type();
     818          22 :         if (type != kWasmAnyFunc) {
     819           1 :           error(pc_ - 1, "invalid element segment type");
     820           1 :           break;
     821             :         }
     822             :       }
     823             : 
     824             :       uint32_t num_elem =
     825        2671 :           consume_count("number of elements", max_table_init_entries());
     826        2671 :       if (is_active) {
     827        2650 :         module_->elem_segments.emplace_back(table_index, offset);
     828             :       } else {
     829          21 :         module_->elem_segments.emplace_back();
     830             :       }
     831             : 
     832             :       WasmElemSegment* init = &module_->elem_segments.back();
     833       19505 :       for (uint32_t j = 0; j < num_elem; j++) {
     834             :         uint32_t index = is_active ? consume_element_func_index()
     835        8489 :                                    : consume_passive_element();
     836        8434 :         if (failed()) break;
     837        8417 :         init->entries.push_back(index);
     838             :       }
     839             :     }
     840             :   }
     841             : 
     842      258450 :   void DecodeCodeSection(bool verify_functions) {
     843             :     uint32_t pos = pc_offset();
     844      258450 :     uint32_t functions_count = consume_u32v("functions count");
     845      258453 :     CheckFunctionsCount(functions_count, pos);
     846     1032993 :     for (uint32_t i = 0; ok() && i < functions_count; ++i) {
     847             :       const byte* pos = pc();
     848             :       uint32_t size = consume_u32v("body size");
     849      387274 :       if (size > kV8MaxWasmFunctionSize) {
     850             :         errorf(pos, "size %u > maximum function size %zu", size,
     851           3 :                kV8MaxWasmFunctionSize);
     852           3 :         return;
     853             :       }
     854             :       uint32_t offset = pc_offset();
     855      387271 :       consume_bytes(size, "function body");
     856      387271 :       if (failed()) break;
     857      387271 :       DecodeFunctionBody(i, size, offset, verify_functions);
     858             :     }
     859             :   }
     860             : 
     861      258721 :   bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
     862      258721 :     if (functions_count != module_->num_declared_functions) {
     863          79 :       Reset(nullptr, nullptr, offset);
     864          79 :       errorf(nullptr, "function body count %u mismatch (%u expected)",
     865          79 :              functions_count, module_->num_declared_functions);
     866          79 :       return false;
     867             :     }
     868             :     return true;
     869             :   }
     870             : 
     871      387777 :   void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
     872             :                           bool verify_functions) {
     873             :     WasmFunction* function =
     874      387777 :         &module_->functions[index + module_->num_imported_functions];
     875      387777 :     function->code = {offset, length};
     876      387777 :     if (verify_functions) {
     877      136550 :       ModuleWireBytes bytes(start_, end_);
     878      136550 :       VerifyFunctionBody(module_->signature_zone->allocator(),
     879      136550 :                          index + module_->num_imported_functions, bytes,
     880      136550 :                          module_.get(), function);
     881             :     }
     882      387777 :   }
     883             : 
     884      268086 :   bool CheckDataSegmentsCount(uint32_t data_segments_count) {
     885      268172 :     if (has_seen_unordered_section(kDataCountSectionCode) &&
     886          86 :         data_segments_count != module_->num_declared_data_segments) {
     887           3 :       errorf(pc(), "data segments count %u mismatch (%u expected)",
     888           3 :              data_segments_count, module_->num_declared_data_segments);
     889           3 :       return false;
     890             :     }
     891             :     return true;
     892             :   }
     893             : 
     894        1346 :   void DecodeDataSection() {
     895             :     uint32_t data_segments_count =
     896        1346 :         consume_count("data segments count", kV8MaxWasmDataSegments);
     897        1346 :     if (!CheckDataSegmentsCount(data_segments_count)) return;
     898             : 
     899        1344 :     module_->data_segments.reserve(data_segments_count);
     900        4566 :     for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
     901             :       const byte* pos = pc();
     902        1761 :       if (!module_->has_memory) {
     903          65 :         error("cannot load data without memory");
     904          65 :         break;
     905             :       }
     906             :       TRACE("DecodeDataSegment[%d] module+%d\n", i,
     907             :             static_cast<int>(pc_ - start_));
     908             : 
     909             :       bool is_active;
     910             :       uint32_t memory_index;
     911             :       WasmInitExpr dest_addr;
     912             :       consume_segment_header("memory index", &is_active, &memory_index,
     913        1696 :                              &dest_addr);
     914        1696 :       if (failed()) break;
     915             : 
     916        1612 :       if (is_active && memory_index != 0) {
     917           0 :         errorf(pos, "illegal memory index %u != 0", memory_index);
     918           0 :         break;
     919             :       }
     920             : 
     921        1612 :       uint32_t source_length = consume_u32v("source size");
     922             :       uint32_t source_offset = pc_offset();
     923             : 
     924        1612 :       if (is_active) {
     925        1563 :         module_->data_segments.emplace_back(dest_addr);
     926             :       } else {
     927          49 :         module_->data_segments.emplace_back();
     928             :       }
     929             : 
     930             :       WasmDataSegment* segment = &module_->data_segments.back();
     931             : 
     932        1612 :       consume_bytes(source_length, "segment data");
     933        1612 :       if (failed()) break;
     934             : 
     935        1611 :       segment->source = {source_offset, source_length};
     936             :     }
     937             :   }
     938             : 
     939       23569 :   void DecodeNameSection() {
     940             :     // TODO(titzer): find a way to report name errors as warnings.
     941             :     // Ignore all but the first occurrence of name section.
     942       23569 :     if (!has_seen_unordered_section(kNameSectionCode)) {
     943             :       set_seen_unordered_section(kNameSectionCode);
     944             :       // Use an inner decoder so that errors don't fail the outer decoder.
     945       23563 :       Decoder inner(start_, pc_, end_, buffer_offset_);
     946             :       // Decode all name subsections.
     947             :       // Be lenient with their order.
     948       47220 :       while (inner.ok() && inner.more()) {
     949             :         uint8_t name_type = inner.consume_u8("name type");
     950       23679 :         if (name_type & 0x80) inner.error("name type if not varuint7");
     951             : 
     952             :         uint32_t name_payload_len = inner.consume_u32v("name payload length");
     953       23680 :         if (!inner.checkAvailable(name_payload_len)) break;
     954             : 
     955             :         // Decode module name, ignore the rest.
     956             :         // Function and local names will be decoded when needed.
     957       23656 :         if (name_type == NameSectionKindCode::kModule) {
     958         139 :           WireBytesRef name = consume_string(inner, false, "module name");
     959         196 :           if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
     960             :         } else {
     961       23517 :           inner.consume_bytes(name_payload_len, "name subsection payload");
     962             :         }
     963             :       }
     964             :     }
     965             :     // Skip the whole names section in the outer decoder.
     966       23572 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     967       23577 :   }
     968             : 
     969           8 :   void DecodeSourceMappingURLSection() {
     970           8 :     Decoder inner(start_, pc_, end_, buffer_offset_);
     971           8 :     WireBytesRef url = wasm::consume_string(inner, true, "module name");
     972          15 :     if (inner.ok() &&
     973             :         !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
     974             :       const byte* url_start =
     975           6 :           inner.start() + inner.GetBufferRelativeOffset(url.offset());
     976             :       module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
     977           6 :                                      url.length());
     978             :       set_seen_unordered_section(kSourceMappingURLSectionCode);
     979             :     }
     980           8 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     981           8 :   }
     982             : 
     983         137 :   void DecodeCompilationHintsSection() {
     984             :     TRACE("DecodeCompilationHints module+%d\n", static_cast<int>(pc_ - start_));
     985             : 
     986             :     // TODO(frgossen): Find a way to report compilation hint errors as warnings.
     987             :     // All except first occurrence after function section and before code
     988             :     // section are ignored.
     989             :     const bool before_function_section =
     990         137 :         next_ordered_section_ <= kFunctionSectionCode;
     991         137 :     const bool after_code_section = next_ordered_section_ > kCodeSectionCode;
     992         274 :     if (before_function_section || after_code_section ||
     993             :         has_seen_unordered_section(kCompilationHintsSectionCode)) {
     994             :       return;
     995             :     }
     996             :     set_seen_unordered_section(kCompilationHintsSectionCode);
     997             : 
     998             :     // TODO(frgossen) Propagate errors to outer decoder in experimental phase.
     999             :     // We should use an inner decoder later and propagate its errors as
    1000             :     // warnings.
    1001         137 :     Decoder& decoder = *this;
    1002             :     // Decoder decoder(start_, pc_, end_, buffer_offset_);
    1003             : 
    1004             :     // Ensure exactly one compilation hint per function.
    1005             :     uint32_t hint_count = decoder.consume_u32v("compilation hint count");
    1006         137 :     if (hint_count != module_->num_declared_functions) {
    1007             :       decoder.errorf(decoder.pc(), "Expected %u compilation hints (%u found)",
    1008           0 :                      module_->num_declared_functions, hint_count);
    1009             :     }
    1010             : 
    1011             :     // Decode sequence of compilation hints.
    1012         137 :     if (decoder.ok()) {
    1013         137 :       module_->compilation_hints.reserve(hint_count);
    1014         137 :       module_->num_lazy_compilation_hints = 0;
    1015             :     }
    1016         527 :     for (uint32_t i = 0; decoder.ok() && i < hint_count; i++) {
    1017             :       TRACE("DecodeCompilationHints[%d] module+%d\n", i,
    1018             :             static_cast<int>(pc_ - start_));
    1019             : 
    1020             :       // Compilation hints are encoded in one byte each.
    1021             :       // +-------+----------+---------------+------------------+
    1022             :       // | 2 bit | 2 bit    | 2 bit         | 2 bit            |
    1023             :       // | ...   | Top tier | Baseline tier | Lazy compilation |
    1024             :       // +-------+----------+---------------+------------------+
    1025             :       uint8_t hint_byte = decoder.consume_u8("compilation hint");
    1026         195 :       if (!decoder.ok()) break;
    1027             : 
    1028             :       // Decode compilation hint.
    1029             :       WasmCompilationHint hint;
    1030             :       hint.strategy =
    1031         195 :           static_cast<WasmCompilationHintStrategy>(hint_byte & 0x03);
    1032             :       hint.baseline_tier =
    1033         195 :           static_cast<WasmCompilationHintTier>(hint_byte >> 2 & 0x3);
    1034             :       hint.top_tier =
    1035         195 :           static_cast<WasmCompilationHintTier>(hint_byte >> 4 & 0x3);
    1036             : 
    1037             :       // Check strategy.
    1038         195 :       if (hint.strategy > WasmCompilationHintStrategy::kEager) {
    1039             :         decoder.errorf(decoder.pc(),
    1040             :                        "Invalid compilation hint %#x (unknown strategy)",
    1041           8 :                        hint_byte);
    1042             :       }
    1043             : 
    1044             :       // Ensure that the top tier never downgrades a compilation result.
    1045             :       // If baseline and top tier are the same compilation will be invoked only
    1046             :       // once.
    1047         195 :       if (hint.top_tier < hint.baseline_tier &&
    1048             :           hint.top_tier != WasmCompilationHintTier::kDefault) {
    1049             :         decoder.errorf(decoder.pc(),
    1050             :                        "Invalid compilation hint %#x (forbidden downgrade)",
    1051          32 :                        hint_byte);
    1052             :       }
    1053             : 
    1054             :       // Happily accept compilation hint.
    1055         195 :       if (decoder.ok()) {
    1056         155 :         if (hint.strategy == WasmCompilationHintStrategy::kLazy) {
    1057          56 :           module_->num_lazy_compilation_hints++;
    1058             :         }
    1059         155 :         module_->compilation_hints.push_back(std::move(hint));
    1060             :       }
    1061             :     }
    1062             : 
    1063             :     // If section was invalid reset compilation hints.
    1064         137 :     if (decoder.failed()) {
    1065             :       module_->compilation_hints.clear();
    1066          40 :       module_->num_lazy_compilation_hints = 0;
    1067             :     }
    1068             : 
    1069             :     // @TODO(frgossen) Skip the whole compilation hints section in the outer
    1070             :     // decoder if inner decoder was used.
    1071             :     // consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
    1072             :   }
    1073             : 
    1074             :   void DecodeDataCountSection() {
    1075             :     module_->num_declared_data_segments =
    1076          48 :         consume_count("data segments count", kV8MaxWasmDataSegments);
    1077             :   }
    1078             : 
    1079         594 :   void DecodeExceptionSection() {
    1080             :     uint32_t exception_count =
    1081         594 :         consume_count("exception count", kV8MaxWasmExceptions);
    1082        1968 :     for (uint32_t i = 0; ok() && i < exception_count; ++i) {
    1083             :       TRACE("DecodeException[%d] module+%d\n", i,
    1084             :             static_cast<int>(pc_ - start_));
    1085         687 :       WasmExceptionSig* exception_sig = nullptr;
    1086         687 :       consume_exception_attribute();  // Attribute ignored for now.
    1087         687 :       consume_exception_sig_index(module_.get(), &exception_sig);
    1088         687 :       module_->exceptions.emplace_back(exception_sig);
    1089             :     }
    1090         594 :   }
    1091             : 
    1092      266758 :   bool CheckMismatchedCounts() {
    1093             :     // The declared vs. defined function count is normally checked when
    1094             :     // decoding the code section, but we have to check it here too in case the
    1095             :     // code section is absent.
    1096      266758 :     if (module_->num_declared_functions != 0) {
    1097             :       DCHECK_LT(module_->num_imported_functions, module_->functions.size());
    1098             :       // We know that the code section has been decoded if the first
    1099             :       // non-imported function has its code set.
    1100      516910 :       if (!module_->functions[module_->num_imported_functions].code.is_set()) {
    1101          22 :         errorf(pc(), "function count is %u, but code section is absent",
    1102          22 :                module_->num_declared_functions);
    1103          22 :         return false;
    1104             :       }
    1105             :     }
    1106             :     // Perform a similar check for the DataCount and Data sections, where data
    1107             :     // segments are declared but the Data section is absent.
    1108      266736 :     if (!CheckDataSegmentsCount(
    1109             :             static_cast<uint32_t>(module_->data_segments.size()))) {
    1110             :       return false;
    1111             :     }
    1112      266739 :     return true;
    1113             :   }
    1114             : 
    1115      282127 :   ModuleResult FinishDecoding(bool verify_functions = true) {
    1116      282127 :     if (ok() && CheckMismatchedCounts()) {
    1117      266740 :       CalculateGlobalOffsets(module_.get());
    1118             :     }
    1119      846390 :     ModuleResult result = toResult(std::move(module_));
    1120      282131 :     if (verify_functions && result.ok() && intermediate_error_.has_error()) {
    1121             :       // Copy error message and location.
    1122       15234 :       return ModuleResult{std::move(intermediate_error_)};
    1123             :     }
    1124             :     return result;
    1125             :   }
    1126             : 
    1127             :   // Decodes an entire module.
    1128      284965 :   ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
    1129             :                             bool verify_functions = true) {
    1130      284965 :     StartDecoding(counters, allocator);
    1131             :     uint32_t offset = 0;
    1132      284971 :     Vector<const byte> orig_bytes(start(), end() - start());
    1133      284971 :     DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
    1134      284970 :     if (failed()) {
    1135       15238 :       return FinishDecoding(verify_functions);
    1136             :     }
    1137             :     // Size of the module header.
    1138             :     offset += 8;
    1139      277351 :     Decoder decoder(start_ + offset, end_, offset);
    1140             : 
    1141             :     WasmSectionIterator section_iter(decoder);
    1142             : 
    1143     4424763 :     while (ok() && section_iter.more()) {
    1144             :       // Shift the offset by the section header length
    1145     1292597 :       offset += section_iter.payload_start() - section_iter.section_start();
    1146     1292597 :       if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
    1147     2583870 :         DecodeSection(section_iter.section_code(), section_iter.payload(),
    1148     1291935 :                       offset, verify_functions);
    1149             :       }
    1150             :       // Shift the offset by the remaining section payload
    1151     1292595 :       offset += section_iter.payload_length();
    1152     1292595 :       section_iter.advance(true);
    1153             :     }
    1154             : 
    1155             :     if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
    1156             : 
    1157      277349 :     if (decoder.failed()) {
    1158        6166 :       return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
    1159             :     }
    1160             : 
    1161      548529 :     return FinishDecoding(verify_functions);
    1162             :   }
    1163             : 
    1164             :   // Decodes a single anonymous function starting at {start_}.
    1165           1 :   FunctionResult DecodeSingleFunction(Zone* zone,
    1166             :                                       const ModuleWireBytes& wire_bytes,
    1167             :                                       const WasmModule* module,
    1168             :                                       std::unique_ptr<WasmFunction> function) {
    1169           1 :     pc_ = start_;
    1170           1 :     function->sig = consume_sig(zone);
    1171           2 :     function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
    1172             : 
    1173           1 :     if (ok())
    1174             :       VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
    1175           1 :                          function.get());
    1176             : 
    1177           1 :     if (intermediate_error_.has_error()) {
    1178           0 :       return FunctionResult{std::move(intermediate_error_)};
    1179             :     }
    1180             : 
    1181           1 :     return FunctionResult(std::move(function));
    1182             :   }
    1183             : 
    1184             :   // Decodes a single function signature at {start}.
    1185             :   FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
    1186         262 :     pc_ = start;
    1187         262 :     FunctionSig* result = consume_sig(zone);
    1188         262 :     return ok() ? result : nullptr;
    1189             :   }
    1190             : 
    1191             :   WasmInitExpr DecodeInitExpr(const byte* start) {
    1192          22 :     pc_ = start;
    1193          22 :     return consume_init_expr(nullptr, kWasmStmt);
    1194             :   }
    1195             : 
    1196         764 :   const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
    1197             : 
    1198             :   Counters* GetCounters() const {
    1199             :     DCHECK_NOT_NULL(counters_);
    1200             :     return counters_;
    1201             :   }
    1202             : 
    1203             :   void SetCounters(Counters* counters) {
    1204             :     DCHECK_NULL(counters_);
    1205      285376 :     counters_ = counters;
    1206             :   }
    1207             : 
    1208             :  private:
    1209             :   const WasmFeatures enabled_features_;
    1210             :   std::shared_ptr<WasmModule> module_;
    1211             :   Counters* counters_ = nullptr;
    1212             :   // The type section is the first section in a module.
    1213             :   uint8_t next_ordered_section_ = kFirstSectionInModule;
    1214             :   // We store next_ordered_section_ as uint8_t instead of SectionCode so that
    1215             :   // we can increment it. This static_assert should make sure that SectionCode
    1216             :   // does not get bigger than uint8_t accidentially.
    1217             :   static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
    1218             :                     sizeof(SectionCode),
    1219             :                 "type mismatch");
    1220             :   uint32_t seen_unordered_sections_ = 0;
    1221             :   static_assert(kBitsPerByte *
    1222             :                         sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
    1223             :                     kLastKnownModuleSection,
    1224             :                 "not enough bits");
    1225             :   WasmError intermediate_error_;
    1226             :   ModuleOrigin origin_;
    1227             : 
    1228             :   bool has_seen_unordered_section(SectionCode section_code) {
    1229      292457 :     return seen_unordered_sections_ & (1 << section_code);
    1230             :   }
    1231             : 
    1232             :   void set_seen_unordered_section(SectionCode section_code) {
    1233       24363 :     seen_unordered_sections_ |= 1 << section_code;
    1234             :   }
    1235             : 
    1236             :   uint32_t off(const byte* ptr) {
    1237           1 :     return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
    1238             :   }
    1239             : 
    1240             :   bool AddTable(WasmModule* module) {
    1241        4173 :     if (enabled_features_.anyref) return true;
    1242        4001 :     if (module->tables.size() > 0) {
    1243          32 :       error("At most one table is supported");
    1244             :       return false;
    1245             :     } else {
    1246             :       return true;
    1247             :     }
    1248             :   }
    1249             : 
    1250             :   bool AddMemory(WasmModule* module) {
    1251       15770 :     if (module->has_memory) {
    1252          64 :       error("At most one memory is supported");
    1253             :       return false;
    1254             :     } else {
    1255       15706 :       module->has_memory = true;
    1256             :       return true;
    1257             :     }
    1258             :   }
    1259             : 
    1260             :   // Decodes a single global entry inside a module starting at {pc_}.
    1261      441416 :   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
    1262             :                             WasmGlobal* global) {
    1263      441416 :     global->type = consume_value_type();
    1264      441416 :     global->mutability = consume_mutability();
    1265             :     const byte* pos = pc();
    1266      441416 :     global->init = consume_init_expr(module, kWasmStmt);
    1267      441416 :     if (global->init.kind == WasmInitExpr::kGlobalIndex) {
    1268          73 :       uint32_t other_index = global->init.val.global_index;
    1269          73 :       if (other_index >= index) {
    1270           0 :         errorf(pos,
    1271             :                "invalid global index in init expression, "
    1272             :                "index %u, other_index %u",
    1273           0 :                index, other_index);
    1274         146 :       } else if (module->globals[other_index].type != global->type) {
    1275           0 :         errorf(pos,
    1276             :                "type mismatch in global initialization "
    1277             :                "(from global #%u), expected %s, got %s",
    1278             :                other_index, ValueTypes::TypeName(global->type),
    1279           0 :                ValueTypes::TypeName(module->globals[other_index].type));
    1280             :       }
    1281             :     } else {
    1282      441343 :       if (!ValueTypes::IsSubType(global->type, TypeOf(module, global->init))) {
    1283         384 :         errorf(pos, "type error in global initialization, expected %s, got %s",
    1284             :                ValueTypes::TypeName(global->type),
    1285         384 :                ValueTypes::TypeName(TypeOf(module, global->init)));
    1286             :       }
    1287             :     }
    1288      441416 :   }
    1289             : 
    1290             :   // Calculate individual global offsets and total size of globals table.
    1291      269261 :   void CalculateGlobalOffsets(WasmModule* module) {
    1292             :     uint32_t untagged_offset = 0;
    1293             :     uint32_t tagged_offset = 0;
    1294             :     uint32_t num_imported_mutable_globals = 0;
    1295     1154038 :     for (WasmGlobal& global : module->globals) {
    1296      884777 :       if (global.mutability && global.imported) {
    1297         433 :         global.index = num_imported_mutable_globals++;
    1298     1768688 :       } else if (ValueTypes::IsReferenceType(global.type)) {
    1299        1126 :         global.offset = tagged_offset;
    1300             :         // All entries in the tagged_globals_buffer have size 1.
    1301        1126 :         tagged_offset++;
    1302             :       } else {
    1303             :         byte size =
    1304      883218 :             ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
    1305      883218 :         untagged_offset = (untagged_offset + size - 1) & ~(size - 1);  // align
    1306      883218 :         global.offset = untagged_offset;
    1307      883218 :         untagged_offset += size;
    1308             :       }
    1309             :     }
    1310      269261 :     module->untagged_globals_buffer_size = untagged_offset;
    1311      269261 :     module->tagged_globals_buffer_size = tagged_offset;
    1312      269261 :   }
    1313             : 
    1314             :   // Verifies the body (code) of a given function.
    1315      136551 :   void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
    1316             :                           const ModuleWireBytes& wire_bytes,
    1317             :                           const WasmModule* module, WasmFunction* function) {
    1318             :     WasmFunctionName func_name(function,
    1319      136551 :                                wire_bytes.GetNameOrNull(function, module));
    1320             :     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
    1321             :       StdoutStream os;
    1322             :       os << "Verifying wasm function " << func_name << std::endl;
    1323             :     }
    1324             :     FunctionBody body = {
    1325             :         function->sig, function->code.offset(),
    1326      136551 :         start_ + GetBufferRelativeOffset(function->code.offset()),
    1327      409653 :         start_ + GetBufferRelativeOffset(function->code.end_offset())};
    1328             : 
    1329             :     DecodeResult result;
    1330             :     {
    1331      136551 :       auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
    1332             :                                               wasm_decode, function_time);
    1333             : 
    1334             :       TimedHistogramScope wasm_decode_function_time_scope(time_counter);
    1335      136551 :       WasmFeatures unused_detected_features;
    1336      273102 :       result = VerifyWasmCode(allocator, enabled_features_, module,
    1337             :                               &unused_detected_features, body);
    1338             :     }
    1339             : 
    1340             :     // If the decode failed and this is the first error, set error code and
    1341             :     // location.
    1342      136551 :     if (result.failed() && intermediate_error_.empty()) {
    1343             :       // Wrap the error message from the function decoder.
    1344       15298 :       std::ostringstream error_msg;
    1345        7649 :       error_msg << "in function " << func_name << ": "
    1346             :                 << result.error().message();
    1347       15298 :       intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
    1348             :     }
    1349      136551 :   }
    1350             : 
    1351      617005 :   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
    1352      617005 :     const byte* pos = pc_;
    1353      617005 :     uint32_t sig_index = consume_u32v("signature index");
    1354     1234010 :     if (sig_index >= module->signatures.size()) {
    1355        5740 :       errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
    1356        5740 :              static_cast<int>(module->signatures.size()));
    1357        5740 :       *sig = nullptr;
    1358        5740 :       return 0;
    1359             :     }
    1360      611265 :     *sig = module->signatures[sig_index];
    1361      611265 :     return sig_index;
    1362             :   }
    1363             : 
    1364         792 :   uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
    1365         792 :     const byte* pos = pc_;
    1366         792 :     uint32_t sig_index = consume_sig_index(module, sig);
    1367         792 :     if (*sig && (*sig)->return_count() != 0) {
    1368           2 :       errorf(pos, "exception signature %u has non-void return", sig_index);
    1369           2 :       *sig = nullptr;
    1370           2 :       return 0;
    1371             :     }
    1372             :     return sig_index;
    1373             :   }
    1374             : 
    1375     2146256 :   uint32_t consume_count(const char* name, size_t maximum) {
    1376     2146256 :     const byte* p = pc_;
    1377     2146256 :     uint32_t count = consume_u32v(name);
    1378     2146269 :     if (count > maximum) {
    1379         118 :       errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
    1380         118 :       return static_cast<uint32_t>(maximum);
    1381             :     }
    1382             :     return count;
    1383             :   }
    1384             : 
    1385             :   uint32_t consume_func_index(WasmModule* module, WasmFunction** func,
    1386             :                               const char* name) {
    1387      359074 :     return consume_index(name, module->functions, func);
    1388             :   }
    1389             : 
    1390             :   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
    1391        1242 :     return consume_index("global index", module->globals, global);
    1392             :   }
    1393             : 
    1394             :   uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
    1395         744 :     return consume_index("table index", module->tables, table);
    1396             :   }
    1397             : 
    1398             :   uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
    1399         145 :     return consume_index("exception index", module->exceptions, except);
    1400             :   }
    1401             : 
    1402             :   template <typename T>
    1403      361205 :   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
    1404      361205 :     const byte* pos = pc_;
    1405      361205 :     uint32_t index = consume_u32v(name);
    1406      722410 :     if (index >= vector.size()) {
    1407         115 :       errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
    1408             :              static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
    1409         115 :       *ptr = nullptr;
    1410         115 :       return 0;
    1411             :     }
    1412      361090 :     *ptr = &vector[index];
    1413      361090 :     return index;
    1414             :   }
    1415             : 
    1416        4141 :   uint8_t validate_table_flags(const char* name) {
    1417        4141 :     uint8_t flags = consume_u8("resizable limits flags");
    1418             :     const byte* pos = pc();
    1419        4141 :     if (flags & 0xFE) {
    1420           8 :       errorf(pos - 1, "invalid %s limits flags", name);
    1421             :     }
    1422        4141 :     return flags;
    1423             :   }
    1424             : 
    1425       15706 :   uint8_t validate_memory_flags(bool* has_shared_memory) {
    1426       15706 :     uint8_t flags = consume_u8("resizable limits flags");
    1427             :     const byte* pos = pc();
    1428       15707 :     *has_shared_memory = false;
    1429       15707 :     if (enabled_features_.threads) {
    1430        1556 :       if (flags & 0xFC) {
    1431           0 :         errorf(pos - 1, "invalid memory limits flags");
    1432        1556 :       } else if (flags == 3) {
    1433             :         DCHECK_NOT_NULL(has_shared_memory);
    1434        1480 :         *has_shared_memory = true;
    1435          76 :       } else if (flags == 2) {
    1436           8 :         errorf(pos - 1,
    1437             :                "memory limits flags should have maximum defined if shared is "
    1438           8 :                "true");
    1439             :       }
    1440             :     } else {
    1441       14151 :       if (flags & 0xFE) {
    1442          16 :         errorf(pos - 1, "invalid memory limits flags");
    1443             :       }
    1444             :     }
    1445       15707 :     return flags;
    1446             :   }
    1447             : 
    1448       19847 :   void consume_resizable_limits(const char* name, const char* units,
    1449             :                                 uint32_t max_initial, uint32_t* initial,
    1450             :                                 bool* has_max, uint32_t max_maximum,
    1451             :                                 uint32_t* maximum, uint8_t flags) {
    1452             :     const byte* pos = pc();
    1453       39697 :     *initial = consume_u32v("initial size");
    1454       19850 :     *has_max = false;
    1455       19850 :     if (*initial > max_initial) {
    1456             :       errorf(pos,
    1457             :              "initial %s size (%u %s) is larger than implementation limit (%u)",
    1458          56 :              name, *initial, units, max_initial);
    1459             :     }
    1460       19852 :     if (flags & 1) {
    1461        6043 :       *has_max = true;
    1462             :       pos = pc();
    1463        6043 :       *maximum = consume_u32v("maximum size");
    1464        6043 :       if (*maximum > max_maximum) {
    1465             :         errorf(
    1466             :             pos,
    1467             :             "maximum %s size (%u %s) is larger than implementation limit (%u)",
    1468          57 :             name, *maximum, units, max_maximum);
    1469             :       }
    1470        6043 :       if (*maximum < *initial) {
    1471             :         errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
    1472          16 :                name, *maximum, units, *initial, units);
    1473             :       }
    1474             :     } else {
    1475       13809 :       *has_max = false;
    1476       13809 :       *maximum = max_initial;
    1477             :     }
    1478       19852 :   }
    1479             : 
    1480     1013849 :   bool expect_u8(const char* name, uint8_t expected) {
    1481             :     const byte* pos = pc();
    1482     1013849 :     uint8_t value = consume_u8(name);
    1483     1013849 :     if (value != expected) {
    1484         680 :       errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
    1485         680 :       return false;
    1486             :     }
    1487             :     return true;
    1488             :   }
    1489             : 
    1490      445866 :   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
    1491             :     const byte* pos = pc();
    1492      445866 :     uint8_t opcode = consume_u8("opcode");
    1493             :     WasmInitExpr expr;
    1494             :     uint32_t len = 0;
    1495      445866 :     switch (opcode) {
    1496             :       case kExprGetGlobal: {
    1497             :         GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
    1498         404 :         if (module->globals.size() <= imm.index) {
    1499          16 :           error("global index is out of bounds");
    1500          16 :           expr.kind = WasmInitExpr::kNone;
    1501          16 :           expr.val.i32_const = 0;
    1502          16 :           break;
    1503             :         }
    1504             :         WasmGlobal* global = &module->globals[imm.index];
    1505         388 :         if (global->mutability || !global->imported) {
    1506             :           error(
    1507             :               "only immutable imported globals can be used in initializer "
    1508          18 :               "expressions");
    1509          18 :           expr.kind = WasmInitExpr::kNone;
    1510          18 :           expr.val.i32_const = 0;
    1511          18 :           break;
    1512             :         }
    1513         370 :         expr.kind = WasmInitExpr::kGlobalIndex;
    1514         370 :         expr.val.global_index = imm.index;
    1515         370 :         len = imm.length;
    1516         370 :         break;
    1517             :       }
    1518             :       case kExprI32Const: {
    1519             :         ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1520        7889 :         expr.kind = WasmInitExpr::kI32Const;
    1521        7889 :         expr.val.i32_const = imm.value;
    1522        7889 :         len = imm.length;
    1523             :         break;
    1524             :       }
    1525             :       case kExprF32Const: {
    1526      436042 :         ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1527      436042 :         expr.kind = WasmInitExpr::kF32Const;
    1528      436042 :         expr.val.f32_const = imm.value;
    1529      436042 :         len = imm.length;
    1530             :         break;
    1531             :       }
    1532             :       case kExprI64Const: {
    1533             :         ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1534         316 :         expr.kind = WasmInitExpr::kI64Const;
    1535         316 :         expr.val.i64_const = imm.value;
    1536         316 :         len = imm.length;
    1537             :         break;
    1538             :       }
    1539             :       case kExprF64Const: {
    1540         571 :         ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1541         571 :         expr.kind = WasmInitExpr::kF64Const;
    1542         571 :         expr.val.f64_const = imm.value;
    1543         571 :         len = imm.length;
    1544             :         break;
    1545             :       }
    1546             :       case kExprRefNull: {
    1547         466 :         if (enabled_features_.anyref || enabled_features_.eh) {
    1548         466 :           expr.kind = WasmInitExpr::kRefNullConst;
    1549             :           len = 0;
    1550         466 :           break;
    1551             :         }
    1552             :         V8_FALLTHROUGH;
    1553             :       }
    1554             :       default: {
    1555         178 :         error("invalid opcode in initialization expression");
    1556         178 :         expr.kind = WasmInitExpr::kNone;
    1557         178 :         expr.val.i32_const = 0;
    1558             :       }
    1559             :     }
    1560      445866 :     consume_bytes(len, "init code");
    1561      445866 :     if (!expect_u8("end opcode", kExprEnd)) {
    1562         552 :       expr.kind = WasmInitExpr::kNone;
    1563             :     }
    1564      445866 :     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
    1565         213 :       errorf(pos, "type error in init expression, expected %s, got %s",
    1566             :              ValueTypes::TypeName(expected),
    1567         426 :              ValueTypes::TypeName(TypeOf(module, expr)));
    1568             :     }
    1569      445866 :     return expr;
    1570             :   }
    1571             : 
    1572             :   // Read a mutability flag
    1573      443748 :   bool consume_mutability() {
    1574      443748 :     byte val = consume_u8("mutability");
    1575      443748 :     if (val > 1) error(pc_ - 1, "invalid mutability");
    1576      443748 :     return val != 0;
    1577             :   }
    1578             : 
    1579             :   // Reads a single 8-bit integer, interpreting it as a local type.
    1580     1333712 :   ValueType consume_value_type() {
    1581     1333712 :     byte val = consume_u8("value type");
    1582             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1583     1333714 :     switch (t) {
    1584             :       case kLocalI32:
    1585             :         return kWasmI32;
    1586             :       case kLocalI64:
    1587       34588 :         return kWasmI64;
    1588             :       case kLocalF32:
    1589      707080 :         return kWasmF32;
    1590             :       case kLocalF64:
    1591      278061 :         return kWasmF64;
    1592             :       default:
    1593        6343 :         if (origin_ == kWasmOrigin) {
    1594        6343 :           switch (t) {
    1595             :             case kLocalS128:
    1596          48 :               if (enabled_features_.simd) return kWasmS128;
    1597             :               break;
    1598             :             case kLocalAnyFunc:
    1599         837 :               if (enabled_features_.anyref) return kWasmAnyFunc;
    1600             :               break;
    1601             :             case kLocalAnyRef:
    1602        5256 :               if (enabled_features_.anyref) return kWasmAnyRef;
    1603             :               break;
    1604             :             case kLocalExceptRef:
    1605         176 :               if (enabled_features_.eh) return kWasmExceptRef;
    1606             :               break;
    1607             :             default:
    1608             :               break;
    1609             :           }
    1610             :         }
    1611          48 :         error(pc_ - 1, "invalid local type");
    1612          48 :         return kWasmStmt;
    1613             :     }
    1614             :   }
    1615             : 
    1616             :   // Reads a single 8-bit integer, interpreting it as a reference type.
    1617        4163 :   ValueType consume_reference_type() {
    1618        4163 :     byte val = consume_u8("reference type");
    1619             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1620        4163 :     switch (t) {
    1621             :       case kLocalAnyFunc:
    1622             :         return kWasmAnyFunc;
    1623             :       case kLocalAnyRef:
    1624          20 :         if (!enabled_features_.anyref) {
    1625           1 :           error(pc_ - 1,
    1626           1 :                 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
    1627             :         }
    1628             :         return kWasmAnyRef;
    1629             :       default:
    1630             :         break;
    1631             :     }
    1632           2 :     error(pc_ - 1, "invalid reference type");
    1633           2 :     return kWasmStmt;
    1634             :   }
    1635             : 
    1636      567929 :   FunctionSig* consume_sig(Zone* zone) {
    1637      567929 :     if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
    1638             :     // parse parameter types
    1639             :     uint32_t param_count =
    1640      567801 :         consume_count("param count", kV8MaxWasmFunctionParams);
    1641      567802 :     if (failed()) return nullptr;
    1642             :     std::vector<ValueType> params;
    1643     1707963 :     for (uint32_t i = 0; ok() && i < param_count; ++i) {
    1644      570081 :       ValueType param = consume_value_type();
    1645      570078 :       params.push_back(param);
    1646             :     }
    1647             :     std::vector<ValueType> returns;
    1648             :     // parse return types
    1649      567802 :     const size_t max_return_count = enabled_features_.mv
    1650             :                                         ? kV8MaxWasmFunctionMultiReturns
    1651      567802 :                                         : kV8MaxWasmFunctionReturns;
    1652      567802 :     uint32_t return_count = consume_count("return count", max_return_count);
    1653      567802 :     if (failed()) return nullptr;
    1654     1207489 :     for (uint32_t i = 0; ok() && i < return_count; ++i) {
    1655      319889 :       ValueType ret = consume_value_type();
    1656      319886 :       returns.push_back(ret);
    1657             :     }
    1658             : 
    1659      567712 :     if (failed()) return nullptr;
    1660             : 
    1661             :     // FunctionSig stores the return types first.
    1662      567699 :     ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
    1663             :     uint32_t b = 0;
    1664     1207453 :     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
    1665     1707777 :     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
    1666             : 
    1667     1135402 :     return new (zone) FunctionSig(return_count, param_count, buffer);
    1668             :   }
    1669             : 
    1670             :   // Consume the attribute field of an exception.
    1671         792 :   uint32_t consume_exception_attribute() {
    1672         792 :     const byte* pos = pc_;
    1673         792 :     uint32_t attribute = consume_u32v("exception attribute");
    1674         792 :     if (attribute != kExceptionAttribute) {
    1675           1 :       errorf(pos, "exception attribute %u not supported", attribute);
    1676           1 :       return 0;
    1677             :     }
    1678             :     return attribute;
    1679             :   }
    1680             : 
    1681        4499 :   void consume_segment_header(const char* name, bool* is_active,
    1682             :                               uint32_t* index, WasmInitExpr* offset) {
    1683             :     const byte* pos = pc();
    1684             :     // In the MVP, this is a table or memory index field that must be 0, but
    1685             :     // we've repurposed it as a flags field in the bulk memory proposal.
    1686             :     uint32_t flags;
    1687        4499 :     if (enabled_features_.bulk_memory) {
    1688        4440 :       flags = consume_u32v("flags");
    1689        4440 :       if (failed()) return;
    1690             :     } else {
    1691             :       // Without the bulk memory proposal, we should still read the table
    1692             :       // index. This is the same as reading the `ActiveWithIndex` flag with
    1693             :       // the bulk memory proposal.
    1694             :       flags = SegmentFlags::kActiveWithIndex;
    1695             :     }
    1696             : 
    1697             :     bool read_index;
    1698             :     bool read_offset;
    1699        4499 :     if (flags == SegmentFlags::kActiveNoIndex) {
    1700        4288 :       *is_active = true;
    1701             :       read_index = false;
    1702             :       read_offset = true;
    1703         211 :     } else if (flags == SegmentFlags::kPassive) {
    1704          71 :       *is_active = false;
    1705             :       read_index = false;
    1706             :       read_offset = false;
    1707         140 :     } else if (flags == SegmentFlags::kActiveWithIndex) {
    1708         140 :       *is_active = true;
    1709             :       read_index = true;
    1710             :       read_offset = true;
    1711             :     } else {
    1712           0 :       errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
    1713           0 :       return;
    1714             :     }
    1715             : 
    1716        4499 :     if (read_index) {
    1717         280 :       *index = consume_u32v(name);
    1718             :     } else {
    1719        4359 :       *index = 0;
    1720             :     }
    1721             : 
    1722        4499 :     if (read_offset) {
    1723        4428 :       *offset = consume_init_expr(module_.get(), kWasmI32);
    1724             :     }
    1725             :   }
    1726             : 
    1727             :   uint32_t consume_element_func_index() {
    1728        8429 :     WasmFunction* func = nullptr;
    1729             :     uint32_t index =
    1730             :         consume_func_index(module_.get(), &func, "element function index");
    1731             :     if (failed()) return index;
    1732             :     DCHECK_NE(func, nullptr);
    1733             :     DCHECK_EQ(index, func->func_index);
    1734             :     DCHECK_NE(index, WasmElemSegment::kNullIndex);
    1735             :     return index;
    1736             :   }
    1737             : 
    1738          55 :   uint32_t consume_passive_element() {
    1739             :     uint32_t index = WasmElemSegment::kNullIndex;
    1740          55 :     uint8_t opcode = consume_u8("element opcode");
    1741          55 :     if (failed()) return index;
    1742          55 :     switch (opcode) {
    1743             :       case kExprRefNull:
    1744             :         index = WasmElemSegment::kNullIndex;
    1745             :         break;
    1746             :       case kExprRefFunc:
    1747             :         index = consume_element_func_index();
    1748          50 :         if (failed()) return index;
    1749             :         break;
    1750             :       default:
    1751           0 :         error("invalid opcode in element");
    1752           0 :         break;
    1753             :     }
    1754          55 :     expect_u8("end opcode", kExprEnd);
    1755          55 :     return index;
    1756             :   }
    1757             : };
    1758             : 
    1759      284965 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
    1760             :                               const byte* module_start, const byte* module_end,
    1761             :                               bool verify_functions, ModuleOrigin origin,
    1762             :                               Counters* counters,
    1763             :                               AccountingAllocator* allocator) {
    1764             :   auto counter =
    1765      284965 :       SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
    1766             :   TimedHistogramScope wasm_decode_module_time_scope(counter);
    1767      284968 :   size_t size = module_end - module_start;
    1768      284968 :   CHECK_LE(module_start, module_end);
    1769      284968 :   if (size >= kV8MaxWasmModuleSize) {
    1770             :     return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
    1771           0 :                                   kV8MaxWasmModuleSize, size}};
    1772             :   }
    1773             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1774             :   auto size_counter =
    1775      284968 :       SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
    1776      284968 :   size_counter->AddSample(static_cast<int>(size));
    1777             :   // Signatures are stored in zone memory, which have the same lifetime
    1778             :   // as the {module}.
    1779      569940 :   ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
    1780             :   ModuleResult result =
    1781      854903 :       decoder.DecodeModule(counters, allocator, verify_functions);
    1782             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1783             :   // TODO(titzer): this isn't accurate, since it doesn't count the data
    1784             :   // allocated on the C++ heap.
    1785             :   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
    1786      284963 :   if (result.ok()) {
    1787      258932 :     auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
    1788             :                                             module_peak_memory_bytes);
    1789      258932 :     peak_counter->AddSample(
    1790      258932 :         static_cast<int>(result.value()->signature_zone->allocation_size()));
    1791             :   }
    1792             :   return result;
    1793             : }
    1794             : 
    1795         452 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
    1796         904 :     : enabled_features_(enabled) {}
    1797             : 
    1798             : ModuleDecoder::~ModuleDecoder() = default;
    1799             : 
    1800         764 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
    1801         764 :   return impl_->shared_module();
    1802             : }
    1803             : 
    1804         408 : void ModuleDecoder::StartDecoding(Counters* counters,
    1805             :                                   AccountingAllocator* allocator,
    1806             :                                   ModuleOrigin origin) {
    1807             :   DCHECK_NULL(impl_);
    1808         408 :   impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
    1809         408 :   impl_->StartDecoding(counters, allocator);
    1810         408 : }
    1811             : 
    1812         408 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
    1813             :                                        uint32_t offset) {
    1814         816 :   impl_->DecodeModuleHeader(bytes, offset);
    1815         408 : }
    1816             : 
    1817        1060 : void ModuleDecoder::DecodeSection(SectionCode section_code,
    1818             :                                   Vector<const uint8_t> bytes, uint32_t offset,
    1819             :                                   bool verify_functions) {
    1820        2120 :   impl_->DecodeSection(section_code, bytes, offset, verify_functions);
    1821        1060 : }
    1822             : 
    1823         508 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
    1824             :                                        uint32_t offset, bool verify_functions) {
    1825        1016 :   impl_->DecodeFunctionBody(index, length, offset, verify_functions);
    1826         508 : }
    1827             : 
    1828         268 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
    1829             :                                         uint32_t offset) {
    1830         268 :   return impl_->CheckFunctionsCount(functions_count, offset);
    1831             : }
    1832             : 
    1833         248 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
    1834         744 :   return impl_->FinishDecoding(verify_functions);
    1835             : }
    1836             : 
    1837       36033 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
    1838             :                                                   const byte* end) {
    1839       36033 :   WireBytesRef string = consume_string(decoder, true, "section name");
    1840       36035 :   if (decoder.failed() || decoder.pc() > end) {
    1841             :     return kUnknownSectionCode;
    1842             :   }
    1843             :   const byte* section_name_start =
    1844       27848 :       decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
    1845             : 
    1846             :   TRACE("  +%d  section name        : \"%.*s\"\n",
    1847             :         static_cast<int>(section_name_start - decoder.start()),
    1848             :         string.length() < 20 ? string.length() : 20, section_name_start);
    1849             : 
    1850       54396 :   if (string.length() == num_chars(kNameString) &&
    1851       26548 :       strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
    1852             :               num_chars(kNameString)) == 0) {
    1853             :     return kNameSectionCode;
    1854        1635 :   } else if (string.length() == num_chars(kSourceMappingURLString) &&
    1855         297 :              strncmp(reinterpret_cast<const char*>(section_name_start),
    1856             :                      kSourceMappingURLString,
    1857             :                      num_chars(kSourceMappingURLString)) == 0) {
    1858             :     return kSourceMappingURLSectionCode;
    1859        1603 :   } else if (string.length() == num_chars(kCompilationHintsString) &&
    1860         281 :              strncmp(reinterpret_cast<const char*>(section_name_start),
    1861             :                      kCompilationHintsString,
    1862             :                      num_chars(kCompilationHintsString)) == 0) {
    1863             :     return kCompilationHintsSectionCode;
    1864             :   }
    1865        1169 :   return kUnknownSectionCode;
    1866             : }
    1867             : 
    1868        2936 : bool ModuleDecoder::ok() { return impl_->ok(); }
    1869             : 
    1870         262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
    1871             :                                            Zone* zone, const byte* start,
    1872             :                                            const byte* end) {
    1873         524 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1874         262 :   return decoder.DecodeFunctionSignature(zone, start);
    1875             : }
    1876             : 
    1877          22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
    1878             :                                           const byte* start, const byte* end) {
    1879          44 :   AccountingAllocator allocator;
    1880          44 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1881          22 :   return decoder.DecodeInitExpr(start);
    1882             : }
    1883             : 
    1884           1 : FunctionResult DecodeWasmFunctionForTesting(
    1885             :     const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
    1886             :     const WasmModule* module, const byte* function_start,
    1887             :     const byte* function_end, Counters* counters) {
    1888           1 :   size_t size = function_end - function_start;
    1889           1 :   CHECK_LE(function_start, function_end);
    1890           1 :   auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
    1891             :                                             function_size_bytes);
    1892             :   // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
    1893           1 :   size_histogram->AddSample(static_cast<int>(size));
    1894           1 :   if (size > kV8MaxWasmFunctionSize) {
    1895             :     return FunctionResult{WasmError{0,
    1896             :                                     "size > maximum function size (%zu): %zu",
    1897           0 :                                     kV8MaxWasmFunctionSize, size}};
    1898             :   }
    1899           2 :   ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
    1900             :   decoder.SetCounters(counters);
    1901           2 :   return decoder.DecodeSingleFunction(zone, wire_bytes, module,
    1902           2 :                                       base::make_unique<WasmFunction>());
    1903             : }
    1904             : 
    1905         140 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
    1906             :                                       const byte* tables_end) {
    1907         140 :   AsmJsOffsets table;
    1908             : 
    1909             :   Decoder decoder(tables_start, tables_end);
    1910             :   uint32_t functions_count = decoder.consume_u32v("functions count");
    1911             :   // Reserve space for the entries, taking care of invalid input.
    1912         140 :   if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
    1913         140 :     table.reserve(functions_count);
    1914             :   }
    1915             : 
    1916         804 :   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
    1917             :     uint32_t size = decoder.consume_u32v("table size");
    1918         332 :     if (size == 0) {
    1919         140 :       table.emplace_back();
    1920         140 :       continue;
    1921             :     }
    1922         192 :     if (!decoder.checkAvailable(size)) {
    1923           0 :       decoder.error("illegal asm function offset table size");
    1924             :     }
    1925         192 :     const byte* table_end = decoder.pc() + size;
    1926             :     uint32_t locals_size = decoder.consume_u32v("locals size");
    1927         192 :     int function_start_position = decoder.consume_u32v("function start pos");
    1928         192 :     int last_byte_offset = locals_size;
    1929             :     int last_asm_position = function_start_position;
    1930             :     std::vector<AsmJsOffsetEntry> func_asm_offsets;
    1931         192 :     func_asm_offsets.reserve(size / 4);  // conservative estimation
    1932             :     // Add an entry for the stack check, associated with position 0.
    1933         384 :     func_asm_offsets.push_back(
    1934             :         {0, function_start_position, function_start_position});
    1935         704 :     while (decoder.ok() && decoder.pc() < table_end) {
    1936         256 :       last_byte_offset += decoder.consume_u32v("byte offset delta");
    1937             :       int call_position =
    1938         256 :           last_asm_position + decoder.consume_i32v("call position delta");
    1939             :       int to_number_position =
    1940         256 :           call_position + decoder.consume_i32v("to_number position delta");
    1941             :       last_asm_position = to_number_position;
    1942         512 :       func_asm_offsets.push_back(
    1943             :           {last_byte_offset, call_position, to_number_position});
    1944             :     }
    1945         192 :     if (decoder.pc() != table_end) {
    1946           0 :       decoder.error("broken asm offset table");
    1947             :     }
    1948             :     table.push_back(std::move(func_asm_offsets));
    1949             :   }
    1950         140 :   if (decoder.more()) decoder.error("unexpected additional bytes");
    1951             : 
    1952         420 :   return decoder.toResult(std::move(table));
    1953             : }
    1954             : 
    1955         250 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
    1956             :                                                       const byte* end) {
    1957             :   Decoder decoder(start, end);
    1958         250 :   decoder.consume_bytes(4, "wasm magic");
    1959         250 :   decoder.consume_bytes(4, "wasm version");
    1960             : 
    1961             :   std::vector<CustomSectionOffset> result;
    1962             : 
    1963         577 :   while (decoder.more()) {
    1964             :     byte section_code = decoder.consume_u8("section code");
    1965             :     uint32_t section_length = decoder.consume_u32v("section length");
    1966             :     uint32_t section_start = decoder.pc_offset();
    1967         335 :     if (section_code != 0) {
    1968             :       // Skip known sections.
    1969           2 :       decoder.consume_bytes(section_length, "section bytes");
    1970           2 :       continue;
    1971             :     }
    1972             :     uint32_t name_length = decoder.consume_u32v("name length");
    1973             :     uint32_t name_offset = decoder.pc_offset();
    1974         333 :     decoder.consume_bytes(name_length, "section name");
    1975             :     uint32_t payload_offset = decoder.pc_offset();
    1976         333 :     if (section_length < (payload_offset - section_start)) {
    1977           8 :       decoder.error("invalid section length");
    1978           8 :       break;
    1979             :     }
    1980         325 :     uint32_t payload_length = section_length - (payload_offset - section_start);
    1981         325 :     decoder.consume_bytes(payload_length);
    1982         325 :     if (decoder.failed()) break;
    1983         325 :     result.push_back({{section_start, section_length},
    1984             :                       {name_offset, name_length},
    1985             :                       {payload_offset, payload_length}});
    1986             :   }
    1987             : 
    1988         250 :   return result;
    1989             : }
    1990             : 
    1991             : namespace {
    1992             : 
    1993      127258 : bool FindNameSection(Decoder& decoder) {
    1994             :   static constexpr int kModuleHeaderSize = 8;
    1995      127258 :   decoder.consume_bytes(kModuleHeaderSize, "module header");
    1996             : 
    1997             :   WasmSectionIterator section_iter(decoder);
    1998             : 
    1999      267686 :   while (decoder.ok() && section_iter.more() &&
    2000             :          section_iter.section_code() != kNameSectionCode) {
    2001       43195 :     section_iter.advance(true);
    2002             :   }
    2003      127258 :   if (!section_iter.more()) return false;
    2004             : 
    2005             :   // Reset the decoder to not read beyond the name section end.
    2006             :   decoder.Reset(section_iter.payload(), decoder.pc_offset());
    2007        2934 :   return true;
    2008             : }
    2009             : 
    2010             : }  // namespace
    2011             : 
    2012      127238 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
    2013             :                          std::unordered_map<uint32_t, WireBytesRef>* names) {
    2014             :   DCHECK_NOT_NULL(names);
    2015             :   DCHECK(names->empty());
    2016             : 
    2017             :   Decoder decoder(module_start, module_end);
    2018      127238 :   if (!FindNameSection(decoder)) return;
    2019             : 
    2020        5844 :   while (decoder.ok() && decoder.more()) {
    2021             :     uint8_t name_type = decoder.consume_u8("name type");
    2022        2930 :     if (name_type & 0x80) break;  // no varuint7
    2023             : 
    2024             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    2025        2930 :     if (!decoder.checkAvailable(name_payload_len)) break;
    2026             : 
    2027        2930 :     if (name_type != NameSectionKindCode::kFunction) {
    2028          28 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    2029          28 :       continue;
    2030             :     }
    2031             :     uint32_t functions_count = decoder.consume_u32v("functions count");
    2032             : 
    2033       33024 :     for (; decoder.ok() && functions_count > 0; --functions_count) {
    2034             :       uint32_t function_index = decoder.consume_u32v("function index");
    2035       15061 :       WireBytesRef name = consume_string(decoder, false, "function name");
    2036             : 
    2037             :       // Be lenient with errors in the name section: Ignore non-UTF8 names. You
    2038             :       // can even assign to the same function multiple times (last valid one
    2039             :       // wins).
    2040       30122 :       if (decoder.ok() && validate_utf8(&decoder, name)) {
    2041       30106 :         names->insert(std::make_pair(function_index, name));
    2042             :       }
    2043             :     }
    2044             :   }
    2045             : }
    2046             : 
    2047          20 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
    2048             :                       LocalNames* result) {
    2049             :   DCHECK_NOT_NULL(result);
    2050             :   DCHECK(result->names.empty());
    2051             : 
    2052             :   Decoder decoder(module_start, module_end);
    2053          20 :   if (!FindNameSection(decoder)) return;
    2054             : 
    2055          44 :   while (decoder.ok() && decoder.more()) {
    2056             :     uint8_t name_type = decoder.consume_u8("name type");
    2057          24 :     if (name_type & 0x80) break;  // no varuint7
    2058             : 
    2059             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    2060          24 :     if (!decoder.checkAvailable(name_payload_len)) break;
    2061             : 
    2062          24 :     if (name_type != NameSectionKindCode::kLocal) {
    2063          20 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    2064          20 :       continue;
    2065             :     }
    2066             : 
    2067             :     uint32_t local_names_count = decoder.consume_u32v("local names count");
    2068          12 :     for (uint32_t i = 0; i < local_names_count; ++i) {
    2069             :       uint32_t func_index = decoder.consume_u32v("function index");
    2070           4 :       if (func_index > kMaxInt) continue;
    2071           4 :       result->names.emplace_back(static_cast<int>(func_index));
    2072             :       LocalNamesPerFunction& func_names = result->names.back();
    2073             :       result->max_function_index =
    2074           8 :           std::max(result->max_function_index, func_names.function_index);
    2075             :       uint32_t num_names = decoder.consume_u32v("namings count");
    2076          28 :       for (uint32_t k = 0; k < num_names; ++k) {
    2077             :         uint32_t local_index = decoder.consume_u32v("local index");
    2078          12 :         WireBytesRef name = consume_string(decoder, true, "local name");
    2079          12 :         if (!decoder.ok()) break;
    2080          12 :         if (local_index > kMaxInt) continue;
    2081             :         func_names.max_local_index =
    2082          24 :             std::max(func_names.max_local_index, static_cast<int>(local_index));
    2083          12 :         func_names.names.emplace_back(static_cast<int>(local_index), name);
    2084             :       }
    2085             :     }
    2086             :   }
    2087             : }
    2088             : 
    2089             : #undef TRACE
    2090             : 
    2091             : }  // namespace wasm
    2092             : }  // namespace internal
    2093      122004 : }  // namespace v8

Generated by: LCOV version 1.10