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

Generated by: LCOV version 1.10