LCOV - code coverage report
Current view: top level - src/wasm - module-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 803 840 95.6 %
Date: 2019-02-19 Functions: 79 79 100.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/wasm/module-decoder.h"
       6             : 
       7             : #include "src/base/functional.h"
       8             : #include "src/base/platform/platform.h"
       9             : #include "src/base/template-utils.h"
      10             : #include "src/counters.h"
      11             : #include "src/flags.h"
      12             : #include "src/objects-inl.h"
      13             : #include "src/ostreams.h"
      14             : #include "src/v8.h"
      15             : #include "src/wasm/decoder.h"
      16             : #include "src/wasm/function-body-decoder-impl.h"
      17             : #include "src/wasm/wasm-engine.h"
      18             : #include "src/wasm/wasm-limits.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : 
      24             : #define TRACE(...)                                    \
      25             :   do {                                                \
      26             :     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
      27             :   } while (false)
      28             : 
      29             : namespace {
      30             : 
      31             : constexpr char kNameString[] = "name";
      32             : constexpr char kSourceMappingURLString[] = "sourceMappingURL";
      33             : 
      34             : template <size_t N>
      35             : constexpr size_t num_chars(const char (&)[N]) {
      36             :   return N - 1;  // remove null character at end.
      37             : }
      38             : 
      39             : const char* ExternalKindName(ImportExportKindCode kind) {
      40         656 :   switch (kind) {
      41             :     case kExternalFunction:
      42             :       return "function";
      43             :     case kExternalTable:
      44             :       return "table";
      45             :     case kExternalMemory:
      46             :       return "memory";
      47             :     case kExternalGlobal:
      48             :       return "global";
      49             :     case kExternalException:
      50             :       return "exception";
      51             :   }
      52             :   return "unknown";
      53             : }
      54             : 
      55             : }  // namespace
      56             : 
      57          31 : const char* SectionName(SectionCode code) {
      58          31 :   switch (code) {
      59             :     case kUnknownSectionCode:
      60             :       return "Unknown";
      61             :     case kTypeSectionCode:
      62           0 :       return "Type";
      63             :     case kImportSectionCode:
      64           0 :       return "Import";
      65             :     case kFunctionSectionCode:
      66           0 :       return "Function";
      67             :     case kTableSectionCode:
      68           0 :       return "Table";
      69             :     case kMemorySectionCode:
      70           0 :       return "Memory";
      71             :     case kGlobalSectionCode:
      72           2 :       return "Global";
      73             :     case kExportSectionCode:
      74           2 :       return "Export";
      75             :     case kStartSectionCode:
      76           8 :       return "Start";
      77             :     case kCodeSectionCode:
      78           1 :       return "Code";
      79             :     case kElementSectionCode:
      80           2 :       return "Element";
      81             :     case kDataSectionCode:
      82           0 :       return "Data";
      83             :     case kExceptionSectionCode:
      84          12 :       return "Exception";
      85             :     case kDataCountSectionCode:
      86           4 :       return "DataCount";
      87             :     case kNameSectionCode:
      88           0 :       return kNameString;
      89             :     case kSourceMappingURLSectionCode:
      90           0 :       return kSourceMappingURLString;
      91             :     default:
      92           0 :       return "<unknown>";
      93             :   }
      94             : }
      95             : 
      96             : namespace {
      97             : 
      98       14541 : bool validate_utf8(Decoder* decoder, WireBytesRef string) {
      99             :   return unibrow::Utf8::ValidateEncoding(
     100             :       decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
     101       29082 :       string.length());
     102             : }
     103             : 
     104      445356 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
     105      445356 :   switch (expr.kind) {
     106             :     case WasmInitExpr::kNone:
     107             :       return kWasmStmt;
     108             :     case WasmInitExpr::kGlobalIndex:
     109         273 :       return expr.val.global_index < module->globals.size()
     110             :                  ? module->globals[expr.val.global_index].type
     111         546 :                  : kWasmStmt;
     112             :     case WasmInitExpr::kI32Const:
     113             :       return kWasmI32;
     114             :     case WasmInitExpr::kI64Const:
     115             :       return kWasmI64;
     116             :     case WasmInitExpr::kF32Const:
     117             :       return kWasmF32;
     118             :     case WasmInitExpr::kF64Const:
     119             :       return kWasmF64;
     120             :     case WasmInitExpr::kAnyRefConst:
     121             :       return kWasmAnyRef;
     122             :     default:
     123           0 :       UNREACHABLE();
     124             :   }
     125             : }
     126             : 
     127             : // Reads a length-prefixed string, checking that it is within bounds. Returns
     128             : // the offset of the string, and the length as an out parameter.
     129      870345 : WireBytesRef consume_string(Decoder& decoder, bool validate_utf8,
     130             :                             const char* name) {
     131             :   uint32_t length = decoder.consume_u32v("string length");
     132             :   uint32_t offset = decoder.pc_offset();
     133             :   const byte* string_start = decoder.pc();
     134             :   // Consume bytes before validation to guarantee that the string is not oob.
     135      870344 :   if (length > 0) {
     136      859346 :     decoder.consume_bytes(length, name);
     137     1702047 :     if (decoder.ok() && validate_utf8 &&
     138      842696 :         !unibrow::Utf8::ValidateEncoding(string_start, length)) {
     139        8642 :       decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
     140             :     }
     141             :   }
     142      870355 :   return {offset, decoder.failed() ? 0 : length};
     143             : }
     144             : 
     145             : // An iterator over the sections in a wasm binary module.
     146             : // Automatically skips all unknown sections.
     147             : class WasmSectionIterator {
     148             :  public:
     149      125301 :   explicit WasmSectionIterator(Decoder& decoder)
     150             :       : decoder_(decoder),
     151             :         section_code_(kUnknownSectionCode),
     152             :         section_start_(decoder.pc()),
     153      524868 :         section_end_(decoder.pc()) {
     154      399567 :     next();
     155             :   }
     156             : 
     157     1719154 :   inline bool more() const { return decoder_.ok() && decoder_.more(); }
     158             : 
     159             :   inline SectionCode section_code() const { return section_code_; }
     160             : 
     161             :   inline const byte* section_start() const { return section_start_; }
     162             : 
     163             :   inline uint32_t section_length() const {
     164         488 :     return static_cast<uint32_t>(section_end_ - section_start_);
     165             :   }
     166             : 
     167     1280957 :   inline Vector<const uint8_t> payload() const {
     168     1280957 :     return {payload_start_, payload_length()};
     169             :   }
     170             : 
     171             :   inline const byte* payload_start() const { return payload_start_; }
     172             : 
     173             :   inline uint32_t payload_length() const {
     174     2559845 :     return static_cast<uint32_t>(section_end_ - payload_start_);
     175             :   }
     176             : 
     177             :   inline const byte* section_end() const { return section_end_; }
     178             : 
     179             :   // Advances to the next section, checking that decoding the current section
     180             :   // stopped at {section_end_}.
     181     1317624 :   void advance(bool move_to_section_end = false) {
     182     3951256 :     if (move_to_section_end && decoder_.pc() < section_end_) {
     183             :       decoder_.consume_bytes(
     184     2631992 :           static_cast<uint32_t>(section_end_ - decoder_.pc()));
     185             :     }
     186     2635272 :     if (decoder_.pc() != section_end_) {
     187         488 :       const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
     188             :       decoder_.errorf(decoder_.pc(),
     189             :                       "section was %s than expected size "
     190             :                       "(%u bytes expected, %zu decoded)",
     191             :                       msg, section_length(),
     192         976 :                       static_cast<size_t>(decoder_.pc() - section_start_));
     193             :     }
     194     1317636 :     next();
     195     1317641 :   }
     196             : 
     197             :  private:
     198             :   Decoder& decoder_;
     199             :   SectionCode section_code_;
     200             :   const byte* section_start_;
     201             :   const byte* payload_start_;
     202             :   const byte* section_end_;
     203             : 
     204             :   // Reads the section code/name at the current position and sets up
     205             :   // the embedder fields.
     206     1717195 :   void next() {
     207     3425346 :     if (!decoder_.more()) {
     208      277450 :       section_code_ = kUnknownSectionCode;
     209     1994657 :       return;
     210             :     }
     211     1439745 :     section_start_ = decoder_.pc();
     212             :     uint8_t section_code = decoder_.consume_u8("section code");
     213             :     // Read and check the section size.
     214     1439749 :     uint32_t section_length = decoder_.consume_u32v("section length");
     215             : 
     216     2879504 :     payload_start_ = decoder_.pc();
     217     1439752 :     if (decoder_.checkAvailable(section_length)) {
     218             :       // Get the limit of the section within the module.
     219     1328350 :       section_end_ = payload_start_ + section_length;
     220             :     } else {
     221             :       // The section would extend beyond the end of the module.
     222      111404 :       section_end_ = payload_start_;
     223             :     }
     224             : 
     225     1439754 :     if (section_code == kUnknownSectionCode) {
     226             :       // Check for the known "name" or "sourceMappingURL" section.
     227             :       section_code =
     228       33797 :           ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
     229             :       // As a side effect, the above function will forward the decoder to after
     230             :       // the identifier string.
     231       67588 :       payload_start_ = decoder_.pc();
     232     1405957 :     } else if (!IsValidSectionCode(section_code)) {
     233             :       decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
     234      220960 :                       section_code);
     235             :       section_code = kUnknownSectionCode;
     236             :     }
     237     1439757 :     section_code_ = decoder_.failed() ? kUnknownSectionCode
     238     1439757 :                                       : static_cast<SectionCode>(section_code);
     239             : 
     240     1560130 :     if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
     241             :       // skip to the end of the unknown section.
     242        7504 :       uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
     243        3752 :       decoder_.consume_bytes(remaining, "section payload");
     244             :     }
     245             :   }
     246             : };
     247             : 
     248             : }  // namespace
     249             : 
     250             : // The main logic for decoding the bytes of a module.
     251      565300 : class ModuleDecoderImpl : public Decoder {
     252             :  public:
     253             :   explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
     254             :       : Decoder(nullptr, nullptr),
     255             :         enabled_features_(enabled),
     256         656 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
     257             : 
     258      282158 :   ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start,
     259             :                     const byte* module_end, ModuleOrigin origin)
     260             :       : Decoder(module_start, module_end),
     261             :         enabled_features_(enabled),
     262      564316 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
     263      282158 :     if (end_ < start_) {
     264           0 :       error(start_, "end is less than start");
     265           0 :       end_ = start_;
     266             :     }
     267      282158 :   }
     268             : 
     269       15507 :   void onFirstError() override {
     270       15507 :     pc_ = end_;  // On error, terminate section decoding loop.
     271       15507 :   }
     272             : 
     273             :   void DumpModule(const Vector<const byte> module_bytes) {
     274             :     std::string path;
     275             :     if (FLAG_dump_wasm_module_path) {
     276             :       path = FLAG_dump_wasm_module_path;
     277             :       if (path.size() &&
     278             :           !base::OS::isDirectorySeparator(path[path.size() - 1])) {
     279             :         path += base::OS::DirectorySeparator();
     280             :       }
     281             :     }
     282             :     // File are named `HASH.{ok,failed}.wasm`.
     283             :     size_t hash = base::hash_range(module_bytes.start(), module_bytes.end());
     284             :     EmbeddedVector<char, 32> buf;
     285             :     SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed");
     286             :     std::string name(buf.start());
     287             :     if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
     288             :       if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) !=
     289             :           1) {
     290             :         OFStream os(stderr);
     291             :         os << "Error while dumping wasm file" << std::endl;
     292             :       }
     293             :       fclose(wasm_file);
     294             :     }
     295             :   }
     296             : 
     297      282197 :   void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
     298      282197 :     CHECK_NULL(module_);
     299             :     SetCounters(counters);
     300             :     module_.reset(
     301     1411005 :         new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
     302      282202 :     module_->initial_pages = 0;
     303      282202 :     module_->maximum_pages = 0;
     304      282202 :     module_->mem_export = false;
     305      282202 :     module_->origin = origin_;
     306      282202 :   }
     307             : 
     308      282200 :   void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
     309      564401 :     if (failed()) return;
     310      282199 :     Reset(bytes, offset);
     311             : 
     312      282199 :     const byte* pos = pc_;
     313             :     uint32_t magic_word = consume_u32("wasm magic");
     314             : #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
     315      282200 :     if (magic_word != kWasmMagic) {
     316             :       errorf(pos,
     317             :              "expected magic word %02x %02x %02x %02x, "
     318             :              "found %02x %02x %02x %02x",
     319        7230 :              BYTES(kWasmMagic), BYTES(magic_word));
     320             :     }
     321             : 
     322      282200 :     pos = pc_;
     323             :     {
     324             :       uint32_t magic_version = consume_u32("wasm version");
     325      282200 :       if (magic_version != kWasmVersion) {
     326             :         errorf(pos,
     327             :                "expected version %02x %02x %02x %02x, "
     328             :                "found %02x %02x %02x %02x",
     329        7622 :                BYTES(kWasmVersion), BYTES(magic_version));
     330             :       }
     331             :     }
     332             : #undef BYTES
     333             :   }
     334             : 
     335         425 :   bool CheckSectionOrder(SectionCode section_code,
     336             :                          SectionCode prev_section_code,
     337             :                          SectionCode next_section_code) {
     338         425 :     if (next_ordered_section_ > next_section_code) {
     339             :       errorf(pc(), "The %s section must appear before the %s section",
     340           3 :              SectionName(section_code), SectionName(next_section_code));
     341           3 :       return false;
     342             :     }
     343         422 :     if (next_ordered_section_ <= prev_section_code) {
     344         420 :       next_ordered_section_ = prev_section_code + 1;
     345             :     }
     346             :     return true;
     347             :   }
     348             : 
     349         426 :   bool CheckUnorderedSection(SectionCode section_code) {
     350         426 :     if (has_seen_unordered_section(section_code)) {
     351             :       errorf(pc(), "Multiple %s sections not allowed",
     352           1 :              SectionName(section_code));
     353           1 :       return false;
     354             :     }
     355             :     set_seen_unordered_section(section_code);
     356         425 :     return true;
     357             :   }
     358             : 
     359     1278957 :   void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
     360             :                      uint32_t offset, bool verify_functions = true) {
     361     2557914 :     if (failed()) return;
     362     1278959 :     Reset(bytes, offset);
     363             :     TRACE("Section: %s\n", SectionName(section_code));
     364             :     TRACE("Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()),
     365             :           static_cast<const void*>(bytes.end()));
     366             : 
     367             :     // Check if the section is out-of-order.
     368     1278959 :     if (section_code < next_ordered_section_ &&
     369             :         section_code < kFirstUnorderedSection) {
     370          24 :       errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     371          12 :       return;
     372             :     }
     373             : 
     374     1278947 :     switch (section_code) {
     375             :       case kUnknownSectionCode:
     376             :         break;
     377             :       case kDataCountSectionCode:
     378          60 :         if (!CheckUnorderedSection(section_code)) return;
     379          59 :         if (!CheckSectionOrder(section_code, kElementSectionCode,
     380          59 :                                kCodeSectionCode))
     381             :           return;
     382             :         break;
     383             :       case kExceptionSectionCode:
     384         366 :         if (!CheckUnorderedSection(section_code)) return;
     385         366 :         if (!CheckSectionOrder(section_code, kGlobalSectionCode,
     386         366 :                                kExportSectionCode))
     387             :           return;
     388             :         break;
     389             :       case kSourceMappingURLSectionCode:
     390             :         // sourceMappingURL is a custom section and currently can occur anywhere
     391             :         // in the module. In case of multiple sourceMappingURL sections, all
     392             :         // except the first occurrence are ignored.
     393             :       case kNameSectionCode:
     394             :         // TODO(titzer): report out of place name section as a warning.
     395             :         // Be lenient with placement of name section. All except first
     396             :         // occurrence are ignored.
     397             :         break;
     398             :       default:
     399     1256413 :         next_ordered_section_ = section_code + 1;
     400     1256413 :         break;
     401             :     }
     402             : 
     403     1278937 :     switch (section_code) {
     404             :       case kUnknownSectionCode:
     405             :         break;
     406             :       case kTypeSectionCode:
     407      257843 :         DecodeTypeSection();
     408      257848 :         break;
     409             :       case kImportSectionCode:
     410      231751 :         DecodeImportSection();
     411      231753 :         break;
     412             :       case kFunctionSectionCode:
     413      256000 :         DecodeFunctionSection();
     414      255999 :         break;
     415             :       case kTableSectionCode:
     416        2359 :         DecodeTableSection();
     417        2359 :         break;
     418             :       case kMemorySectionCode:
     419       10610 :         DecodeMemorySection();
     420       10610 :         break;
     421             :       case kGlobalSectionCode:
     422        2671 :         DecodeGlobalSection();
     423        2671 :         break;
     424             :       case kExportSectionCode:
     425      233542 :         DecodeExportSection();
     426      233536 :         break;
     427             :       case kStartSectionCode:
     428        2744 :         DecodeStartSection();
     429        2744 :         break;
     430             :       case kCodeSectionCode:
     431      255382 :         DecodeCodeSection(verify_functions);
     432      255383 :         break;
     433             :       case kElementSectionCode:
     434        2021 :         DecodeElementSection();
     435        2021 :         break;
     436             :       case kDataSectionCode:
     437        1482 :         DecodeDataSection();
     438        1482 :         break;
     439             :       case kNameSectionCode:
     440       22095 :         DecodeNameSection();
     441       22090 :         break;
     442             :       case kSourceMappingURLSectionCode:
     443           8 :         DecodeSourceMappingURLSection();
     444           8 :         break;
     445             :       case kDataCountSectionCode:
     446          58 :         if (enabled_features_.bulk_memory) {
     447             :           DecodeDataCountSection();
     448             :         } else {
     449           4 :           errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     450             :         }
     451             :         break;
     452             :       case kExceptionSectionCode:
     453         364 :         if (enabled_features_.eh) {
     454         354 :           DecodeExceptionSection();
     455             :         } else {
     456          20 :           errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     457             :         }
     458             :         break;
     459             :       default:
     460           0 :         errorf(pc(), "unexpected section <%s>", SectionName(section_code));
     461           0 :         return;
     462             :     }
     463             : 
     464     1278933 :     if (pc() != bytes.end()) {
     465         132 :       const char* msg = pc() < bytes.end() ? "shorter" : "longer";
     466             :       errorf(pc(),
     467             :              "section was %s than expected size "
     468             :              "(%zu bytes expected, %zu decoded)",
     469         132 :              msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
     470             :     }
     471             :   }
     472             : 
     473      257843 :   void DecodeTypeSection() {
     474      257843 :     uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
     475     2769137 :     module_->signatures.reserve(signatures_count);
     476     1642464 :     for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
     477             :       TRACE("DecodeSignature[%d] module+%d\n", i,
     478             :             static_cast<int>(pc_ - start_));
     479      563381 :       FunctionSig* s = consume_sig(module_->signature_zone.get());
     480      563382 :       module_->signatures.push_back(s);
     481     1126676 :       uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
     482      563382 :       module_->signature_ids.push_back(id);
     483             :     }
     484             :     module_->signature_map.Freeze();
     485      257851 :   }
     486             : 
     487      231751 :   void DecodeImportSection() {
     488             :     uint32_t import_table_count =
     489      231751 :         consume_count("imports count", kV8MaxWasmImports);
     490     1641292 :     module_->import_table.reserve(import_table_count);
     491      935100 :     for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
     492             :       TRACE("DecodeImportTable[%d] module+%d\n", i,
     493             :             static_cast<int>(pc_ - start_));
     494             : 
     495             :       module_->import_table.push_back({
     496             :           {0, 0},             // module_name
     497             :           {0, 0},             // field_name
     498             :           kExternalFunction,  // kind
     499             :           0                   // index
     500      707389 :       });
     501      235795 :       WasmImport* import = &module_->import_table.back();
     502      235795 :       const byte* pos = pc_;
     503      235795 :       import->module_name = consume_string(*this, true, "module name");
     504      235800 :       import->field_name = consume_string(*this, true, "field name");
     505             :       import->kind =
     506      235793 :           static_cast<ImportExportKindCode>(consume_u8("import kind"));
     507      235793 :       switch (import->kind) {
     508             :         case kExternalFunction: {
     509             :           // ===== Imported function =======================================
     510      454500 :           import->index = static_cast<uint32_t>(module_->functions.size());
     511      227250 :           module_->num_imported_functions++;
     512             :           module_->functions.push_back({nullptr,        // sig
     513             :                                         import->index,  // func_index
     514             :                                         0,              // sig_index
     515             :                                         {0, 0},         // code
     516             :                                         true,           // imported
     517      909000 :                                         false});        // exported
     518             :           WasmFunction* function = &module_->functions.back();
     519             :           function->sig_index =
     520      227250 :               consume_sig_index(module_.get(), &function->sig);
     521      227250 :           break;
     522             :         }
     523             :         case kExternalTable: {
     524             :           // ===== Imported table ==========================================
     525        1567 :           if (!AddTable(module_.get())) break;
     526        3102 :           import->index = static_cast<uint32_t>(module_->tables.size());
     527        1551 :           module_->num_imported_tables++;
     528        1551 :           module_->tables.emplace_back();
     529             :           WasmTable* table = &module_->tables.back();
     530        1551 :           table->imported = true;
     531        1551 :           ValueType type = consume_reference_type();
     532        1551 :           if (!enabled_features_.anyref) {
     533        1545 :             if (type != kWasmAnyFunc) {
     534           0 :               error(pc_ - 1, "invalid table type");
     535           0 :               break;
     536             :             }
     537             :           }
     538        1551 :           table->type = type;
     539        1551 :           uint8_t flags = validate_table_flags("element count");
     540             :           consume_resizable_limits(
     541             :               "element count", "elements", FLAG_wasm_max_table_size,
     542             :               &table->initial_size, &table->has_maximum_size,
     543        1551 :               FLAG_wasm_max_table_size, &table->maximum_size, flags);
     544        1551 :           break;
     545             :         }
     546             :         case kExternalMemory: {
     547             :           // ===== Imported memory =========================================
     548        4796 :           if (!AddMemory(module_.get())) break;
     549        4772 :           uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     550             :           consume_resizable_limits(
     551             :               "memory", "pages", kSpecMaxWasmMemoryPages,
     552             :               &module_->initial_pages, &module_->has_maximum_pages,
     553        9548 :               kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
     554        4773 :           break;
     555             :         }
     556             :         case kExternalGlobal: {
     557             :           // ===== Imported global =========================================
     558        4152 :           import->index = static_cast<uint32_t>(module_->globals.size());
     559             :           module_->globals.push_back(
     560        8304 :               {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
     561             :           WasmGlobal* global = &module_->globals.back();
     562        2076 :           global->type = consume_value_type();
     563        2076 :           global->mutability = consume_mutability();
     564        2076 :           if (global->mutability) {
     565         291 :             module_->num_imported_mutable_globals++;
     566             :           }
     567             :           break;
     568             :         }
     569             :         case kExternalException: {
     570             :           // ===== Imported exception ======================================
     571         106 :           if (!enabled_features_.eh) {
     572           1 :             errorf(pos, "unknown import kind 0x%02x", import->kind);
     573           1 :             break;
     574             :           }
     575         210 :           import->index = static_cast<uint32_t>(module_->exceptions.size());
     576         105 :           WasmExceptionSig* exception_sig = nullptr;
     577         105 :           consume_exception_attribute();  // Attribute ignored for now.
     578         105 :           consume_exception_sig_index(module_.get(), &exception_sig);
     579         105 :           module_->exceptions.emplace_back(exception_sig);
     580         105 :           break;
     581             :         }
     582             :         default:
     583           0 :           errorf(pos, "unknown import kind 0x%02x", import->kind);
     584           0 :           break;
     585             :       }
     586             :     }
     587      231753 :   }
     588             : 
     589      511990 :   void DecodeFunctionSection() {
     590             :     uint32_t functions_count =
     591      255993 :         consume_count("functions count", kV8MaxWasmFunctions);
     592             :     auto counter =
     593      511994 :         SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
     594      255997 :     counter->AddSample(static_cast<int>(functions_count));
     595             :     DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
     596             :     uint32_t total_function_count =
     597     1281587 :         module_->num_imported_functions + functions_count;
     598      256000 :     module_->functions.reserve(total_function_count);
     599      255999 :     module_->num_declared_functions = functions_count;
     600      640753 :     for (uint32_t i = 0; i < functions_count; ++i) {
     601      769588 :       uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
     602             :       module_->functions.push_back({nullptr,     // sig
     603             :                                     func_index,  // func_index
     604             :                                     0,           // sig_index
     605             :                                     {0, 0},      // code
     606             :                                     false,       // imported
     607     1154382 :                                     false});     // exported
     608             :       WasmFunction* function = &module_->functions.back();
     609      384794 :       function->sig_index = consume_sig_index(module_.get(), &function->sig);
     610      640793 :       if (!ok()) return;
     611             :     }
     612             :     DCHECK_EQ(module_->functions.size(), total_function_count);
     613             :   }
     614             : 
     615        2359 :   void DecodeTableSection() {
     616             :     // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
     617             :     // implementation of AnyRef landed.
     618        2359 :     uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
     619        2359 :     uint32_t table_count = consume_count("table count", max_count);
     620             : 
     621        9352 :     for (uint32_t i = 0; ok() && i < table_count; i++) {
     622        4650 :       if (!AddTable(module_.get())) break;
     623        2317 :       module_->tables.emplace_back();
     624             :       WasmTable* table = &module_->tables.back();
     625        2317 :       table->type = consume_reference_type();
     626        2317 :       uint8_t flags = validate_table_flags("table elements");
     627             :       consume_resizable_limits(
     628             :           "table elements", "elements", FLAG_wasm_max_table_size,
     629             :           &table->initial_size, &table->has_maximum_size,
     630        2317 :           FLAG_wasm_max_table_size, &table->maximum_size, flags);
     631             :     }
     632        2359 :   }
     633             : 
     634       10610 :   void DecodeMemorySection() {
     635       10610 :     uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
     636             : 
     637       42260 :     for (uint32_t i = 0; ok() && i < memory_count; i++) {
     638       31640 :       if (!AddMemory(module_.get())) break;
     639       10520 :       uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     640             :       consume_resizable_limits(
     641             :           "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
     642             :           &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
     643       21040 :           &module_->maximum_pages, flags);
     644             :     }
     645       10610 :   }
     646             : 
     647        2671 :   void DecodeGlobalSection() {
     648        2671 :     uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
     649      889526 :     uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
     650        2671 :     module_->globals.reserve(imported_globals + globals_count);
     651      887254 :     for (uint32_t i = 0; ok() && i < globals_count; ++i) {
     652             :       TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
     653             :       // Add an uninitialized global and pass a pointer to it.
     654             :       module_->globals.push_back(
     655     1763824 :           {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
     656      440956 :       WasmGlobal* global = &module_->globals.back();
     657      440956 :       DecodeGlobalInModule(module_.get(), i + imported_globals, global);
     658             :     }
     659        4943 :     if (ok()) CalculateGlobalOffsets(module_.get());
     660        2671 :   }
     661             : 
     662      233538 :   void DecodeExportSection() {
     663             :     uint32_t export_table_count =
     664      233538 :         consume_count("exports count", kV8MaxWasmExports);
     665     1871205 :     module_->export_table.reserve(export_table_count);
     666     1167590 :     for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
     667             :       TRACE("DecodeExportTable[%d] module+%d\n", i,
     668             :             static_cast<int>(pc_ - start_));
     669             : 
     670             :       module_->export_table.push_back({
     671             :           {0, 0},             // name
     672             :           kExternalFunction,  // kind
     673             :           0                   // index
     674     1050775 :       });
     675      350257 :       WasmExport* exp = &module_->export_table.back();
     676             : 
     677      350913 :       exp->name = consume_string(*this, true, "field name");
     678             : 
     679             :       const byte* pos = pc();
     680      350253 :       exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
     681      350253 :       switch (exp->kind) {
     682             :         case kExternalFunction: {
     683      346678 :           WasmFunction* func = nullptr;
     684             :           exp->index =
     685      346677 :               consume_func_index(module_.get(), &func, "export function index");
     686      346677 :           module_->num_exported_functions++;
     687      346677 :           if (func) func->exported = true;
     688             :           break;
     689             :         }
     690             :         case kExternalTable: {
     691         680 :           WasmTable* table = nullptr;
     692         680 :           exp->index = consume_table_index(module_.get(), &table);
     693         680 :           if (table) table->exported = true;
     694             :           break;
     695             :         }
     696             :         case kExternalMemory: {
     697             :           uint32_t index = consume_u32v("memory index");
     698             :           // TODO(titzer): This should become more regular
     699             :           // once we support multiple memories.
     700        1740 :           if (!module_->has_memory || index != 0) {
     701          24 :             error("invalid memory index != 0");
     702             :           }
     703        1740 :           module_->mem_export = true;
     704        1740 :           break;
     705             :         }
     706             :         case kExternalGlobal: {
     707        1010 :           WasmGlobal* global = nullptr;
     708        1010 :           exp->index = consume_global_index(module_.get(), &global);
     709        1010 :           if (global) {
     710         994 :             global->exported = true;
     711             :           }
     712             :           break;
     713             :         }
     714             :         case kExternalException: {
     715         145 :           if (!enabled_features_.eh) {
     716           0 :             errorf(pos, "invalid export kind 0x%02x", exp->kind);
     717           0 :             break;
     718             :           }
     719         145 :           WasmException* exception = nullptr;
     720         145 :           exp->index = consume_exception_index(module_.get(), &exception);
     721         145 :           break;
     722             :         }
     723             :         default:
     724           0 :           errorf(pos, "invalid export kind 0x%02x", exp->kind);
     725           0 :           break;
     726             :       }
     727             :     }
     728             :     // Check for duplicate exports (except for asm.js).
     729      695498 :     if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
     730        7498 :       std::vector<WasmExport> sorted_exports(module_->export_table);
     731             : 
     732      629539 :       auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
     733             :         // Return true if a < b.
     734     1579551 :         if (a.name.length() != b.name.length()) {
     735      154533 :           return a.name.length() < b.name.length();
     736             :         }
     737     1425018 :         const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
     738      475006 :         const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
     739      475006 :         return memcmp(left, right, a.name.length()) < 0;
     740        7498 :       };
     741        7498 :       std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
     742             : 
     743             :       auto it = sorted_exports.begin();
     744             :       WasmExport* last = &*it++;
     745      129588 :       for (auto end = sorted_exports.end(); it != end; last = &*it++) {
     746             :         DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
     747      114920 :         if (!cmp_less(*last, *it)) {
     748         656 :           const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
     749         328 :           TruncatedUserString<> name(pc, it->name.length());
     750             :           errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
     751             :                  name.length(), name.start(), ExternalKindName(last->kind),
     752         984 :                  last->index, ExternalKindName(it->kind), it->index);
     753             :           break;
     754             :         }
     755             :       }
     756             :     }
     757      233536 :   }
     758             : 
     759        2744 :   void DecodeStartSection() {
     760             :     WasmFunction* func;
     761        2744 :     const byte* pos = pc_;
     762        2744 :     module_->start_function_index =
     763        2744 :         consume_func_index(module_.get(), &func, "start function index");
     764        8192 :     if (func &&
     765        5368 :         (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
     766          64 :       error(pos, "invalid start function: non-zero parameter or return count");
     767             :     }
     768        2744 :   }
     769             : 
     770        2021 :   void DecodeElementSection() {
     771             :     uint32_t element_count =
     772        2021 :         consume_count("element count", FLAG_wasm_max_table_size);
     773             : 
     774       19245 :     if (element_count > 0 && module_->tables.size() == 0) {
     775          49 :       error(pc_, "The element section requires a table");
     776             :     }
     777        6803 :     for (uint32_t i = 0; ok() && i < element_count; ++i) {
     778             :       const byte* pos = pc();
     779             : 
     780             :       bool is_active;
     781             :       uint32_t table_index;
     782             :       WasmInitExpr offset;
     783        2522 :       consume_segment_header("table index", &is_active, &table_index, &offset);
     784        4672 :       if (failed()) return;
     785             : 
     786        2393 :       if (is_active) {
     787        7044 :         if (table_index >= module_->tables.size()) {
     788           0 :           errorf(pos, "out of bounds table index %u", table_index);
     789           0 :           break;
     790             :         }
     791        2348 :         if (module_->tables[table_index].type != kWasmAnyFunc) {
     792             :           errorf(pos,
     793             :                  "Invalid element segment. Table %u is not of type AnyFunc",
     794           2 :                  table_index);
     795           2 :           break;
     796             :         }
     797             :       }
     798             : 
     799             :       uint32_t num_elem =
     800        2391 :           consume_count("number of elements", kV8MaxWasmTableEntries);
     801        2391 :       if (is_active) {
     802        2346 :         module_->elem_segments.emplace_back(table_index, offset);
     803             :       } else {
     804          45 :         module_->elem_segments.emplace_back();
     805             :       }
     806             : 
     807             :       WasmElemSegment* init = &module_->elem_segments.back();
     808       10467 :       for (uint32_t j = 0; j < num_elem; j++) {
     809        8093 :         WasmFunction* func = nullptr;
     810             :         uint32_t index =
     811        8093 :             consume_func_index(module_.get(), &func, "element function index");
     812             :         DCHECK_IMPLIES(ok(), func != nullptr);
     813        8093 :         if (!ok()) break;
     814             :         DCHECK_EQ(index, func->func_index);
     815        8076 :         init->entries.push_back(index);
     816             :       }
     817             :     }
     818             :   }
     819             : 
     820      255380 :   void DecodeCodeSection(bool verify_functions) {
     821      383656 :     uint32_t pos = pc_offset();
     822      255380 :     uint32_t functions_count = consume_u32v("functions count");
     823      255381 :     CheckFunctionsCount(functions_count, pos);
     824     1278054 :     for (uint32_t i = 0; ok() && i < functions_count; ++i) {
     825             :       const byte* pos = pc();
     826             :       uint32_t size = consume_u32v("body size");
     827      383658 :       if (size > kV8MaxWasmFunctionSize) {
     828             :         errorf(pos, "size %u > maximum function size %zu", size,
     829           3 :                kV8MaxWasmFunctionSize);
     830      255384 :         return;
     831             :       }
     832             :       uint32_t offset = pc_offset();
     833      383655 :       consume_bytes(size, "function body");
     834      383654 :       if (failed()) break;
     835      383647 :       DecodeFunctionBody(i, size, offset, verify_functions);
     836             :     }
     837             :   }
     838             : 
     839      255584 :   bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
     840      255663 :     if (functions_count != module_->num_declared_functions) {
     841          79 :       Reset(nullptr, nullptr, offset);
     842             :       errorf(nullptr, "function body count %u mismatch (%u expected)",
     843          79 :              functions_count, module_->num_declared_functions);
     844          79 :       return false;
     845             :     }
     846             :     return true;
     847             :   }
     848             : 
     849      384071 :   void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
     850             :                           bool verify_functions) {
     851             :     WasmFunction* function =
     852      519673 :         &module_->functions[index + module_->num_imported_functions];
     853      384071 :     function->code = {offset, length};
     854      384071 :     if (verify_functions) {
     855      135602 :       ModuleWireBytes bytes(start_, end_);
     856             :       VerifyFunctionBody(module_->signature_zone->allocator(),
     857             :                          index + module_->num_imported_functions, bytes,
     858      271204 :                          module_.get(), function);
     859             :     }
     860      384071 :   }
     861             : 
     862      265119 :   bool CheckDataSegmentsCount(uint32_t data_segments_count) {
     863      265221 :     if (has_seen_unordered_section(kDataCountSectionCode) &&
     864         105 :         data_segments_count != module_->num_declared_data_segments) {
     865             :       errorf(pc(), "data segments count %u mismatch (%u expected)",
     866           3 :              data_segments_count, module_->num_declared_data_segments);
     867           3 :       return false;
     868             :     }
     869             :     return true;
     870             :   }
     871             : 
     872        1482 :   void DecodeDataSection() {
     873             :     uint32_t data_segments_count =
     874        1482 :         consume_count("data segments count", kV8MaxWasmDataSegments);
     875        2964 :     if (!CheckDataSegmentsCount(data_segments_count)) return;
     876             : 
     877        6873 :     module_->data_segments.reserve(data_segments_count);
     878        6454 :     for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
     879        1897 :       const byte* pos = pc();
     880        1897 :       if (!module_->has_memory) {
     881          65 :         error("cannot load data without memory");
     882          65 :         break;
     883             :       }
     884             :       TRACE("DecodeDataSegment[%d] module+%d\n", i,
     885             :             static_cast<int>(pc_ - start_));
     886             : 
     887             :       bool is_active;
     888             :       uint32_t memory_index;
     889             :       WasmInitExpr dest_addr;
     890             :       consume_segment_header("memory index", &is_active, &memory_index,
     891        1832 :                              &dest_addr);
     892        1832 :       if (failed()) break;
     893             : 
     894        1748 :       if (is_active && memory_index != 0) {
     895           0 :         errorf(pos, "illegal memory index %u != 0", memory_index);
     896           0 :         break;
     897             :       }
     898             : 
     899        1748 :       uint32_t source_length = consume_u32v("source size");
     900             :       uint32_t source_offset = pc_offset();
     901             : 
     902        1748 :       if (is_active) {
     903        1691 :         module_->data_segments.emplace_back(dest_addr);
     904             :       } else {
     905          57 :         module_->data_segments.emplace_back();
     906             :       }
     907             : 
     908             :       WasmDataSegment* segment = &module_->data_segments.back();
     909             : 
     910        1748 :       consume_bytes(source_length, "segment data");
     911        1748 :       if (failed()) break;
     912             : 
     913        1747 :       segment->source = {source_offset, source_length};
     914             :     }
     915             :   }
     916             : 
     917       22092 :   void DecodeNameSection() {
     918             :     // TODO(titzer): find a way to report name errors as warnings.
     919             :     // ignore all but the first occurrence of name section.
     920       22092 :     if (!has_seen_unordered_section(kNameSectionCode)) {
     921             :       set_seen_unordered_section(kNameSectionCode);
     922             :       // Use an inner decoder so that errors don't fail the outer decoder.
     923       22086 :       Decoder inner(start_, pc_, end_, buffer_offset_);
     924             :       // Decode all name subsections.
     925             :       // Be lenient with their order.
     926       44261 :       while (inner.ok() && inner.more()) {
     927             :         uint8_t name_type = inner.consume_u8("name type");
     928       22197 :         if (name_type & 0x80) inner.error("name type if not varuint7");
     929             : 
     930             :         uint32_t name_payload_len = inner.consume_u32v("name payload length");
     931       22200 :         if (!inner.checkAvailable(name_payload_len)) break;
     932             : 
     933             :         // Decode module name, ignore the rest.
     934             :         // Function and local names will be decoded when needed.
     935       22175 :         if (name_type == NameSectionKindCode::kModule) {
     936         139 :           WireBytesRef name = consume_string(inner, false, "module name");
     937         196 :           if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
     938             :         } else {
     939       22036 :           inner.consume_bytes(name_payload_len, "name subsection payload");
     940             :         }
     941             :       }
     942             :     }
     943             :     // Skip the whole names section in the outer decoder.
     944       22090 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     945       22090 :   }
     946             : 
     947          15 :   void DecodeSourceMappingURLSection() {
     948           8 :     Decoder inner(start_, pc_, end_, buffer_offset_);
     949           8 :     WireBytesRef url = wasm::consume_string(inner, true, "module name");
     950          15 :     if (inner.ok() &&
     951             :         !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
     952             :       const byte* url_start =
     953          12 :           inner.start() + inner.GetBufferRelativeOffset(url.offset());
     954           6 :       module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
     955          12 :                                      url.length());
     956             :       set_seen_unordered_section(kSourceMappingURLSectionCode);
     957             :     }
     958           8 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     959           8 :   }
     960             : 
     961             :   void DecodeDataCountSection() {
     962          56 :     module_->num_declared_data_segments =
     963          56 :         consume_count("data segments count", kV8MaxWasmDataSegments);
     964             :   }
     965             : 
     966         354 :   void DecodeExceptionSection() {
     967             :     uint32_t exception_count =
     968         354 :         consume_count("exception count", kV8MaxWasmExceptions);
     969        1522 :     for (uint32_t i = 0; ok() && i < exception_count; ++i) {
     970             :       TRACE("DecodeException[%d] module+%d\n", i,
     971             :             static_cast<int>(pc_ - start_));
     972         407 :       WasmExceptionSig* exception_sig = nullptr;
     973         407 :       consume_exception_attribute();  // Attribute ignored for now.
     974         407 :       consume_exception_sig_index(module_.get(), &exception_sig);
     975         407 :       module_->exceptions.emplace_back(exception_sig);
     976             :     }
     977         354 :   }
     978             : 
     979      263656 :   bool CheckMismatchedCounts() {
     980             :     // The declared vs. defined function count is normally checked when
     981             :     // decoding the code section, but we have to check it here too in case the
     982             :     // code section is absent.
     983      263656 :     if (module_->num_declared_functions != 0) {
     984             :       DCHECK_LT(module_->num_imported_functions, module_->functions.size());
     985             :       // We know that the code section has been decoded if the first
     986             :       // non-imported function has its code set.
     987      510642 :       if (!module_->functions[module_->num_imported_functions].code.is_set()) {
     988             :         errorf(pc(), "function count is %u, but code section is absent",
     989          22 :                module_->num_declared_functions);
     990          22 :         return false;
     991             :       }
     992             :     }
     993             :     // Perform a similar check for the DataCount and Data sections, where data
     994             :     // segments are declared but the Data section is absent.
     995      263637 :     if (!CheckDataSegmentsCount(
     996      527268 :             static_cast<uint32_t>(module_->data_segments.size()))) {
     997             :       return false;
     998             :     }
     999      263636 :     return true;
    1000             :   }
    1001             : 
    1002      278965 :   ModuleResult FinishDecoding(bool verify_functions = true) {
    1003      278965 :     if (ok() && CheckMismatchedCounts()) {
    1004      263638 :       CalculateGlobalOffsets(module_.get());
    1005             :     }
    1006      557931 :     ModuleResult result = toResult(std::move(module_));
    1007      522565 :     if (verify_functions && result.ok() && intermediate_error_.has_error()) {
    1008             :       // Copy error message and location.
    1009        6697 :       return ModuleResult{std::move(intermediate_error_)};
    1010             :     }
    1011      278969 :     return result;
    1012             :   }
    1013             : 
    1014             :   // Decodes an entire module.
    1015      281871 :   ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
    1016             :                             bool verify_functions = true) {
    1017      281871 :     StartDecoding(counters, allocator);
    1018             :     uint32_t offset = 0;
    1019      281874 :     Vector<const byte> orig_bytes(start(), end() - start());
    1020      281874 :     DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
    1021      281872 :     if (failed()) {
    1022       15212 :       return FinishDecoding(verify_functions);
    1023             :     }
    1024             :     // Size of the module header.
    1025             :     offset += 8;
    1026      274266 :     Decoder decoder(start_ + offset, end_, offset);
    1027             : 
    1028             :     WasmSectionIterator section_iter(decoder);
    1029             : 
    1030     3098641 :     while (ok() && section_iter.more()) {
    1031             :       // Shift the offset by the section header length
    1032     1278896 :       offset += section_iter.payload_start() - section_iter.section_start();
    1033     1278896 :       if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
    1034             :         DecodeSection(section_iter.section_code(), section_iter.payload(),
    1035     2556472 :                       offset, verify_functions);
    1036             :       }
    1037             :       // Shift the offset by the remaining section payload
    1038     2557776 :       offset += section_iter.payload_length();
    1039     1278888 :       section_iter.advance(true);
    1040             :     }
    1041             : 
    1042             :     if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
    1043             : 
    1044      274267 :     if (decoder.failed()) {
    1045        9249 :       return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
    1046             :     }
    1047             : 
    1048      542367 :     return FinishDecoding(verify_functions);
    1049             :   }
    1050             : 
    1051             :   // Decodes a single anonymous function starting at {start_}.
    1052           2 :   FunctionResult DecodeSingleFunction(Zone* zone,
    1053             :                                       const ModuleWireBytes& wire_bytes,
    1054             :                                       const WasmModule* module,
    1055           1 :                                       std::unique_ptr<WasmFunction> function) {
    1056           1 :     pc_ = start_;
    1057           1 :     function->sig = consume_sig(zone);
    1058           2 :     function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
    1059             : 
    1060           1 :     if (ok())
    1061             :       VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
    1062           1 :                          function.get());
    1063             : 
    1064           1 :     if (intermediate_error_.has_error()) {
    1065           0 :       return FunctionResult{std::move(intermediate_error_)};
    1066             :     }
    1067             : 
    1068           1 :     return FunctionResult(std::move(function));
    1069             :   }
    1070             : 
    1071             :   // Decodes a single function signature at {start}.
    1072             :   FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
    1073         262 :     pc_ = start;
    1074         262 :     FunctionSig* result = consume_sig(zone);
    1075         262 :     return ok() ? result : nullptr;
    1076             :   }
    1077             : 
    1078             :   WasmInitExpr DecodeInitExpr(const byte* start) {
    1079          22 :     pc_ = start;
    1080          22 :     return consume_init_expr(nullptr, kWasmStmt);
    1081             :   }
    1082             : 
    1083             :   const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
    1084             : 
    1085             :   Counters* GetCounters() const {
    1086             :     DCHECK_NOT_NULL(counters_);
    1087             :     return counters_;
    1088             :   }
    1089             : 
    1090             :   void SetCounters(Counters* counters) {
    1091             :     DCHECK_NULL(counters_);
    1092      282198 :     counters_ = counters;
    1093             :   }
    1094             : 
    1095             :  private:
    1096             :   const WasmFeatures enabled_features_;
    1097             :   std::shared_ptr<WasmModule> module_;
    1098             :   Counters* counters_ = nullptr;
    1099             :   // The type section is the first section in a module.
    1100             :   uint8_t next_ordered_section_ = kFirstSectionInModule;
    1101             :   // We store next_ordered_section_ as uint8_t instead of SectionCode so that we
    1102             :   // can increment it. This static_assert should make sure that SectionCode does
    1103             :   // not get bigger than uint8_t accidentially.
    1104             :   static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
    1105             :                     sizeof(SectionCode),
    1106             :                 "type mismatch");
    1107             :   uint32_t seen_unordered_sections_ = 0;
    1108             :   static_assert(kBitsPerByte *
    1109             :                         sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
    1110             :                     kLastKnownModuleSection,
    1111             :                 "not enough bits");
    1112             :   WasmError intermediate_error_;
    1113             :   ModuleOrigin origin_;
    1114             : 
    1115             :   bool has_seen_unordered_section(SectionCode section_code) {
    1116      287644 :     return seen_unordered_sections_ & (1 << section_code);
    1117             :   }
    1118             : 
    1119             :   void set_seen_unordered_section(SectionCode section_code) {
    1120       22517 :     seen_unordered_sections_ |= 1 << section_code;
    1121             :   }
    1122             : 
    1123             :   uint32_t off(const byte* ptr) {
    1124           1 :     return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
    1125             :   }
    1126             : 
    1127        3900 :   bool AddTable(WasmModule* module) {
    1128        3900 :     if (enabled_features_.anyref) return true;
    1129        7760 :     if (module->tables.size() > 0) {
    1130          32 :       error("At most one table is supported");
    1131          32 :       return false;
    1132             :     } else {
    1133             :       return true;
    1134             :     }
    1135             :   }
    1136             : 
    1137             :   bool AddMemory(WasmModule* module) {
    1138       15354 :     if (module->has_memory) {
    1139          64 :       error("At most one memory is supported");
    1140             :       return false;
    1141             :     } else {
    1142       15290 :       module->has_memory = true;
    1143             :       return true;
    1144             :     }
    1145             :   }
    1146             : 
    1147             :   // Decodes a single global entry inside a module starting at {pc_}.
    1148      440956 :   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
    1149             :                             WasmGlobal* global) {
    1150      440956 :     global->type = consume_value_type();
    1151      440956 :     global->mutability = consume_mutability();
    1152      440956 :     const byte* pos = pc();
    1153      440956 :     global->init = consume_init_expr(module, kWasmStmt);
    1154      440956 :     if (global->init.kind == WasmInitExpr::kGlobalIndex) {
    1155          65 :       uint32_t other_index = global->init.val.global_index;
    1156          65 :       if (other_index >= index) {
    1157             :         errorf(pos,
    1158             :                "invalid global index in init expression, "
    1159             :                "index %u, other_index %u",
    1160           0 :                index, other_index);
    1161         130 :       } else if (module->globals[other_index].type != global->type) {
    1162             :         errorf(pos,
    1163             :                "type mismatch in global initialization "
    1164             :                "(from global #%u), expected %s, got %s",
    1165             :                other_index, ValueTypes::TypeName(global->type),
    1166           0 :                ValueTypes::TypeName(module->globals[other_index].type));
    1167             :       }
    1168             :     } else {
    1169      440891 :       if (global->type != TypeOf(module, global->init)) {
    1170             :         errorf(pos, "type error in global initialization, expected %s, got %s",
    1171             :                ValueTypes::TypeName(global->type),
    1172         384 :                ValueTypes::TypeName(TypeOf(module, global->init)));
    1173             :       }
    1174             :     }
    1175      440956 :   }
    1176             : 
    1177             :   // Decodes a single data segment entry inside a module starting at {pc_}.
    1178             : 
    1179             :   // Calculate individual global offsets and total size of globals table.
    1180      265905 :   void CalculateGlobalOffsets(WasmModule* module) {
    1181             :     uint32_t untagged_offset = 0;
    1182             :     uint32_t tagged_offset = 0;
    1183             :     uint32_t num_imported_mutable_globals = 0;
    1184     1415419 :     for (WasmGlobal& global : module->globals) {
    1185      883609 :       if (global.mutability && global.imported) {
    1186         313 :         global.index = num_imported_mutable_globals++;
    1187      883296 :       } else if (global.type == ValueType::kWasmAnyRef) {
    1188         278 :         global.offset = tagged_offset;
    1189             :         // All entries in the tagged_globals_buffer have size 1.
    1190         278 :         tagged_offset++;
    1191             :       } else {
    1192             :         byte size =
    1193      883018 :             ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
    1194      883018 :         untagged_offset = (untagged_offset + size - 1) & ~(size - 1);  // align
    1195      883018 :         global.offset = untagged_offset;
    1196      883018 :         untagged_offset += size;
    1197             :       }
    1198             :     }
    1199      265905 :     module->untagged_globals_buffer_size = untagged_offset;
    1200      265905 :     module->tagged_globals_buffer_size = tagged_offset;
    1201      265905 :   }
    1202             : 
    1203             :   // Verifies the body (code) of a given function.
    1204      135603 :   void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
    1205             :                           const ModuleWireBytes& wire_bytes,
    1206      135603 :                           const WasmModule* module, WasmFunction* function) {
    1207             :     WasmFunctionName func_name(function,
    1208      135603 :                                wire_bytes.GetNameOrNull(function, module));
    1209             :     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
    1210             :       StdoutStream os;
    1211             :       os << "Verifying wasm function " << func_name << std::endl;
    1212             :     }
    1213             :     FunctionBody body = {
    1214             :         function->sig, function->code.offset(),
    1215             :         start_ + GetBufferRelativeOffset(function->code.offset()),
    1216      542412 :         start_ + GetBufferRelativeOffset(function->code.end_offset())};
    1217             : 
    1218             :     DecodeResult result;
    1219             :     {
    1220      271206 :       auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
    1221             :                                               wasm_decode, function_time);
    1222             : 
    1223             :       TimedHistogramScope wasm_decode_function_time_scope(time_counter);
    1224      135603 :       WasmFeatures unused_detected_features;
    1225      271206 :       result = VerifyWasmCode(allocator, enabled_features_, module,
    1226             :                               &unused_detected_features, body);
    1227             :     }
    1228             : 
    1229             :     // If the decode failed and this is the first error, set error code and
    1230             :     // location.
    1231      142332 :     if (result.failed() && intermediate_error_.empty()) {
    1232             :       // Wrap the error message from the function decoder.
    1233        6729 :       std::ostringstream error_msg;
    1234        6729 :       error_msg << "in function " << func_name << ": "
    1235             :                 << result.error().message();
    1236       20187 :       intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
    1237             :     }
    1238      135603 :   }
    1239             : 
    1240      612556 :   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
    1241      612556 :     const byte* pos = pc_;
    1242      612556 :     uint32_t sig_index = consume_u32v("signature index");
    1243     1225112 :     if (sig_index >= module->signatures.size()) {
    1244             :       errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
    1245        5740 :              static_cast<int>(module->signatures.size()));
    1246        5740 :       *sig = nullptr;
    1247        5740 :       return 0;
    1248             :     }
    1249      606816 :     *sig = module->signatures[sig_index];
    1250      606816 :     return sig_index;
    1251             :   }
    1252             : 
    1253         512 :   uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
    1254         512 :     const byte* pos = pc_;
    1255         512 :     uint32_t sig_index = consume_sig_index(module, sig);
    1256         512 :     if (*sig && (*sig)->return_count() != 0) {
    1257           2 :       errorf(pos, "exception signature %u has non-void return", sig_index);
    1258           2 :       *sig = nullptr;
    1259           2 :       return 0;
    1260             :     }
    1261             :     return sig_index;
    1262             :   }
    1263             : 
    1264     2128101 :   uint32_t consume_count(const char* name, size_t maximum) {
    1265     2128101 :     const byte* p = pc_;
    1266     2128101 :     uint32_t count = consume_u32v(name);
    1267     2128118 :     if (count > maximum) {
    1268         118 :       errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
    1269         118 :       return static_cast<uint32_t>(maximum);
    1270             :     }
    1271             :     return count;
    1272             :   }
    1273             : 
    1274             :   uint32_t consume_func_index(WasmModule* module, WasmFunction** func,
    1275             :                               const char* name) {
    1276      357515 :     return consume_index(name, module->functions, func);
    1277             :   }
    1278             : 
    1279             :   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
    1280        1010 :     return consume_index("global index", module->globals, global);
    1281             :   }
    1282             : 
    1283             :   uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
    1284         680 :     return consume_index("table index", module->tables, table);
    1285             :   }
    1286             : 
    1287             :   uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
    1288         145 :     return consume_index("exception index", module->exceptions, except);
    1289             :   }
    1290             : 
    1291             :   template <typename T>
    1292      718698 :   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
    1293      359349 :     const byte* pos = pc_;
    1294      359349 :     uint32_t index = consume_u32v(name);
    1295      718698 :     if (index >= vector.size()) {
    1296         115 :       errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
    1297             :              static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
    1298         115 :       *ptr = nullptr;
    1299         115 :       return 0;
    1300             :     }
    1301      359234 :     *ptr = &vector[index];
    1302      359234 :     return index;
    1303             :   }
    1304             : 
    1305        3868 :   uint8_t validate_table_flags(const char* name) {
    1306        7736 :     uint8_t flags = consume_u8("resizable limits flags");
    1307             :     const byte* pos = pc();
    1308        3868 :     if (flags & 0xFE) {
    1309           8 :       errorf(pos - 1, "invalid %s limits flags", name);
    1310             :     }
    1311        3868 :     return flags;
    1312             :   }
    1313             : 
    1314       15289 :   uint8_t validate_memory_flags(bool* has_shared_memory) {
    1315       30583 :     uint8_t flags = consume_u8("resizable limits flags");
    1316             :     const byte* pos = pc();
    1317       15294 :     *has_shared_memory = false;
    1318       15294 :     if (enabled_features_.threads) {
    1319        1332 :       if (flags & 0xFC) {
    1320           0 :         errorf(pos - 1, "invalid memory limits flags");
    1321        1332 :       } else if (flags == 3) {
    1322             :         DCHECK_NOT_NULL(has_shared_memory);
    1323        1256 :         *has_shared_memory = true;
    1324          76 :       } else if (flags == 2) {
    1325             :         errorf(pos - 1,
    1326             :                "memory limits flags should have maximum defined if shared is "
    1327           8 :                "true");
    1328             :       }
    1329             :     } else {
    1330       13962 :       if (flags & 0xFE) {
    1331          16 :         errorf(pos - 1, "invalid memory limits flags");
    1332             :       }
    1333             :     }
    1334       15294 :     return flags;
    1335             :   }
    1336             : 
    1337       19157 :   void consume_resizable_limits(const char* name, const char* units,
    1338             :                                 uint32_t max_initial, uint32_t* initial,
    1339             :                                 bool* has_max, uint32_t max_maximum,
    1340             :                                 uint32_t* maximum, uint8_t flags) {
    1341       24806 :     const byte* pos = pc();
    1342       38317 :     *initial = consume_u32v("initial size");
    1343       19160 :     *has_max = false;
    1344       19160 :     if (*initial > max_initial) {
    1345             :       errorf(pos,
    1346             :              "initial %s size (%u %s) is larger than implementation limit (%u)",
    1347          48 :              name, *initial, units, max_initial);
    1348             :     }
    1349       19163 :     if (flags & 1) {
    1350        5649 :       *has_max = true;
    1351             :       pos = pc();
    1352        5648 :       *maximum = consume_u32v("maximum size");
    1353        5648 :       if (*maximum > max_maximum) {
    1354             :         errorf(
    1355             :             pos,
    1356             :             "maximum %s size (%u %s) is larger than implementation limit (%u)",
    1357          49 :             name, *maximum, units, max_maximum);
    1358             :       }
    1359        5649 :       if (*maximum < *initial) {
    1360             :         errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
    1361          16 :                name, *maximum, units, *initial, units);
    1362             :       }
    1363             :     } else {
    1364       13514 :       *has_max = false;
    1365       13514 :       *maximum = max_initial;
    1366             :     }
    1367       19163 :   }
    1368             : 
    1369     1008873 :   bool expect_u8(const char* name, uint8_t expected) {
    1370     1008873 :     const byte* pos = pc();
    1371     1008873 :     uint8_t value = consume_u8(name);
    1372     1008874 :     if (value != expected) {
    1373         680 :       errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
    1374         680 :       return false;
    1375             :     }
    1376             :     return true;
    1377             :   }
    1378             : 
    1379      445230 :   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
    1380      890168 :     const byte* pos = pc();
    1381      445230 :     uint8_t opcode = consume_u8("opcode");
    1382             :     WasmInitExpr expr;
    1383             :     uint32_t len = 0;
    1384      445230 :     switch (opcode) {
    1385             :       case kExprGetGlobal: {
    1386         372 :         GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
    1387         744 :         if (module->globals.size() <= imm.index) {
    1388          16 :           error("global index is out of bounds");
    1389          16 :           expr.kind = WasmInitExpr::kNone;
    1390          16 :           expr.val.i32_const = 0;
    1391          16 :           break;
    1392             :         }
    1393             :         WasmGlobal* global = &module->globals[imm.index];
    1394         356 :         if (global->mutability || !global->imported) {
    1395             :           error(
    1396             :               "only immutable imported globals can be used in initializer "
    1397          18 :               "expressions");
    1398          18 :           expr.kind = WasmInitExpr::kNone;
    1399          18 :           expr.val.i32_const = 0;
    1400          18 :           break;
    1401             :         }
    1402         338 :         expr.kind = WasmInitExpr::kGlobalIndex;
    1403         338 :         expr.val.global_index = imm.index;
    1404         338 :         len = imm.length;
    1405         338 :         break;
    1406             :       }
    1407             :       case kExprI32Const: {
    1408             :         ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1409        7637 :         expr.kind = WasmInitExpr::kI32Const;
    1410        7637 :         expr.val.i32_const = imm.value;
    1411        7637 :         len = imm.length;
    1412             :         break;
    1413             :       }
    1414             :       case kExprF32Const: {
    1415      436038 :         ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1416      436038 :         expr.kind = WasmInitExpr::kF32Const;
    1417      436038 :         expr.val.f32_const = imm.value;
    1418      436038 :         len = imm.length;
    1419             :         break;
    1420             :       }
    1421             :       case kExprI64Const: {
    1422             :         ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1423         316 :         expr.kind = WasmInitExpr::kI64Const;
    1424         316 :         expr.val.i64_const = imm.value;
    1425         316 :         len = imm.length;
    1426             :         break;
    1427             :       }
    1428             :       case kExprF64Const: {
    1429         575 :         ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1430         575 :         expr.kind = WasmInitExpr::kF64Const;
    1431         575 :         expr.val.f64_const = imm.value;
    1432         575 :         len = imm.length;
    1433             :         break;
    1434             :       }
    1435             :       case kExprRefNull: {
    1436         114 :         if (enabled_features_.anyref) {
    1437         114 :           expr.kind = WasmInitExpr::kAnyRefConst;
    1438             :           len = 0;
    1439         114 :           break;
    1440             :         }
    1441             :         V8_FALLTHROUGH;
    1442             :       }
    1443             :       default: {
    1444         178 :         error("invalid opcode in initialization expression");
    1445         178 :         expr.kind = WasmInitExpr::kNone;
    1446         178 :         expr.val.i32_const = 0;
    1447             :       }
    1448             :     }
    1449      445230 :     consume_bytes(len, "init code");
    1450      445230 :     if (!expect_u8("end opcode", kExprEnd)) {
    1451         552 :       expr.kind = WasmInitExpr::kNone;
    1452             :     }
    1453      445230 :     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
    1454             :       errorf(pos, "type error in init expression, expected %s, got %s",
    1455             :              ValueTypes::TypeName(expected),
    1456         213 :              ValueTypes::TypeName(TypeOf(module, expr)));
    1457             :     }
    1458      445230 :     return expr;
    1459             :   }
    1460             : 
    1461             :   // Read a mutability flag
    1462      443032 :   bool consume_mutability() {
    1463      443032 :     byte val = consume_u8("mutability");
    1464      443032 :     if (val > 1) error(pc_ - 1, "invalid mutability");
    1465      443032 :     return val != 0;
    1466             :   }
    1467             : 
    1468             :   // Reads a single 8-bit integer, interpreting it as a local type.
    1469     1325583 :   ValueType consume_value_type() {
    1470     1325583 :     byte val = consume_u8("value type");
    1471             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1472     1325590 :     switch (t) {
    1473             :       case kLocalI32:
    1474             :         return kWasmI32;
    1475             :       case kLocalI64:
    1476       33876 :         return kWasmI64;
    1477             :       case kLocalF32:
    1478      706556 :         return kWasmF32;
    1479             :       case kLocalF64:
    1480      277471 :         return kWasmF64;
    1481             :       default:
    1482        2863 :         if (origin_ == kWasmOrigin) {
    1483        2863 :           switch (t) {
    1484             :             case kLocalS128:
    1485          32 :               if (enabled_features_.simd) return kWasmS128;
    1486             :               break;
    1487             :             case kLocalAnyFunc:
    1488         149 :               if (enabled_features_.anyref) return kWasmAnyFunc;
    1489             :               break;
    1490             :             case kLocalAnyRef:
    1491        2656 :               if (enabled_features_.anyref) return kWasmAnyRef;
    1492             :               break;
    1493             :             default:
    1494             :               break;
    1495             :           }
    1496             :         }
    1497          48 :         error(pc_ - 1, "invalid local type");
    1498          48 :         return kWasmStmt;
    1499             :     }
    1500             :   }
    1501             : 
    1502             :   // Reads a single 8-bit integer, interpreting it as a reference type.
    1503        3868 :   ValueType consume_reference_type() {
    1504        3868 :     byte val = consume_u8("reference type");
    1505             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1506        3868 :     switch (t) {
    1507             :       case kLocalAnyFunc:
    1508             :         return kWasmAnyFunc;
    1509             :       case kLocalAnyRef:
    1510           3 :         if (!enabled_features_.anyref) {
    1511             :           error(pc_ - 1,
    1512           0 :                 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
    1513             :         }
    1514             :         return kWasmAnyRef;
    1515             :       default:
    1516             :         break;
    1517             :     }
    1518           2 :     error(pc_ - 1, "invalid reference type");
    1519           2 :     return kWasmStmt;
    1520             :   }
    1521             : 
    1522      563643 :   FunctionSig* consume_sig(Zone* zone) {
    1523      563643 :     if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
    1524             :     // parse parameter types
    1525             :     uint32_t param_count =
    1526      563516 :         consume_count("param count", kV8MaxWasmFunctionParams);
    1527      563516 :     if (failed()) return nullptr;
    1528             :     std::vector<ValueType> params;
    1529     2259666 :     for (uint32_t i = 0; ok() && i < param_count; ++i) {
    1530      566316 :       ValueType param = consume_value_type();
    1531      566318 :       params.push_back(param);
    1532             :     }
    1533             :     std::vector<ValueType> returns;
    1534             :     // parse return types
    1535             :     const size_t max_return_count = enabled_features_.mv
    1536             :                                         ? kV8MaxWasmFunctionMultiReturns
    1537      563517 :                                         : kV8MaxWasmFunctionReturns;
    1538      563517 :     uint32_t return_count = consume_count("return count", max_return_count);
    1539      563516 :     if (failed()) return nullptr;
    1540     1195907 :     for (uint32_t i = 0; ok() && i < return_count; ++i) {
    1541      316238 :       ValueType ret = consume_value_type();
    1542      316238 :       returns.push_back(ret);
    1543             :     }
    1544             : 
    1545      563428 :     if (failed()) return nullptr;
    1546             : 
    1547             :     // FunctionSig stores the return types first.
    1548      563416 :     ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
    1549             :     uint32_t b = 0;
    1550      879645 :     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
    1551     1132556 :     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
    1552             : 
    1553     1126832 :     return new (zone) FunctionSig(return_count, param_count, buffer);
    1554             :   }
    1555             : 
    1556             :   // Consume the attribute field of an exception.
    1557         512 :   uint32_t consume_exception_attribute() {
    1558         512 :     const byte* pos = pc_;
    1559         512 :     uint32_t attribute = consume_u32v("exception attribute");
    1560         512 :     if (attribute != kExceptionAttribute) {
    1561           1 :       errorf(pos, "exception attribute %u not supported", attribute);
    1562           1 :       return 0;
    1563             :     }
    1564             :     return attribute;
    1565             :   }
    1566             : 
    1567        4354 :   void consume_segment_header(const char* name, bool* is_active,
    1568             :                               uint32_t* index, WasmInitExpr* offset) {
    1569        4354 :     const byte* pos = pc();
    1570             :     // In the MVP, this is a table or memory index field that must be 0, but
    1571             :     // we've repurposed it as a flags field in the bulk memory proposal.
    1572             :     uint32_t flags;
    1573        4354 :     if (enabled_features_.bulk_memory) {
    1574         159 :       flags = consume_u32v("flags");
    1575         159 :       if (failed()) return;
    1576             :     } else {
    1577             :       // Without the bulk memory proposal, we should still read the table index.
    1578             :       // This is the same as reading the `ActiveWithIndex` flag with the bulk
    1579             :       // memory proposal.
    1580             :       flags = SegmentFlags::kActiveWithIndex;
    1581             :     }
    1582             : 
    1583             :     bool read_index;
    1584             :     bool read_offset;
    1585        4354 :     if (flags == SegmentFlags::kActiveNoIndex) {
    1586          48 :       *is_active = true;
    1587             :       read_index = false;
    1588             :       read_offset = true;
    1589        4306 :     } else if (flags == SegmentFlags::kPassive) {
    1590         102 :       *is_active = false;
    1591             :       read_index = false;
    1592             :       read_offset = false;
    1593        4204 :     } else if (flags == SegmentFlags::kActiveWithIndex) {
    1594        4204 :       *is_active = true;
    1595             :       read_index = true;
    1596             :       read_offset = true;
    1597             :     } else {
    1598           0 :       errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
    1599           0 :       return;
    1600             :     }
    1601             : 
    1602        4354 :     if (read_index) {
    1603        8408 :       *index = consume_u32v(name);
    1604             :     } else {
    1605         150 :       *index = 0;
    1606             :     }
    1607             : 
    1608        4354 :     if (read_offset) {
    1609        4252 :       *offset = consume_init_expr(module_.get(), kWasmI32);
    1610             :     }
    1611             :   }
    1612             : };
    1613             : 
    1614      281867 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
    1615             :                               const byte* module_start, const byte* module_end,
    1616             :                               bool verify_functions, ModuleOrigin origin,
    1617             :                               Counters* counters,
    1618             :                               AccountingAllocator* allocator) {
    1619             :   auto counter =
    1620      281867 :       SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
    1621             :   TimedHistogramScope wasm_decode_module_time_scope(counter);
    1622      281873 :   size_t size = module_end - module_start;
    1623      281873 :   CHECK_LE(module_start, module_end);
    1624      281873 :   if (size >= kV8MaxWasmModuleSize) {
    1625             :     return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
    1626           0 :                                   kV8MaxWasmModuleSize, size}};
    1627             :   }
    1628             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1629             :   auto size_counter =
    1630      281873 :       SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
    1631      281873 :   size_counter->AddSample(static_cast<int>(size));
    1632             :   // Signatures are stored in zone memory, which have the same lifetime
    1633             :   // as the {module}.
    1634      563746 :   ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
    1635             :   ModuleResult result =
    1636      845614 :       decoder.DecodeModule(counters, allocator, verify_functions);
    1637             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1638             :   // TODO(titzer): this isn't accurate, since it doesn't count the data
    1639             :   // allocated on the C++ heap.
    1640             :   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
    1641      281870 :   if (result.ok()) {
    1642      256814 :     auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
    1643             :                                             module_peak_memory_bytes);
    1644             :     peak_counter->AddSample(
    1645      513628 :         static_cast<int>(result.value()->signature_zone->allocation_size()));
    1646             :   }
    1647             :   return result;
    1648             : }
    1649             : 
    1650         356 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
    1651         356 :     : enabled_features_(enabled) {}
    1652             : 
    1653             : ModuleDecoder::~ModuleDecoder() = default;
    1654             : 
    1655         616 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
    1656         616 :   return impl_->shared_module();
    1657             : }
    1658             : 
    1659         328 : void ModuleDecoder::StartDecoding(Counters* counters,
    1660             :                                   AccountingAllocator* allocator,
    1661             :                                   ModuleOrigin origin) {
    1662             :   DCHECK_NULL(impl_);
    1663         328 :   impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
    1664         328 :   impl_->StartDecoding(counters, allocator);
    1665         328 : }
    1666             : 
    1667         328 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
    1668             :                                        uint32_t offset) {
    1669         656 :   impl_->DecodeModuleHeader(bytes, offset);
    1670         328 : }
    1671             : 
    1672         724 : void ModuleDecoder::DecodeSection(SectionCode section_code,
    1673             :                                   Vector<const uint8_t> bytes, uint32_t offset,
    1674             :                                   bool verify_functions) {
    1675        1448 :   impl_->DecodeSection(section_code, bytes, offset, verify_functions);
    1676         724 : }
    1677             : 
    1678         424 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
    1679             :                                        uint32_t offset, bool verify_functions) {
    1680         848 :   impl_->DecodeFunctionBody(index, length, offset, verify_functions);
    1681         424 : }
    1682             : 
    1683         204 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
    1684             :                                         uint32_t offset) {
    1685         204 :   return impl_->CheckFunctionsCount(functions_count, offset);
    1686             : }
    1687             : 
    1688         180 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
    1689         540 :   return impl_->FinishDecoding(verify_functions);
    1690             : }
    1691             : 
    1692      112428 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
    1693             :                                                   const byte* end) {
    1694       33850 :   WireBytesRef string = consume_string(decoder, true, "section name");
    1695       60409 :   if (decoder.failed() || decoder.pc() > end) {
    1696             :     return kUnknownSectionCode;
    1697             :   }
    1698             :   const byte* section_name_start =
    1699       52022 :       decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
    1700             : 
    1701             :   TRACE("  +%d  section name        : \"%.*s\"\n",
    1702             :         static_cast<int>(section_name_start - decoder.start()),
    1703             :         string.length() < 20 ? string.length() : 20, section_name_start);
    1704             : 
    1705       50875 :   if (string.length() == num_chars(kNameString) &&
    1706             :       strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
    1707       24864 :               num_chars(kNameString)) == 0) {
    1708             :     return kNameSectionCode;
    1709        1337 :   } else if (string.length() == num_chars(kSourceMappingURLString) &&
    1710             :              strncmp(reinterpret_cast<const char*>(section_name_start),
    1711             :                      kSourceMappingURLString,
    1712         144 :                      num_chars(kSourceMappingURLString)) == 0) {
    1713             :     return kSourceMappingURLSectionCode;
    1714             :   }
    1715        1177 :   return kUnknownSectionCode;
    1716             : }
    1717             : 
    1718        2104 : bool ModuleDecoder::ok() { return impl_->ok(); }
    1719             : 
    1720         262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
    1721             :                                            Zone* zone, const byte* start,
    1722             :                                            const byte* end) {
    1723         262 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1724         262 :   return decoder.DecodeFunctionSignature(zone, start);
    1725             : }
    1726             : 
    1727          22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
    1728             :                                           const byte* start, const byte* end) {
    1729          22 :   AccountingAllocator allocator;
    1730          44 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1731          22 :   return decoder.DecodeInitExpr(start);
    1732             : }
    1733             : 
    1734           1 : FunctionResult DecodeWasmFunctionForTesting(
    1735             :     const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
    1736             :     const WasmModule* module, const byte* function_start,
    1737             :     const byte* function_end, Counters* counters) {
    1738           1 :   size_t size = function_end - function_start;
    1739           1 :   CHECK_LE(function_start, function_end);
    1740           1 :   auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
    1741             :                                             function_size_bytes);
    1742             :   // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
    1743           1 :   size_histogram->AddSample(static_cast<int>(size));
    1744           1 :   if (size > kV8MaxWasmFunctionSize) {
    1745             :     return FunctionResult{WasmError{0,
    1746             :                                     "size > maximum function size (%zu): %zu",
    1747           0 :                                     kV8MaxWasmFunctionSize, size}};
    1748             :   }
    1749           1 :   ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
    1750             :   decoder.SetCounters(counters);
    1751             :   return decoder.DecodeSingleFunction(zone, wire_bytes, module,
    1752           3 :                                       base::make_unique<WasmFunction>());
    1753             : }
    1754             : 
    1755         140 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
    1756             :                                       const byte* tables_end) {
    1757             :   AsmJsOffsets table;
    1758             : 
    1759             :   Decoder decoder(tables_start, tables_end);
    1760             :   uint32_t functions_count = decoder.consume_u32v("functions count");
    1761             :   // Reserve space for the entries, taking care of invalid input.
    1762         140 :   if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
    1763         140 :     table.reserve(functions_count);
    1764             :   }
    1765             : 
    1766         664 :   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
    1767             :     uint32_t size = decoder.consume_u32v("table size");
    1768         332 :     if (size == 0) {
    1769         140 :       table.emplace_back();
    1770         140 :       continue;
    1771             :     }
    1772         192 :     if (!decoder.checkAvailable(size)) {
    1773           0 :       decoder.error("illegal asm function offset table size");
    1774             :     }
    1775         192 :     const byte* table_end = decoder.pc() + size;
    1776             :     uint32_t locals_size = decoder.consume_u32v("locals size");
    1777         192 :     int function_start_position = decoder.consume_u32v("function start pos");
    1778         192 :     int last_byte_offset = locals_size;
    1779             :     int last_asm_position = function_start_position;
    1780             :     std::vector<AsmJsOffsetEntry> func_asm_offsets;
    1781         192 :     func_asm_offsets.reserve(size / 4);  // conservative estimation
    1782             :     // Add an entry for the stack check, associated with position 0.
    1783             :     func_asm_offsets.push_back(
    1784         384 :         {0, function_start_position, function_start_position});
    1785         640 :     while (decoder.ok() && decoder.pc() < table_end) {
    1786         256 :       last_byte_offset += decoder.consume_u32v("byte offset delta");
    1787             :       int call_position =
    1788         256 :           last_asm_position + decoder.consume_i32v("call position delta");
    1789             :       int to_number_position =
    1790         256 :           call_position + decoder.consume_i32v("to_number position delta");
    1791             :       last_asm_position = to_number_position;
    1792             :       func_asm_offsets.push_back(
    1793         512 :           {last_byte_offset, call_position, to_number_position});
    1794             :     }
    1795         192 :     if (decoder.pc() != table_end) {
    1796           0 :       decoder.error("broken asm offset table");
    1797             :     }
    1798             :     table.push_back(std::move(func_asm_offsets));
    1799             :   }
    1800         140 :   if (decoder.more()) decoder.error("unexpected additional bytes");
    1801             : 
    1802         420 :   return decoder.toResult(std::move(table));
    1803             : }
    1804             : 
    1805         250 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
    1806             :                                                       const byte* end) {
    1807             :   Decoder decoder(start, end);
    1808         250 :   decoder.consume_bytes(4, "wasm magic");
    1809         250 :   decoder.consume_bytes(4, "wasm version");
    1810             : 
    1811             :   std::vector<CustomSectionOffset> result;
    1812             : 
    1813         577 :   while (decoder.more()) {
    1814             :     byte section_code = decoder.consume_u8("section code");
    1815             :     uint32_t section_length = decoder.consume_u32v("section length");
    1816             :     uint32_t section_start = decoder.pc_offset();
    1817         335 :     if (section_code != 0) {
    1818             :       // Skip known sections.
    1819           2 :       decoder.consume_bytes(section_length, "section bytes");
    1820           2 :       continue;
    1821             :     }
    1822             :     uint32_t name_length = decoder.consume_u32v("name length");
    1823             :     uint32_t name_offset = decoder.pc_offset();
    1824         333 :     decoder.consume_bytes(name_length, "section name");
    1825             :     uint32_t payload_offset = decoder.pc_offset();
    1826         333 :     if (section_length < (payload_offset - section_start)) {
    1827           8 :       decoder.error("invalid section length");
    1828           8 :       break;
    1829             :     }
    1830         325 :     uint32_t payload_length = section_length - (payload_offset - section_start);
    1831         325 :     decoder.consume_bytes(payload_length);
    1832         325 :     if (decoder.failed()) break;
    1833             :     result.push_back({{section_start, section_length},
    1834             :                       {name_offset, name_length},
    1835         325 :                       {payload_offset, payload_length}});
    1836             :   }
    1837             : 
    1838         250 :   return result;
    1839             : }
    1840             : 
    1841             : namespace {
    1842             : 
    1843      125301 : bool FindNameSection(Decoder& decoder) {
    1844             :   static constexpr int kModuleHeaderSize = 8;
    1845      125301 :   decoder.consume_bytes(kModuleHeaderSize, "module header");
    1846             : 
    1847             :   WasmSectionIterator section_iter(decoder);
    1848             : 
    1849      253879 :   while (decoder.ok() && section_iter.more() &&
    1850       41462 :          section_iter.section_code() != kNameSectionCode) {
    1851       38741 :     section_iter.advance(true);
    1852             :   }
    1853      250602 :   if (!section_iter.more()) return false;
    1854             : 
    1855             :   // Reset the decoder to not read beyond the name section end.
    1856             :   decoder.Reset(section_iter.payload(), decoder.pc_offset());
    1857        2721 :   return true;
    1858             : }
    1859             : 
    1860             : }  // namespace
    1861             : 
    1862      125281 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
    1863             :                          std::unordered_map<uint32_t, WireBytesRef>* names) {
    1864             :   DCHECK_NOT_NULL(names);
    1865             :   DCHECK(names->empty());
    1866             : 
    1867             :   Decoder decoder(module_start, module_end);
    1868      250562 :   if (!FindNameSection(decoder)) return;
    1869             : 
    1870        5418 :   while (decoder.ok() && decoder.more()) {
    1871             :     uint8_t name_type = decoder.consume_u8("name type");
    1872        2717 :     if (name_type & 0x80) break;  // no varuint7
    1873             : 
    1874             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    1875        2717 :     if (!decoder.checkAvailable(name_payload_len)) break;
    1876             : 
    1877        2717 :     if (name_type != NameSectionKindCode::kFunction) {
    1878          28 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    1879          28 :       continue;
    1880             :     }
    1881             :     uint32_t functions_count = decoder.consume_u32v("functions count");
    1882             : 
    1883       34346 :     for (; decoder.ok() && functions_count > 0; --functions_count) {
    1884             :       uint32_t function_index = decoder.consume_u32v("function index");
    1885       14484 :       WireBytesRef name = consume_string(decoder, false, "function name");
    1886             : 
    1887             :       // Be lenient with errors in the name section: Ignore non-UTF8 names. You
    1888             :       // can even assign to the same function multiple times (last valid one
    1889             :       // wins).
    1890       28968 :       if (decoder.ok() && validate_utf8(&decoder, name)) {
    1891       28952 :         names->insert(std::make_pair(function_index, name));
    1892             :       }
    1893             :     }
    1894             :   }
    1895             : }
    1896             : 
    1897          20 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
    1898             :                       LocalNames* result) {
    1899             :   DCHECK_NOT_NULL(result);
    1900             :   DCHECK(result->names.empty());
    1901             : 
    1902             :   Decoder decoder(module_start, module_end);
    1903          40 :   if (!FindNameSection(decoder)) return;
    1904             : 
    1905          44 :   while (decoder.ok() && decoder.more()) {
    1906             :     uint8_t name_type = decoder.consume_u8("name type");
    1907          24 :     if (name_type & 0x80) break;  // no varuint7
    1908             : 
    1909             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    1910          24 :     if (!decoder.checkAvailable(name_payload_len)) break;
    1911             : 
    1912          24 :     if (name_type != NameSectionKindCode::kLocal) {
    1913          20 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    1914          20 :       continue;
    1915             :     }
    1916             : 
    1917             :     uint32_t local_names_count = decoder.consume_u32v("local names count");
    1918           8 :     for (uint32_t i = 0; i < local_names_count; ++i) {
    1919             :       uint32_t func_index = decoder.consume_u32v("function index");
    1920           4 :       if (func_index > kMaxInt) continue;
    1921           4 :       result->names.emplace_back(static_cast<int>(func_index));
    1922             :       LocalNamesPerFunction& func_names = result->names.back();
    1923             :       result->max_function_index =
    1924           8 :           std::max(result->max_function_index, func_names.function_index);
    1925             :       uint32_t num_names = decoder.consume_u32v("namings count");
    1926          16 :       for (uint32_t k = 0; k < num_names; ++k) {
    1927             :         uint32_t local_index = decoder.consume_u32v("local index");
    1928          12 :         WireBytesRef name = consume_string(decoder, true, "local name");
    1929          12 :         if (!decoder.ok()) break;
    1930          12 :         if (local_index > kMaxInt) continue;
    1931             :         func_names.max_local_index =
    1932          24 :             std::max(func_names.max_local_index, static_cast<int>(local_index));
    1933          12 :         func_names.names.emplace_back(static_cast<int>(local_index), name);
    1934             :       }
    1935             :     }
    1936             :   }
    1937             : }
    1938             : 
    1939             : #undef TRACE
    1940             : 
    1941             : }  // namespace wasm
    1942             : }  // namespace internal
    1943      178779 : }  // namespace v8

Generated by: LCOV version 1.10