LCOV - code coverage report
Current view: top level - src/wasm - module-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 806 843 95.6 %
Date: 2019-01-20 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         738 :   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          32 : const char* SectionName(SectionCode code) {
      58          32 :   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           9 :       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       16915 : bool validate_utf8(Decoder* decoder, WireBytesRef string) {
      99             :   return unibrow::Utf8::ValidateEncoding(
     100             :       decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
     101       33830 :       string.length());
     102             : }
     103             : 
     104      446462 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
     105      446462 :   switch (expr.kind) {
     106             :     case WasmInitExpr::kNone:
     107             :       return kWasmStmt;
     108             :     case WasmInitExpr::kGlobalIndex:
     109         307 :       return expr.val.global_index < module->globals.size()
     110             :                  ? module->globals[expr.val.global_index].type
     111         614 :                  : 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      978127 : 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      978135 :   if (length > 0) {
     136      965784 :     decoder.consume_bytes(length, name);
     137     1912679 :     if (decoder.ok() && validate_utf8 &&
     138      946890 :         !unibrow::Utf8::ValidateEncoding(string_start, length)) {
     139        9722 :       decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
     140             :     }
     141             :   }
     142      978166 :   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      139775 :   explicit WasmSectionIterator(Decoder& decoder)
     150             :       : decoder_(decoder),
     151             :         section_code_(kUnknownSectionCode),
     152             :         section_start_(decoder.pc()),
     153      586379 :         section_end_(decoder.pc()) {
     154      446604 :     next();
     155             :   }
     156             : 
     157     1923313 :   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         549 :     return static_cast<uint32_t>(section_end_ - section_start_);
     165             :   }
     166             : 
     167     1435631 :   inline Vector<const uint8_t> payload() const {
     168     1435631 :     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     2868708 :     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     1475046 :   void advance(bool move_to_section_end = false) {
     182     4423464 :     if (move_to_section_end && decoder_.pc() < section_end_) {
     183             :       decoder_.consume_bytes(
     184     2946676 :           static_cast<uint32_t>(section_end_ - decoder_.pc()));
     185             :     }
     186     2950160 :     if (decoder_.pc() != section_end_) {
     187         549 :       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        1098 :                       static_cast<size_t>(decoder_.pc() - section_start_));
     193             :     }
     194     1475080 :     next();
     195     1475107 :   }
     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     1921672 :   void next() {
     207     3834058 :     if (!decoder_.more()) {
     208      309786 :       section_code_ = kUnknownSectionCode;
     209     2231486 :       return;
     210             :     }
     211     1611886 :     section_start_ = decoder_.pc();
     212             :     uint8_t section_code = decoder_.consume_u8("section code");
     213             :     // Read and check the section size.
     214     1611907 :     uint32_t section_length = decoder_.consume_u32v("section length");
     215             : 
     216     3223814 :     payload_start_ = decoder_.pc();
     217     1611907 :     if (decoder_.checkAvailable(section_length)) {
     218             :       // Get the limit of the section within the module.
     219     1486939 :       section_end_ = payload_start_ + section_length;
     220             :     } else {
     221             :       // The section would extend beyond the end of the module.
     222      124968 :       section_end_ = payload_start_;
     223             :     }
     224             : 
     225     1611907 :     if (section_code == kUnknownSectionCode) {
     226             :       // Check for the known "name" or "sourceMappingURL" section.
     227             :       section_code =
     228       37468 :           ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
     229             :       // As a side effect, the above function will forward the decoder to after
     230             :       // the identifier string.
     231       74906 :       payload_start_ = decoder_.pc();
     232     1574439 :     } else if (!IsValidSectionCode(section_code)) {
     233             :       decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
     234      248436 :                       section_code);
     235             :       section_code = kUnknownSectionCode;
     236             :     }
     237     1611914 :     section_code_ = decoder_.failed() ? kUnknownSectionCode
     238     1611914 :                                       : static_cast<SectionCode>(section_code);
     239             : 
     240     1746583 :     if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
     241             :       // skip to the end of the unknown section.
     242        8278 :       uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
     243        4139 :       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      632459 : class ModuleDecoderImpl : public Decoder {
     252             :  public:
     253             :   explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
     254             :       : Decoder(nullptr, nullptr),
     255             :         enabled_features_(enabled),
     256         778 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
     257             : 
     258      315647 :   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      631294 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
     263      315647 :     if (end_ < start_) {
     264           0 :       error(start_, "end is less than start");
     265           0 :       end_ = start_;
     266             :     }
     267      315647 :   }
     268             : 
     269       17387 :   void onFirstError() override {
     270       17387 :     pc_ = end_;  // On error, terminate section decoding loop.
     271       17387 :   }
     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      315748 :   void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
     298      315748 :     CHECK_NULL(module_);
     299             :     SetCounters(counters);
     300             :     module_.reset(
     301     1578756 :         new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
     302      315752 :     module_->initial_pages = 0;
     303      315752 :     module_->maximum_pages = 0;
     304      315752 :     module_->mem_export = false;
     305      315752 :     module_->origin = origin_;
     306      315752 :   }
     307             : 
     308      315744 :   void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
     309      631491 :     if (failed()) return;
     310      315744 :     Reset(bytes, offset);
     311             : 
     312      315729 :     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      315741 :     if (magic_word != kWasmMagic) {
     316             :       errorf(pos,
     317             :              "expected magic word %02x %02x %02x %02x, "
     318             :              "found %02x %02x %02x %02x",
     319        8112 :              BYTES(kWasmMagic), BYTES(magic_word));
     320             :     }
     321             : 
     322      315741 :     pos = pc_;
     323             :     {
     324             :       uint32_t magic_version = consume_u32("wasm version");
     325      315747 :       if (magic_version != kWasmVersion) {
     326             :         errorf(pos,
     327             :                "expected version %02x %02x %02x %02x, "
     328             :                "found %02x %02x %02x %02x",
     329        8549 :                BYTES(kWasmVersion), BYTES(magic_version));
     330             :       }
     331             :     }
     332             : #undef BYTES
     333             :   }
     334             : 
     335         474 :   bool CheckSectionOrder(SectionCode section_code,
     336             :                          SectionCode prev_section_code,
     337             :                          SectionCode next_section_code) {
     338         474 :     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         471 :     if (next_ordered_section_ <= prev_section_code) {
     344         469 :       next_ordered_section_ = prev_section_code + 1;
     345             :     }
     346             :     return true;
     347             :   }
     348             : 
     349         475 :   bool CheckUnorderedSection(SectionCode section_code) {
     350         475 :     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         474 :     return true;
     357             :   }
     358             : 
     359     1433226 :   void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
     360             :                      uint32_t offset, bool verify_functions = true) {
     361     2866419 :     if (failed()) return;
     362     1433241 :     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     1433233 :     if (section_code < next_ordered_section_ &&
     369             :         section_code < kFirstUnorderedSection) {
     370          26 :       errorf(pc(), "unexpected section: %s", SectionName(section_code));
     371          13 :       return;
     372             :     }
     373             : 
     374     1433220 :     switch (section_code) {
     375             :       case kUnknownSectionCode:
     376             :         break;
     377             :       case kDataCountSectionCode:
     378          66 :         if (!CheckUnorderedSection(section_code)) return;
     379          65 :         if (!CheckSectionOrder(section_code, kElementSectionCode,
     380          65 :                                kCodeSectionCode))
     381             :           return;
     382             :         break;
     383             :       case kExceptionSectionCode:
     384         409 :         if (!CheckUnorderedSection(section_code)) return;
     385         409 :         if (!CheckSectionOrder(section_code, kGlobalSectionCode,
     386         409 :                                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     1407962 :         next_ordered_section_ = section_code + 1;
     400     1407962 :         break;
     401             :     }
     402             : 
     403     1433171 :     switch (section_code) {
     404             :       case kUnknownSectionCode:
     405             :         break;
     406             :       case kTypeSectionCode:
     407      288533 :         DecodeTypeSection();
     408      288547 :         break;
     409             :       case kImportSectionCode:
     410      260477 :         DecodeImportSection();
     411      260480 :         break;
     412             :       case kFunctionSectionCode:
     413      286504 :         DecodeFunctionSection();
     414      286497 :         break;
     415             :       case kTableSectionCode:
     416        2539 :         DecodeTableSection();
     417        2539 :         break;
     418             :       case kMemorySectionCode:
     419       11385 :         DecodeMemorySection();
     420       11385 :         break;
     421             :       case kGlobalSectionCode:
     422        2830 :         DecodeGlobalSection();
     423        2830 :         break;
     424             :       case kExportSectionCode:
     425      262704 :         DecodeExportSection();
     426      262697 :         break;
     427             :       case kStartSectionCode:
     428        3328 :         DecodeStartSection();
     429        3328 :         break;
     430             :       case kCodeSectionCode:
     431      285792 :         DecodeCodeSection(verify_functions);
     432      285791 :         break;
     433             :       case kElementSectionCode:
     434        2159 :         DecodeElementSection();
     435        2159 :         break;
     436             :       case kDataSectionCode:
     437        1669 :         DecodeDataSection();
     438        1669 :         break;
     439             :       case kNameSectionCode:
     440       24761 :         DecodeNameSection();
     441       24756 :         break;
     442             :       case kSourceMappingURLSectionCode:
     443           9 :         DecodeSourceMappingURLSection();
     444           9 :         break;
     445             :       case kDataCountSectionCode:
     446          64 :         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         407 :         if (enabled_features_.eh) {
     454         397 :           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     1433168 :     if (pc() != bytes.end()) {
     465         148 :       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         148 :              msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
     470             :     }
     471             :   }
     472             : 
     473      288532 :   void DecodeTypeSection() {
     474      288532 :     uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
     475     3103054 :     module_->signatures.reserve(signatures_count);
     476     1840144 :     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      631515 :       FunctionSig* s = consume_sig(module_->signature_zone.get());
     480      631515 :       module_->signatures.push_back(s);
     481     1262931 :       uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
     482      631505 :       module_->signature_ids.push_back(id);
     483             :     }
     484             :     module_->signature_map.Freeze();
     485      288557 :   }
     486             : 
     487      260477 :   void DecodeImportSection() {
     488             :     uint32_t import_table_count =
     489      260477 :         consume_count("imports count", kV8MaxWasmImports);
     490     1843013 :     module_->import_table.reserve(import_table_count);
     491     1051040 :     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      795074 :       });
     501      265018 :       WasmImport* import = &module_->import_table.back();
     502      265018 :       const byte* pos = pc_;
     503      265018 :       import->module_name = consume_string(*this, true, "module name");
     504      265032 :       import->field_name = consume_string(*this, true, "field name");
     505             :       import->kind =
     506      265011 :           static_cast<ImportExportKindCode>(consume_u8("import kind"));
     507      265011 :       switch (import->kind) {
     508             :         case kExternalFunction: {
     509             :           // ===== Imported function =======================================
     510      510894 :           import->index = static_cast<uint32_t>(module_->functions.size());
     511      255447 :           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     1021788 :                                         false});        // exported
     518             :           WasmFunction* function = &module_->functions.back();
     519             :           function->sig_index =
     520      255447 :               consume_sig_index(module_.get(), &function->sig);
     521      255447 :           break;
     522             :         }
     523             :         case kExternalTable: {
     524             :           // ===== Imported table ==========================================
     525        1762 :           if (!AddTable(module_.get())) break;
     526        3488 :           import->index = static_cast<uint32_t>(module_->tables.size());
     527        1744 :           module_->tables.emplace_back();
     528             :           WasmTable* table = &module_->tables.back();
     529        1744 :           table->imported = true;
     530        1744 :           ValueType type = consume_reference_type();
     531        1744 :           if (!enabled_features_.anyref) {
     532        1738 :             if (type != kWasmAnyFunc) {
     533           0 :               error(pc_ - 1, "invalid table type");
     534           0 :               break;
     535             :             }
     536             :           }
     537        1744 :           table->type = type;
     538        1744 :           uint8_t flags = validate_table_flags("element count");
     539             :           consume_resizable_limits(
     540             :               "element count", "elements", FLAG_wasm_max_table_size,
     541             :               &table->initial_size, &table->has_maximum_size,
     542        1744 :               FLAG_wasm_max_table_size, &table->maximum_size, flags);
     543        1744 :           break;
     544             :         }
     545             :         case kExternalMemory: {
     546             :           // ===== Imported memory =========================================
     547        5355 :           if (!AddMemory(module_.get())) break;
     548        5329 :           uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     549             :           consume_resizable_limits(
     550             :               "memory", "pages", kSpecMaxWasmMemoryPages,
     551             :               &module_->initial_pages, &module_->has_maximum_pages,
     552       10654 :               kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
     553        5341 :           break;
     554             :         }
     555             :         case kExternalGlobal: {
     556             :           // ===== Imported global =========================================
     557        4672 :           import->index = static_cast<uint32_t>(module_->globals.size());
     558             :           module_->globals.push_back(
     559        9344 :               {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
     560             :           WasmGlobal* global = &module_->globals.back();
     561        2336 :           global->type = consume_value_type();
     562        2336 :           global->mutability = consume_mutability();
     563        2336 :           if (global->mutability) {
     564         327 :             module_->num_imported_mutable_globals++;
     565             :           }
     566             :           break;
     567             :         }
     568             :         case kExternalException: {
     569             :           // ===== Imported exception ======================================
     570         119 :           if (!enabled_features_.eh) {
     571           1 :             errorf(pos, "unknown import kind 0x%02x", import->kind);
     572           1 :             break;
     573             :           }
     574         236 :           import->index = static_cast<uint32_t>(module_->exceptions.size());
     575         118 :           WasmExceptionSig* exception_sig = nullptr;
     576         118 :           consume_exception_attribute();  // Attribute ignored for now.
     577         118 :           consume_exception_sig_index(module_.get(), &exception_sig);
     578         118 :           module_->exceptions.emplace_back(exception_sig);
     579         118 :           break;
     580             :         }
     581             :         default:
     582           0 :           errorf(pos, "unknown import kind 0x%02x", import->kind);
     583           0 :           break;
     584             :       }
     585             :     }
     586      260492 :   }
     587             : 
     588      572971 :   void DecodeFunctionSection() {
     589             :     uint32_t functions_count =
     590      286477 :         consume_count("functions count", kV8MaxWasmFunctions);
     591             :     auto counter =
     592      572988 :         SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
     593      286494 :     counter->AddSample(static_cast<int>(functions_count));
     594             :     DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
     595             :     uint32_t total_function_count =
     596     1435190 :         module_->num_imported_functions + functions_count;
     597      286500 :     module_->functions.reserve(total_function_count);
     598      286500 :     module_->num_declared_functions = functions_count;
     599      717552 :     for (uint32_t i = 0; i < functions_count; ++i) {
     600      862192 :       uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
     601             :       module_->functions.push_back({nullptr,     // sig
     602             :                                     func_index,  // func_index
     603             :                                     0,           // sig_index
     604             :                                     {0, 0},      // code
     605             :                                     false,       // imported
     606     1293286 :                                     false});     // exported
     607             :       WasmFunction* function = &module_->functions.back();
     608      431094 :       function->sig_index = consume_sig_index(module_.get(), &function->sig);
     609      717600 :       if (!ok()) return;
     610             :     }
     611             :     DCHECK_EQ(module_->functions.size(), total_function_count);
     612             :   }
     613             : 
     614        2539 :   void DecodeTableSection() {
     615             :     // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
     616             :     // implementation of AnyRef landed.
     617        2539 :     uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
     618        2539 :     uint32_t table_count = consume_count("table count", max_count);
     619             : 
     620       10060 :     for (uint32_t i = 0; ok() && i < table_count; i++) {
     621        5000 :       if (!AddTable(module_.get())) break;
     622        2491 :       module_->tables.emplace_back();
     623             :       WasmTable* table = &module_->tables.back();
     624        2491 :       table->type = consume_reference_type();
     625        2491 :       uint8_t flags = validate_table_flags("table elements");
     626             :       consume_resizable_limits(
     627             :           "table elements", "elements", FLAG_wasm_max_table_size,
     628             :           &table->initial_size, &table->has_maximum_size,
     629        2491 :           FLAG_wasm_max_table_size, &table->maximum_size, flags);
     630             :     }
     631        2539 :   }
     632             : 
     633       11385 :   void DecodeMemorySection() {
     634       11385 :     uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
     635             : 
     636       45338 :     for (uint32_t i = 0; ok() && i < memory_count; i++) {
     637       33942 :       if (!AddMemory(module_.get())) break;
     638       11284 :       uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
     639             :       consume_resizable_limits(
     640             :           "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
     641             :           &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
     642       22568 :           &module_->maximum_pages, flags);
     643             :     }
     644       11385 :   }
     645             : 
     646        2830 :   void DecodeGlobalSection() {
     647        2830 :     uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
     648      891246 :     uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
     649        2830 :     module_->globals.reserve(imported_globals + globals_count);
     650      888866 :     for (uint32_t i = 0; ok() && i < globals_count; ++i) {
     651             :       TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
     652             :       // Add an uninitialized global and pass a pointer to it.
     653             :       module_->globals.push_back(
     654     1766412 :           {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
     655      441603 :       WasmGlobal* global = &module_->globals.back();
     656      441603 :       DecodeGlobalInModule(module_.get(), i + imported_globals, global);
     657             :     }
     658        5210 :     if (ok()) CalculateGlobalOffsets(module_.get());
     659        2830 :   }
     660             : 
     661      262699 :   void DecodeExportSection() {
     662             :     uint32_t export_table_count =
     663      262699 :         consume_count("exports count", kV8MaxWasmExports);
     664     2102774 :     module_->export_table.reserve(export_table_count);
     665     1312496 :     for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
     666             :       TRACE("DecodeExportTable[%d] module+%d\n", i,
     667             :             static_cast<int>(pc_ - start_));
     668             : 
     669             :       module_->export_table.push_back({
     670             :           {0, 0},             // name
     671             :           kExternalFunction,  // kind
     672             :           0                   // index
     673     1180617 :       });
     674      393531 :       WasmExport* exp = &module_->export_table.back();
     675             : 
     676      394269 :       exp->name = consume_string(*this, true, "field name");
     677             : 
     678             :       const byte* pos = pc();
     679      393522 :       exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
     680      393522 :       switch (exp->kind) {
     681             :         case kExternalFunction: {
     682      389574 :           WasmFunction* func = nullptr;
     683      389578 :           exp->index = consume_func_index(module_.get(), &func);
     684      389578 :           module_->num_exported_functions++;
     685      389578 :           if (func) func->exported = true;
     686             :           break;
     687             :         }
     688             :         case kExternalTable: {
     689         747 :           WasmTable* table = nullptr;
     690         747 :           exp->index = consume_table_index(module_.get(), &table);
     691         747 :           if (table) table->exported = true;
     692             :           break;
     693             :         }
     694             :         case kExternalMemory: {
     695             :           uint32_t index = consume_u32v("memory index");
     696             :           // TODO(titzer): This should become more regular
     697             :           // once we support multiple memories.
     698        1902 :           if (!module_->has_memory || index != 0) {
     699          27 :             error("invalid memory index != 0");
     700             :           }
     701        1902 :           module_->mem_export = true;
     702        1902 :           break;
     703             :         }
     704             :         case kExternalGlobal: {
     705        1136 :           WasmGlobal* global = nullptr;
     706        1136 :           exp->index = consume_global_index(module_.get(), &global);
     707        1136 :           if (global) {
     708        1118 :             global->exported = true;
     709             :           }
     710             :           break;
     711             :         }
     712             :         case kExternalException: {
     713         163 :           if (!enabled_features_.eh) {
     714           0 :             errorf(pos, "invalid export kind 0x%02x", exp->kind);
     715           0 :             break;
     716             :           }
     717         163 :           WasmException* exception = nullptr;
     718         163 :           exp->index = consume_exception_index(module_.get(), &exception);
     719         163 :           break;
     720             :         }
     721             :         default:
     722           0 :           errorf(pos, "invalid export kind 0x%02x", exp->kind);
     723           0 :           break;
     724             :       }
     725             :     }
     726             :     // Check for duplicate exports (except for asm.js).
     727      781895 :     if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
     728        8391 :       std::vector<WasmExport> sorted_exports(module_->export_table);
     729             : 
     730      706004 :       auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
     731             :         // Return true if a < b.
     732     1771270 :         if (a.name.length() != b.name.length()) {
     733      173371 :           return a.name.length() < b.name.length();
     734             :         }
     735     1597899 :         const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
     736      532633 :         const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
     737      532633 :         return memcmp(left, right, a.name.length()) < 0;
     738        8391 :       };
     739        8391 :       std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
     740             : 
     741             :       auto it = sorted_exports.begin();
     742             :       WasmExport* last = &*it++;
     743      145062 :       for (auto end = sorted_exports.end(); it != end; last = &*it++) {
     744             :         DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
     745      128649 :         if (!cmp_less(*last, *it)) {
     746         738 :           const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
     747         369 :           TruncatedUserString<> name(pc, it->name.length());
     748             :           errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
     749             :                  name.length(), name.start(), ExternalKindName(last->kind),
     750        1107 :                  last->index, ExternalKindName(it->kind), it->index);
     751             :           break;
     752             :         }
     753             :       }
     754             :     }
     755      262705 :   }
     756             : 
     757        3328 :   void DecodeStartSection() {
     758             :     WasmFunction* func;
     759        3328 :     const byte* pos = pc_;
     760        6656 :     module_->start_function_index = consume_func_index(module_.get(), &func);
     761        9948 :     if (func &&
     762        6539 :         (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
     763          72 :       error(pos, "invalid start function: non-zero parameter or return count");
     764             :     }
     765        3328 :   }
     766             : 
     767        2159 :   void DecodeElementSection() {
     768             :     uint32_t element_count =
     769        2159 :         consume_count("element count", FLAG_wasm_max_table_size);
     770             : 
     771       20824 :     if (element_count > 0 && module_->tables.size() == 0) {
     772          55 :       error(pc_, "The element section requires a table");
     773             :     }
     774        7327 :     for (uint32_t i = 0; ok() && i < element_count; ++i) {
     775             :       const byte* pos = pc();
     776             : 
     777             :       bool is_active;
     778             :       uint32_t table_index;
     779             :       WasmInitExpr offset;
     780        2731 :       consume_segment_header("table index", &is_active, &table_index, &offset);
     781        5035 :       if (failed()) return;
     782             : 
     783        2586 :       if (is_active) {
     784        7662 :         if (table_index >= module_->tables.size()) {
     785           0 :           errorf(pos, "out of bounds table index %u", table_index);
     786           0 :           break;
     787             :         }
     788        2554 :         if (module_->tables[table_index].type != kWasmAnyFunc) {
     789             :           errorf(pos,
     790             :                  "Invalid element segment. Table %u is not of type AnyFunc",
     791           2 :                  table_index);
     792           2 :           break;
     793             :         }
     794             :       }
     795             : 
     796             :       uint32_t num_elem =
     797        2584 :           consume_count("number of elements", kV8MaxWasmTableEntries);
     798        2584 :       if (is_active) {
     799        2552 :         module_->elem_segments.emplace_back(table_index, offset);
     800             :       } else {
     801          32 :         module_->elem_segments.emplace_back();
     802             :       }
     803             : 
     804             :       WasmElemSegment* init = &module_->elem_segments.back();
     805       11371 :       for (uint32_t j = 0; j < num_elem; j++) {
     806        8806 :         WasmFunction* func = nullptr;
     807        8806 :         uint32_t index = consume_func_index(module_.get(), &func);
     808             :         DCHECK_IMPLIES(ok(), func != nullptr);
     809        8806 :         if (!ok()) break;
     810             :         DCHECK_EQ(index, func->func_index);
     811        8787 :         init->entries.push_back(index);
     812             :       }
     813             :     }
     814             :   }
     815             : 
     816      285771 :   void DecodeCodeSection(bool verify_functions) {
     817      429779 :     uint32_t pos = pc_offset();
     818      285771 :     uint32_t functions_count = consume_u32v("functions count");
     819      285785 :     CheckFunctionsCount(functions_count, pos);
     820     1431102 :     for (uint32_t i = 0; ok() && i < functions_count; ++i) {
     821             :       const byte* pos = pc();
     822             :       uint32_t size = consume_u32v("body size");
     823      429777 :       if (size > kV8MaxWasmFunctionSize) {
     824             :         errorf(pos, "size %u > maximum function size %zu", size,
     825           3 :                kV8MaxWasmFunctionSize);
     826      285786 :         return;
     827             :       }
     828             :       uint32_t offset = pc_offset();
     829      429774 :       consume_bytes(size, "function body");
     830      429776 :       if (failed()) break;
     831      429768 :       DecodeFunctionBody(i, size, offset, verify_functions);
     832             :     }
     833             :   }
     834             : 
     835      286026 :   bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
     836      286115 :     if (functions_count != module_->num_declared_functions) {
     837          89 :       Reset(nullptr, nullptr, offset);
     838             :       errorf(nullptr, "function body count %u mismatch (%u expected)",
     839          89 :              functions_count, module_->num_declared_functions);
     840          89 :       return false;
     841             :     }
     842             :     return true;
     843             :   }
     844             : 
     845      430263 :   void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
     846             :                           bool verify_functions) {
     847             :     WasmFunction* function =
     848      581996 :         &module_->functions[index + module_->num_imported_functions];
     849      430263 :     function->code = {offset, length};
     850      430263 :     if (verify_functions) {
     851      151733 :       ModuleWireBytes bytes(start_, end_);
     852             :       VerifyFunctionBody(module_->signature_zone->allocator(),
     853             :                          index + module_->num_imported_functions, bytes,
     854      303466 :                          module_.get(), function);
     855             :     }
     856      430263 :   }
     857             : 
     858      296581 :   bool CheckDataSegmentsCount(uint32_t data_segments_count) {
     859      296695 :     if (has_seen_unordered_section(kDataCountSectionCode) &&
     860         117 :         data_segments_count != module_->num_declared_data_segments) {
     861             :       errorf(pc(), "data segments count %u mismatch (%u expected)",
     862           3 :              data_segments_count, module_->num_declared_data_segments);
     863           3 :       return false;
     864             :     }
     865             :     return true;
     866             :   }
     867             : 
     868        1669 :   void DecodeDataSection() {
     869             :     uint32_t data_segments_count =
     870        1669 :         consume_count("data segments count", kV8MaxWasmDataSegments);
     871        3338 :     if (!CheckDataSegmentsCount(data_segments_count)) return;
     872             : 
     873        7738 :     module_->data_segments.reserve(data_segments_count);
     874        7268 :     for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
     875        2135 :       const byte* pos = pc();
     876        2135 :       if (!module_->has_memory) {
     877          73 :         error("cannot load data without memory");
     878          73 :         break;
     879             :       }
     880             :       TRACE("DecodeDataSegment[%d] module+%d\n", i,
     881             :             static_cast<int>(pc_ - start_));
     882             : 
     883             :       bool is_active;
     884             :       uint32_t memory_index;
     885             :       WasmInitExpr dest_addr;
     886             :       consume_segment_header("memory index", &is_active, &memory_index,
     887        2062 :                              &dest_addr);
     888        2062 :       if (failed()) break;
     889             : 
     890        1968 :       if (is_active && memory_index != 0) {
     891           0 :         errorf(pos, "illegal memory index %u != 0", memory_index);
     892           0 :         break;
     893             :       }
     894             : 
     895        1968 :       uint32_t source_length = consume_u32v("source size");
     896             :       uint32_t source_offset = pc_offset();
     897             : 
     898        1968 :       if (is_active) {
     899        1904 :         module_->data_segments.emplace_back(dest_addr);
     900             :       } else {
     901          64 :         module_->data_segments.emplace_back();
     902             :       }
     903             : 
     904             :       WasmDataSegment* segment = &module_->data_segments.back();
     905             : 
     906        1968 :       consume_bytes(source_length, "segment data");
     907        1968 :       if (failed()) break;
     908             : 
     909        1967 :       segment->source = {source_offset, source_length};
     910             :     }
     911             :   }
     912             : 
     913       24739 :   void DecodeNameSection() {
     914             :     // TODO(titzer): find a way to report name errors as warnings.
     915             :     // ignore all but the first occurrence of name section.
     916       24739 :     if (!has_seen_unordered_section(kNameSectionCode)) {
     917             :       set_seen_unordered_section(kNameSectionCode);
     918             :       // Use an inner decoder so that errors don't fail the outer decoder.
     919       24753 :       Decoder inner(start_, pc_, end_, buffer_offset_);
     920             :       // Decode all name subsections.
     921             :       // Be lenient with their order.
     922       49613 :       while (inner.ok() && inner.more()) {
     923             :         uint8_t name_type = inner.consume_u8("name type");
     924       24877 :         if (name_type & 0x80) inner.error("name type if not varuint7");
     925             : 
     926             :         uint32_t name_payload_len = inner.consume_u32v("name payload length");
     927       24880 :         if (!inner.checkAvailable(name_payload_len)) break;
     928             : 
     929             :         // Decode module name, ignore the rest.
     930             :         // Function and local names will be decoded when needed.
     931       24861 :         if (name_type == NameSectionKindCode::kModule) {
     932         149 :           WireBytesRef name = consume_string(inner, false, "module name");
     933         206 :           if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
     934             :         } else {
     935       24712 :           inner.consume_bytes(name_payload_len, "name subsection payload");
     936             :         }
     937             :       }
     938             :     }
     939             :     // Skip the whole names section in the outer decoder.
     940       24741 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     941       24762 :   }
     942             : 
     943          17 :   void DecodeSourceMappingURLSection() {
     944           9 :     Decoder inner(start_, pc_, end_, buffer_offset_);
     945           9 :     WireBytesRef url = wasm::consume_string(inner, true, "module name");
     946          17 :     if (inner.ok() &&
     947             :         !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
     948             :       const byte* url_start =
     949          14 :           inner.start() + inner.GetBufferRelativeOffset(url.offset());
     950           7 :       module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
     951          14 :                                      url.length());
     952             :       set_seen_unordered_section(kSourceMappingURLSectionCode);
     953             :     }
     954           9 :     consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
     955           9 :   }
     956             : 
     957             :   void DecodeDataCountSection() {
     958          62 :     module_->num_declared_data_segments =
     959          62 :         consume_count("data segments count", kV8MaxWasmDataSegments);
     960             :   }
     961             : 
     962         397 :   void DecodeExceptionSection() {
     963             :     uint32_t exception_count =
     964         397 :         consume_count("exception count", kV8MaxWasmExceptions);
     965        1708 :     for (uint32_t i = 0; ok() && i < exception_count; ++i) {
     966             :       TRACE("DecodeException[%d] module+%d\n", i,
     967             :             static_cast<int>(pc_ - start_));
     968         457 :       WasmExceptionSig* exception_sig = nullptr;
     969         457 :       consume_exception_attribute();  // Attribute ignored for now.
     970         457 :       consume_exception_sig_index(module_.get(), &exception_sig);
     971         457 :       module_->exceptions.emplace_back(exception_sig);
     972             :     }
     973         397 :   }
     974             : 
     975      294914 :   bool CheckMismatchedCounts() {
     976             :     // The declared vs. defined function count is normally checked when
     977             :     // decoding the code section, but we have to check it here too in case the
     978             :     // code section is absent.
     979      294914 :     if (module_->num_declared_functions != 0) {
     980             :       DCHECK_LT(module_->num_imported_functions, module_->functions.size());
     981             :       // We know that the code section has been decoded if the first
     982             :       // non-imported function has its code set.
     983      571476 :       if (!module_->functions[module_->num_imported_functions].code.is_set()) {
     984             :         errorf(pc(), "function count is %u, but code section is absent",
     985          25 :                module_->num_declared_functions);
     986          25 :         return false;
     987             :       }
     988             :     }
     989             :     // Perform a similar check for the DataCount and Data sections, where data
     990             :     // segments are declared but the Data section is absent.
     991      294911 :     if (!CheckDataSegmentsCount(
     992      589778 :             static_cast<uint32_t>(module_->data_segments.size()))) {
     993             :       return false;
     994             :     }
     995      294910 :     return true;
     996             :   }
     997             : 
     998      312098 :   ModuleResult FinishDecoding(bool verify_functions = true) {
     999      312098 :     if (ok() && CheckMismatchedCounts()) {
    1000      294910 :       CalculateGlobalOffsets(module_.get());
    1001             :     }
    1002      624224 :     ModuleResult result = toResult(std::move(module_));
    1003      584716 :     if (verify_functions && result.ok() && intermediate_error_.has_error()) {
    1004             :       // Copy error message and location.
    1005        6823 :       return ModuleResult{std::move(intermediate_error_)};
    1006             :     }
    1007      312111 :     return result;
    1008             :   }
    1009             : 
    1010             :   // Decodes an entire module.
    1011      315357 :   ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
    1012             :                             bool verify_functions = true) {
    1013      315357 :     StartDecoding(counters, allocator);
    1014             :     uint32_t offset = 0;
    1015      315363 :     Vector<const byte> orig_bytes(start(), end() - start());
    1016      315363 :     DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
    1017      315360 :     if (failed()) {
    1018       17062 :       return FinishDecoding(verify_functions);
    1019             :     }
    1020             :     // Size of the module header.
    1021             :     offset += 8;
    1022      306829 :     Decoder decoder(start_ + offset, end_, offset);
    1023             : 
    1024             :     WasmSectionIterator section_iter(decoder);
    1025             : 
    1026     3471263 :     while (ok() && section_iter.more()) {
    1027             :       // Shift the offset by the section header length
    1028     1433121 :       offset += section_iter.payload_start() - section_iter.section_start();
    1029     1433121 :       if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
    1030             :         DecodeSection(section_iter.section_code(), section_iter.payload(),
    1031     2864760 :                       offset, verify_functions);
    1032             :       }
    1033             :       // Shift the offset by the remaining section payload
    1034     2866154 :       offset += section_iter.payload_length();
    1035     1433077 :       section_iter.advance(true);
    1036             :     }
    1037             : 
    1038             :     if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
    1039             : 
    1040      306831 :     if (decoder.failed()) {
    1041       10371 :       return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
    1042             :     }
    1043             : 
    1044      606747 :     return FinishDecoding(verify_functions);
    1045             :   }
    1046             : 
    1047             :   // Decodes a single anonymous function starting at {start_}.
    1048           2 :   FunctionResult DecodeSingleFunction(Zone* zone,
    1049             :                                       const ModuleWireBytes& wire_bytes,
    1050             :                                       const WasmModule* module,
    1051           1 :                                       std::unique_ptr<WasmFunction> function) {
    1052           1 :     pc_ = start_;
    1053           1 :     function->sig = consume_sig(zone);
    1054           2 :     function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
    1055             : 
    1056           1 :     if (ok())
    1057             :       VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
    1058           1 :                          function.get());
    1059             : 
    1060           1 :     if (intermediate_error_.has_error()) {
    1061           0 :       return FunctionResult{std::move(intermediate_error_)};
    1062             :     }
    1063             : 
    1064           1 :     return FunctionResult(std::move(function));
    1065             :   }
    1066             : 
    1067             :   // Decodes a single function signature at {start}.
    1068             :   FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
    1069         262 :     pc_ = start;
    1070         262 :     FunctionSig* result = consume_sig(zone);
    1071         262 :     return ok() ? result : nullptr;
    1072             :   }
    1073             : 
    1074             :   WasmInitExpr DecodeInitExpr(const byte* start) {
    1075          22 :     pc_ = start;
    1076          22 :     return consume_init_expr(nullptr, kWasmStmt);
    1077             :   }
    1078             : 
    1079             :   const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
    1080             : 
    1081             :   Counters* GetCounters() const {
    1082             :     DCHECK_NOT_NULL(counters_);
    1083             :     return counters_;
    1084             :   }
    1085             : 
    1086             :   void SetCounters(Counters* counters) {
    1087             :     DCHECK_NULL(counters_);
    1088      315749 :     counters_ = counters;
    1089             :   }
    1090             : 
    1091             :  private:
    1092             :   const WasmFeatures enabled_features_;
    1093             :   std::shared_ptr<WasmModule> module_;
    1094             :   Counters* counters_ = nullptr;
    1095             :   // The type section is the first section in a module.
    1096             :   uint8_t next_ordered_section_ = kFirstSectionInModule;
    1097             :   // We store next_ordered_section_ as uint8_t instead of SectionCode so that we
    1098             :   // can increment it. This static_assert should make sure that SectionCode does
    1099             :   // not get bigger than uint8_t accidentially.
    1100             :   static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
    1101             :                     sizeof(SectionCode),
    1102             :                 "type mismatch");
    1103             :   uint32_t seen_unordered_sections_ = 0;
    1104             :   static_assert(kBitsPerByte *
    1105             :                         sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
    1106             :                     kLastKnownModuleSection,
    1107             :                 "not enough bits");
    1108             :   WasmError intermediate_error_;
    1109             :   ModuleOrigin origin_;
    1110             : 
    1111             :   bool has_seen_unordered_section(SectionCode section_code) {
    1112      321803 :     return seen_unordered_sections_ & (1 << section_code);
    1113             :   }
    1114             : 
    1115             :   void set_seen_unordered_section(SectionCode section_code) {
    1116       25234 :     seen_unordered_sections_ |= 1 << section_code;
    1117             :   }
    1118             : 
    1119             :   uint32_t off(const byte* ptr) {
    1120           1 :     return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
    1121             :   }
    1122             : 
    1123        4271 :   bool AddTable(WasmModule* module) {
    1124        4271 :     if (enabled_features_.anyref) return true;
    1125        8502 :     if (module->tables.size() > 0) {
    1126          36 :       error("At most one table is supported");
    1127          36 :       return false;
    1128             :     } else {
    1129             :       return true;
    1130             :     }
    1131             :   }
    1132             : 
    1133             :   bool AddMemory(WasmModule* module) {
    1134       16676 :     if (module->has_memory) {
    1135          72 :       error("At most one memory is supported");
    1136             :       return false;
    1137             :     } else {
    1138       16604 :       module->has_memory = true;
    1139             :       return true;
    1140             :     }
    1141             :   }
    1142             : 
    1143             :   // Decodes a single global entry inside a module starting at {pc_}.
    1144      441603 :   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
    1145             :                             WasmGlobal* global) {
    1146      441603 :     global->type = consume_value_type();
    1147      441603 :     global->mutability = consume_mutability();
    1148      441603 :     const byte* pos = pc();
    1149      441603 :     global->init = consume_init_expr(module, kWasmStmt);
    1150      441603 :     if (global->init.kind == WasmInitExpr::kGlobalIndex) {
    1151          73 :       uint32_t other_index = global->init.val.global_index;
    1152          73 :       if (other_index >= index) {
    1153             :         errorf(pos,
    1154             :                "invalid global index in init expression, "
    1155             :                "index %u, other_index %u",
    1156           0 :                index, other_index);
    1157         146 :       } else if (module->globals[other_index].type != global->type) {
    1158             :         errorf(pos,
    1159             :                "type mismatch in global initialization "
    1160             :                "(from global #%u), expected %s, got %s",
    1161             :                other_index, ValueTypes::TypeName(global->type),
    1162           0 :                ValueTypes::TypeName(module->globals[other_index].type));
    1163             :       }
    1164             :     } else {
    1165      441530 :       if (global->type != TypeOf(module, global->init)) {
    1166             :         errorf(pos, "type error in global initialization, expected %s, got %s",
    1167             :                ValueTypes::TypeName(global->type),
    1168         432 :                ValueTypes::TypeName(TypeOf(module, global->init)));
    1169             :       }
    1170             :     }
    1171      441603 :   }
    1172             : 
    1173             :   // Decodes a single data segment entry inside a module starting at {pc_}.
    1174             : 
    1175             :   // Calculate individual global offsets and total size of globals table.
    1176      297268 :   void CalculateGlobalOffsets(WasmModule* module) {
    1177             :     uint32_t untagged_offset = 0;
    1178             :     uint32_t tagged_offset = 0;
    1179             :     uint32_t num_imported_mutable_globals = 0;
    1180     1479687 :     for (WasmGlobal& global : module->globals) {
    1181      885151 :       if (global.mutability && global.imported) {
    1182         352 :         global.index = num_imported_mutable_globals++;
    1183      884799 :       } else if (global.type == ValueType::kWasmAnyRef) {
    1184         312 :         global.offset = tagged_offset;
    1185             :         // All entries in the tagged_globals_buffer have size 1.
    1186         312 :         tagged_offset++;
    1187             :       } else {
    1188             :         byte size =
    1189      884487 :             ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
    1190      884487 :         untagged_offset = (untagged_offset + size - 1) & ~(size - 1);  // align
    1191      884487 :         global.offset = untagged_offset;
    1192      884487 :         untagged_offset += size;
    1193             :       }
    1194             :     }
    1195      297268 :     module->untagged_globals_buffer_size = untagged_offset;
    1196      297268 :     module->tagged_globals_buffer_size = tagged_offset;
    1197      297268 :   }
    1198             : 
    1199             :   // Verifies the body (code) of a given function.
    1200      151734 :   void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
    1201             :                           const ModuleWireBytes& wire_bytes,
    1202      151734 :                           const WasmModule* module, WasmFunction* function) {
    1203             :     WasmFunctionName func_name(function,
    1204      151734 :                                wire_bytes.GetNameOrNull(function, module));
    1205             :     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
    1206             :       StdoutStream os;
    1207             :       os << "Verifying wasm function " << func_name << std::endl;
    1208             :     }
    1209             :     FunctionBody body = {
    1210             :         function->sig, function->code.offset(),
    1211             :         start_ + GetBufferRelativeOffset(function->code.offset()),
    1212      606936 :         start_ + GetBufferRelativeOffset(function->code.end_offset())};
    1213             : 
    1214             :     DecodeResult result;
    1215             :     {
    1216      303468 :       auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
    1217             :                                               wasm_decode, function_time);
    1218             : 
    1219             :       TimedHistogramScope wasm_decode_function_time_scope(time_counter);
    1220      151734 :       WasmFeatures unused_detected_features;
    1221      303468 :       result = VerifyWasmCode(allocator, enabled_features_, module,
    1222             :                               &unused_detected_features, body);
    1223             :     }
    1224             : 
    1225             :     // If the decode failed and this is the first error, set error code and
    1226             :     // location.
    1227      158593 :     if (result.failed() && intermediate_error_.empty()) {
    1228             :       // Wrap the error message from the function decoder.
    1229        6859 :       std::ostringstream error_msg;
    1230        6859 :       error_msg << "in function " << func_name << ": "
    1231             :                 << result.error().message();
    1232       20577 :       intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
    1233             :     }
    1234      151734 :   }
    1235             : 
    1236      687115 :   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
    1237      687115 :     const byte* pos = pc_;
    1238      687115 :     uint32_t sig_index = consume_u32v("signature index");
    1239     1374238 :     if (sig_index >= module->signatures.size()) {
    1240             :       errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
    1241        6457 :              static_cast<int>(module->signatures.size()));
    1242        6457 :       *sig = nullptr;
    1243        6457 :       return 0;
    1244             :     }
    1245      680662 :     *sig = module->signatures[sig_index];
    1246      680662 :     return sig_index;
    1247             :   }
    1248             : 
    1249         575 :   uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
    1250         575 :     const byte* pos = pc_;
    1251         575 :     uint32_t sig_index = consume_sig_index(module, sig);
    1252         575 :     if (*sig && (*sig)->return_count() != 0) {
    1253           2 :       errorf(pos, "exception signature %u has non-void return", sig_index);
    1254           2 :       *sig = nullptr;
    1255           2 :       return 0;
    1256             :     }
    1257             :     return sig_index;
    1258             :   }
    1259             : 
    1260     2385111 :   uint32_t consume_count(const char* name, size_t maximum) {
    1261     2385111 :     const byte* p = pc_;
    1262     2385111 :     uint32_t count = consume_u32v(name);
    1263     2385160 :     if (count > maximum) {
    1264         132 :       errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
    1265         132 :       return static_cast<uint32_t>(maximum);
    1266             :     }
    1267             :     return count;
    1268             :   }
    1269             : 
    1270             :   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
    1271      401708 :     return consume_index("function index", module->functions, func);
    1272             :   }
    1273             : 
    1274             :   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
    1275        1136 :     return consume_index("global index", module->globals, global);
    1276             :   }
    1277             : 
    1278             :   uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
    1279         747 :     return consume_index("table index", module->tables, table);
    1280             :   }
    1281             : 
    1282             :   uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
    1283         163 :     return consume_index("exception index", module->exceptions, except);
    1284             :   }
    1285             : 
    1286             :   template <typename T>
    1287      807506 :   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
    1288      403753 :     const byte* pos = pc_;
    1289      403753 :     uint32_t index = consume_u32v(name);
    1290      807506 :     if (index >= vector.size()) {
    1291         120 :       errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
    1292             :              static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
    1293         120 :       *ptr = nullptr;
    1294         120 :       return 0;
    1295             :     }
    1296      403633 :     *ptr = &vector[index];
    1297      403633 :     return index;
    1298             :   }
    1299             : 
    1300        4235 :   uint8_t validate_table_flags(const char* name) {
    1301        8470 :     uint8_t flags = consume_u8("resizable limits flags");
    1302             :     const byte* pos = pc();
    1303        4235 :     if (flags & 0xFE) {
    1304           9 :       errorf(pos - 1, "invalid %s limits flags", name);
    1305             :     }
    1306        4235 :     return flags;
    1307             :   }
    1308             : 
    1309       16602 :   uint8_t validate_memory_flags(bool* has_shared_memory) {
    1310       33213 :     uint8_t flags = consume_u8("resizable limits flags");
    1311             :     const byte* pos = pc();
    1312       16611 :     *has_shared_memory = false;
    1313       16611 :     if (enabled_features_.threads) {
    1314        1461 :       if (flags & 0xFC) {
    1315           0 :         errorf(pos - 1, "invalid memory limits flags");
    1316        1461 :       } else if (flags == 3) {
    1317             :         DCHECK_NOT_NULL(has_shared_memory);
    1318        1369 :         *has_shared_memory = true;
    1319          92 :       } else if (flags == 2) {
    1320             :         errorf(pos - 1,
    1321             :                "memory limits flags should have maximum defined if shared is "
    1322           9 :                "true");
    1323             :       }
    1324             :     } else {
    1325       15150 :       if (flags & 0xFE) {
    1326          18 :         errorf(pos - 1, "invalid memory limits flags");
    1327             :       }
    1328             :     }
    1329       16611 :     return flags;
    1330             :   }
    1331             : 
    1332       20837 :   void consume_resizable_limits(const char* name, const char* units,
    1333             :                                 uint32_t max_initial, uint32_t* initial,
    1334             :                                 bool* has_max, uint32_t max_maximum,
    1335             :                                 uint32_t* maximum, uint8_t flags) {
    1336       27081 :     const byte* pos = pc();
    1337       41689 :     *initial = consume_u32v("initial size");
    1338       20852 :     *has_max = false;
    1339       20852 :     if (*initial > max_initial) {
    1340             :       errorf(pos,
    1341             :              "initial %s size (%u %s) is larger than implementation limit (%u)",
    1342          54 :              name, *initial, units, max_initial);
    1343             :     }
    1344       20860 :     if (flags & 1) {
    1345        6244 :       *has_max = true;
    1346             :       pos = pc();
    1347        6245 :       *maximum = consume_u32v("maximum size");
    1348        6245 :       if (*maximum > max_maximum) {
    1349             :         errorf(
    1350             :             pos,
    1351             :             "maximum %s size (%u %s) is larger than implementation limit (%u)",
    1352          55 :             name, *maximum, units, max_maximum);
    1353             :       }
    1354        6245 :       if (*maximum < *initial) {
    1355             :         errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
    1356          18 :                name, *maximum, units, *initial, units);
    1357             :       }
    1358             :     } else {
    1359       14616 :       *has_max = false;
    1360       14616 :       *maximum = max_initial;
    1361             :     }
    1362       20861 :   }
    1363             : 
    1364     1078092 :   bool expect_u8(const char* name, uint8_t expected) {
    1365     1078092 :     const byte* pos = pc();
    1366     1078092 :     uint8_t value = consume_u8(name);
    1367     1078094 :     if (value != expected) {
    1368         748 :       errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
    1369         748 :       return false;
    1370             :     }
    1371             :     return true;
    1372             :   }
    1373             : 
    1374      446320 :   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
    1375      892313 :     const byte* pos = pc();
    1376      446320 :     uint8_t opcode = consume_u8("opcode");
    1377             :     WasmInitExpr expr;
    1378             :     uint32_t len = 0;
    1379      446320 :     switch (opcode) {
    1380             :       case kExprGetGlobal: {
    1381         418 :         GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
    1382         836 :         if (module->globals.size() <= imm.index) {
    1383          18 :           error("global index is out of bounds");
    1384          18 :           expr.kind = WasmInitExpr::kNone;
    1385          18 :           expr.val.i32_const = 0;
    1386          18 :           break;
    1387             :         }
    1388             :         WasmGlobal* global = &module->globals[imm.index];
    1389         400 :         if (global->mutability || !global->imported) {
    1390             :           error(
    1391             :               "only immutable imported globals can be used in initializer "
    1392          20 :               "expressions");
    1393          20 :           expr.kind = WasmInitExpr::kNone;
    1394          20 :           expr.val.i32_const = 0;
    1395          20 :           break;
    1396             :         }
    1397         380 :         expr.kind = WasmInitExpr::kGlobalIndex;
    1398         380 :         expr.val.global_index = imm.index;
    1399         380 :         len = imm.length;
    1400         380 :         break;
    1401             :       }
    1402             :       case kExprI32Const: {
    1403             :         ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1404        8455 :         expr.kind = WasmInitExpr::kI32Const;
    1405        8455 :         expr.val.i32_const = imm.value;
    1406        8455 :         len = imm.length;
    1407             :         break;
    1408             :       }
    1409             :       case kExprF32Const: {
    1410      436080 :         ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1411      436080 :         expr.kind = WasmInitExpr::kF32Const;
    1412      436080 :         expr.val.f32_const = imm.value;
    1413      436080 :         len = imm.length;
    1414             :         break;
    1415             :       }
    1416             :       case kExprI64Const: {
    1417             :         ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1418         355 :         expr.kind = WasmInitExpr::kI64Const;
    1419         355 :         expr.val.i64_const = imm.value;
    1420         355 :         len = imm.length;
    1421             :         break;
    1422             :       }
    1423             :       case kExprF64Const: {
    1424         685 :         ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
    1425         685 :         expr.kind = WasmInitExpr::kF64Const;
    1426         685 :         expr.val.f64_const = imm.value;
    1427         685 :         len = imm.length;
    1428             :         break;
    1429             :       }
    1430             :       case kExprRefNull: {
    1431         128 :         if (enabled_features_.anyref) {
    1432         128 :           expr.kind = WasmInitExpr::kAnyRefConst;
    1433             :           len = 0;
    1434         128 :           break;
    1435             :         }
    1436             :         V8_FALLTHROUGH;
    1437             :       }
    1438             :       default: {
    1439         199 :         error("invalid opcode in initialization expression");
    1440         199 :         expr.kind = WasmInitExpr::kNone;
    1441         199 :         expr.val.i32_const = 0;
    1442             :       }
    1443             :     }
    1444      446320 :     consume_bytes(len, "init code");
    1445      446320 :     if (!expect_u8("end opcode", kExprEnd)) {
    1446         619 :       expr.kind = WasmInitExpr::kNone;
    1447             :     }
    1448      446320 :     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
    1449             :       errorf(pos, "type error in init expression, expected %s, got %s",
    1450             :              ValueTypes::TypeName(expected),
    1451         237 :              ValueTypes::TypeName(TypeOf(module, expr)));
    1452             :     }
    1453      446320 :     return expr;
    1454             :   }
    1455             : 
    1456             :   // Read a mutability flag
    1457      443939 :   bool consume_mutability() {
    1458      443939 :     byte val = consume_u8("mutability");
    1459      443939 :     if (val > 1) error(pc_ - 1, "invalid mutability");
    1460      443939 :     return val != 0;
    1461             :   }
    1462             : 
    1463             :   // Reads a single 8-bit integer, interpreting it as a local type.
    1464     1428839 :   ValueType consume_value_type() {
    1465     1428839 :     byte val = consume_u8("value type");
    1466             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1467     1428853 :     switch (t) {
    1468             :       case kLocalI32:
    1469             :         return kWasmI32;
    1470             :       case kLocalI64:
    1471       38086 :         return kWasmI64;
    1472             :       case kLocalF32:
    1473      740494 :         return kWasmF32;
    1474             :       case kLocalF64:
    1475      312258 :         return kWasmF64;
    1476             :       default:
    1477         930 :         if (origin_ == kWasmOrigin) {
    1478         930 :           switch (t) {
    1479             :             case kLocalS128:
    1480          36 :               if (enabled_features_.simd) return kWasmS128;
    1481             :               break;
    1482             :             case kLocalAnyFunc:
    1483          80 :               if (enabled_features_.anyref) return kWasmAnyFunc;
    1484             :               break;
    1485             :             case kLocalAnyRef:
    1486         785 :               if (enabled_features_.anyref) return kWasmAnyRef;
    1487             :               break;
    1488             :             default:
    1489             :               break;
    1490             :           }
    1491             :         }
    1492          53 :         error(pc_ - 1, "invalid local type");
    1493          53 :         return kWasmStmt;
    1494             :     }
    1495             :   }
    1496             : 
    1497             :   // Reads a single 8-bit integer, interpreting it as a reference type.
    1498        4235 :   ValueType consume_reference_type() {
    1499        4235 :     byte val = consume_u8("reference type");
    1500             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1501        4235 :     switch (t) {
    1502             :       case kLocalAnyFunc:
    1503             :         return kWasmAnyFunc;
    1504             :       case kLocalAnyRef:
    1505           3 :         if (!enabled_features_.anyref) {
    1506             :           error(pc_ - 1,
    1507           0 :                 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
    1508             :         }
    1509             :         return kWasmAnyRef;
    1510             :       default:
    1511             :         break;
    1512             :     }
    1513           2 :     error(pc_ - 1, "invalid reference type");
    1514           2 :     return kWasmStmt;
    1515             :   }
    1516             : 
    1517      631773 :   FunctionSig* consume_sig(Zone* zone) {
    1518      631773 :     if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
    1519             :     // parse parameter types
    1520             :     uint32_t param_count =
    1521      631644 :         consume_count("param count", kV8MaxWasmFunctionParams);
    1522      631641 :     if (failed()) return nullptr;
    1523             :     std::vector<ValueType> params;
    1524     2521396 :     for (uint32_t i = 0; ok() && i < param_count; ++i) {
    1525      629050 :       ValueType param = consume_value_type();
    1526      629059 :       params.push_back(param);
    1527             :     }
    1528             :     std::vector<ValueType> returns;
    1529             :     // parse return types
    1530             :     const size_t max_return_count = enabled_features_.mv
    1531             :                                         ? kV8MaxWasmFunctionMultiReturns
    1532      631648 :                                         : kV8MaxWasmFunctionReturns;
    1533      631648 :     uint32_t return_count = consume_count("return count", max_return_count);
    1534      631649 :     if (failed()) return nullptr;
    1535     1343267 :     for (uint32_t i = 0; ok() && i < return_count; ++i) {
    1536      355853 :       ValueType ret = consume_value_type();
    1537      355858 :       returns.push_back(ret);
    1538             :     }
    1539             : 
    1540      631552 :     if (failed()) return nullptr;
    1541             : 
    1542             :     // FunctionSig stores the return types first.
    1543      631538 :     ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
    1544             :     uint32_t b = 0;
    1545      987387 :     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
    1546     1258040 :     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
    1547             : 
    1548     1263074 :     return new (zone) FunctionSig(return_count, param_count, buffer);
    1549             :   }
    1550             : 
    1551             :   // Consume the attribute field of an exception.
    1552         575 :   uint32_t consume_exception_attribute() {
    1553         575 :     const byte* pos = pc_;
    1554         575 :     uint32_t attribute = consume_u32v("exception attribute");
    1555         575 :     if (attribute != kExceptionAttribute) {
    1556           1 :       errorf(pos, "exception attribute %u not supported", attribute);
    1557           1 :       return 0;
    1558             :     }
    1559             :     return attribute;
    1560             :   }
    1561             : 
    1562        4793 :   void consume_segment_header(const char* name, bool* is_active,
    1563             :                               uint32_t* index, WasmInitExpr* offset) {
    1564        4793 :     const byte* pos = pc();
    1565             :     // In the MVP, this is a table or memory index field that must be 0, but
    1566             :     // we've repurposed it as a flags field in the bulk memory proposal.
    1567             :     uint32_t flags;
    1568        4793 :     if (enabled_features_.bulk_memory) {
    1569         176 :       flags = consume_u32v("flags");
    1570         176 :       if (failed()) return;
    1571             :     } else {
    1572        4617 :       flags = consume_u32v(name);
    1573        4617 :       if (failed()) return;
    1574             : 
    1575        4617 :       if (flags != 0) {
    1576           2 :         errorf(pos, "illegal %s %u != 0", name, flags);
    1577           2 :         return;
    1578             :       }
    1579             :     }
    1580             : 
    1581             :     bool read_index;
    1582             :     bool read_offset;
    1583        4791 :     if (flags == SegmentFlags::kActiveNoIndex) {
    1584        4686 :       *is_active = true;
    1585             :       read_index = false;
    1586             :       read_offset = true;
    1587         105 :     } else if (flags == SegmentFlags::kPassive) {
    1588          96 :       *is_active = false;
    1589             :       read_index = false;
    1590             :       read_offset = false;
    1591           9 :     } else if (flags == SegmentFlags::kActiveWithIndex) {
    1592           9 :       *is_active = true;
    1593             :       read_index = true;
    1594             :       read_offset = true;
    1595             :     } else {
    1596           0 :       errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
    1597           0 :       return;
    1598             :     }
    1599             : 
    1600        4791 :     if (read_index) {
    1601          18 :       *index = consume_u32v(name);
    1602             :     } else {
    1603        4782 :       *index = 0;
    1604             :     }
    1605             : 
    1606        4791 :     if (read_offset) {
    1607        4695 :       *offset = consume_init_expr(module_.get(), kWasmI32);
    1608             :     }
    1609             :   }
    1610             : };
    1611             : 
    1612      315340 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
    1613             :                               const byte* module_start, const byte* module_end,
    1614             :                               bool verify_functions, ModuleOrigin origin,
    1615             :                               Counters* counters,
    1616             :                               AccountingAllocator* allocator) {
    1617             :   auto counter =
    1618      315340 :       SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
    1619             :   TimedHistogramScope wasm_decode_module_time_scope(counter);
    1620      315358 :   size_t size = module_end - module_start;
    1621      315358 :   CHECK_LE(module_start, module_end);
    1622      315358 :   if (size >= kV8MaxWasmModuleSize) {
    1623             :     return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
    1624           0 :                                   kV8MaxWasmModuleSize, size}};
    1625             :   }
    1626             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1627             :   auto size_counter =
    1628      315358 :       SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
    1629      315358 :   size_counter->AddSample(static_cast<int>(size));
    1630             :   // Signatures are stored in zone memory, which have the same lifetime
    1631             :   // as the {module}.
    1632      630723 :   ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
    1633             :   ModuleResult result =
    1634      946086 :       decoder.DecodeModule(counters, allocator, verify_functions);
    1635             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1636             :   // TODO(titzer): this isn't accurate, since it doesn't count the data
    1637             :   // allocated on the C++ heap.
    1638             :   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
    1639      315360 :   if (result.ok()) {
    1640      287928 :     auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
    1641             :                                             module_peak_memory_bytes);
    1642             :     peak_counter->AddSample(
    1643      575856 :         static_cast<int>(result.value()->signature_zone->allocation_size()));
    1644             :   }
    1645             :   return result;
    1646             : }
    1647             : 
    1648         424 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
    1649         424 :     : enabled_features_(enabled) {}
    1650             : 
    1651             : ModuleDecoder::~ModuleDecoder() = default;
    1652             : 
    1653         732 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
    1654         732 :   return impl_->shared_module();
    1655             : }
    1656             : 
    1657         389 : void ModuleDecoder::StartDecoding(Counters* counters,
    1658             :                                   AccountingAllocator* allocator,
    1659             :                                   ModuleOrigin origin) {
    1660             :   DCHECK_NULL(impl_);
    1661         389 :   impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
    1662         389 :   impl_->StartDecoding(counters, allocator);
    1663         389 : }
    1664             : 
    1665         389 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
    1666             :                                        uint32_t offset) {
    1667         778 :   impl_->DecodeModuleHeader(bytes, offset);
    1668         389 : }
    1669             : 
    1670         860 : void ModuleDecoder::DecodeSection(SectionCode section_code,
    1671             :                                   Vector<const uint8_t> bytes, uint32_t offset,
    1672             :                                   bool verify_functions) {
    1673        1720 :   impl_->DecodeSection(section_code, bytes, offset, verify_functions);
    1674         860 : }
    1675             : 
    1676         503 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
    1677             :                                        uint32_t offset, bool verify_functions) {
    1678        1006 :   impl_->DecodeFunctionBody(index, length, offset, verify_functions);
    1679         503 : }
    1680             : 
    1681         243 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
    1682             :                                         uint32_t offset) {
    1683         243 :   return impl_->CheckFunctionsCount(functions_count, offset);
    1684             : }
    1685             : 
    1686         214 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
    1687         642 :   return impl_->FinishDecoding(verify_functions);
    1688             : }
    1689             : 
    1690      126038 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
    1691             :                                                   const byte* end) {
    1692       37514 :   WireBytesRef string = consume_string(decoder, true, "section name");
    1693       67417 :   if (decoder.failed() || decoder.pc() > end) {
    1694             :     return kUnknownSectionCode;
    1695             :   }
    1696             :   const byte* section_name_start =
    1697       58634 :       decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
    1698             : 
    1699             :   TRACE("  +%d  section name        : \"%.*s\"\n",
    1700             :         static_cast<int>(section_name_start - decoder.start()),
    1701             :         string.length() < 20 ? string.length() : 20, section_name_start);
    1702             : 
    1703       57373 :   if (string.length() == num_chars(kNameString) &&
    1704             :       strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
    1705       28056 :               num_chars(kNameString)) == 0) {
    1706             :     return kNameSectionCode;
    1707        1478 :   } else if (string.length() == num_chars(kSourceMappingURLString) &&
    1708             :              strncmp(reinterpret_cast<const char*>(section_name_start),
    1709             :                      kSourceMappingURLString,
    1710         163 :                      num_chars(kSourceMappingURLString)) == 0) {
    1711             :     return kSourceMappingURLSectionCode;
    1712             :   }
    1713        1296 :   return kUnknownSectionCode;
    1714             : }
    1715             : 
    1716        2498 : bool ModuleDecoder::ok() { return impl_->ok(); }
    1717             : 
    1718         262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
    1719             :                                            Zone* zone, const byte* start,
    1720             :                                            const byte* end) {
    1721         262 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1722         262 :   return decoder.DecodeFunctionSignature(zone, start);
    1723             : }
    1724             : 
    1725          22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
    1726             :                                           const byte* start, const byte* end) {
    1727          22 :   AccountingAllocator allocator;
    1728          44 :   ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
    1729          22 :   return decoder.DecodeInitExpr(start);
    1730             : }
    1731             : 
    1732           1 : FunctionResult DecodeWasmFunctionForTesting(
    1733             :     const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
    1734             :     const WasmModule* module, const byte* function_start,
    1735             :     const byte* function_end, Counters* counters) {
    1736           1 :   size_t size = function_end - function_start;
    1737           1 :   CHECK_LE(function_start, function_end);
    1738           1 :   auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
    1739             :                                             function_size_bytes);
    1740             :   // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
    1741           1 :   size_histogram->AddSample(static_cast<int>(size));
    1742           1 :   if (size > kV8MaxWasmFunctionSize) {
    1743             :     return FunctionResult{WasmError{0,
    1744             :                                     "size > maximum function size (%zu): %zu",
    1745           0 :                                     kV8MaxWasmFunctionSize, size}};
    1746             :   }
    1747           1 :   ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
    1748             :   decoder.SetCounters(counters);
    1749             :   return decoder.DecodeSingleFunction(zone, wire_bytes, module,
    1750           3 :                                       base::make_unique<WasmFunction>());
    1751             : }
    1752             : 
    1753         159 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
    1754             :                                       const byte* tables_end) {
    1755             :   AsmJsOffsets table;
    1756             : 
    1757             :   Decoder decoder(tables_start, tables_end);
    1758             :   uint32_t functions_count = decoder.consume_u32v("functions count");
    1759             :   // Reserve space for the entries, taking care of invalid input.
    1760         159 :   if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
    1761         159 :     table.reserve(functions_count);
    1762             :   }
    1763             : 
    1764         756 :   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
    1765             :     uint32_t size = decoder.consume_u32v("table size");
    1766         378 :     if (size == 0) {
    1767         159 :       table.emplace_back();
    1768         159 :       continue;
    1769             :     }
    1770         219 :     if (!decoder.checkAvailable(size)) {
    1771           0 :       decoder.error("illegal asm function offset table size");
    1772             :     }
    1773         219 :     const byte* table_end = decoder.pc() + size;
    1774             :     uint32_t locals_size = decoder.consume_u32v("locals size");
    1775         219 :     int function_start_position = decoder.consume_u32v("function start pos");
    1776         219 :     int last_byte_offset = locals_size;
    1777             :     int last_asm_position = function_start_position;
    1778             :     std::vector<AsmJsOffsetEntry> func_asm_offsets;
    1779         219 :     func_asm_offsets.reserve(size / 4);  // conservative estimation
    1780             :     // Add an entry for the stack check, associated with position 0.
    1781             :     func_asm_offsets.push_back(
    1782         438 :         {0, function_start_position, function_start_position});
    1783         729 :     while (decoder.ok() && decoder.pc() < table_end) {
    1784         291 :       last_byte_offset += decoder.consume_u32v("byte offset delta");
    1785             :       int call_position =
    1786         291 :           last_asm_position + decoder.consume_i32v("call position delta");
    1787             :       int to_number_position =
    1788         291 :           call_position + decoder.consume_i32v("to_number position delta");
    1789             :       last_asm_position = to_number_position;
    1790             :       func_asm_offsets.push_back(
    1791         582 :           {last_byte_offset, call_position, to_number_position});
    1792             :     }
    1793         219 :     if (decoder.pc() != table_end) {
    1794           0 :       decoder.error("broken asm offset table");
    1795             :     }
    1796             :     table.push_back(std::move(func_asm_offsets));
    1797             :   }
    1798         159 :   if (decoder.more()) decoder.error("unexpected additional bytes");
    1799             : 
    1800         477 :   return decoder.toResult(std::move(table));
    1801             : }
    1802             : 
    1803          56 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
    1804             :                                                       const byte* end) {
    1805             :   Decoder decoder(start, end);
    1806          56 :   decoder.consume_bytes(4, "wasm magic");
    1807          56 :   decoder.consume_bytes(4, "wasm version");
    1808             : 
    1809             :   std::vector<CustomSectionOffset> result;
    1810             : 
    1811         207 :   while (decoder.more()) {
    1812             :     byte section_code = decoder.consume_u8("section code");
    1813             :     uint32_t section_length = decoder.consume_u32v("section length");
    1814             :     uint32_t section_start = decoder.pc_offset();
    1815         160 :     if (section_code != 0) {
    1816             :       // Skip known sections.
    1817           2 :       decoder.consume_bytes(section_length, "section bytes");
    1818           2 :       continue;
    1819             :     }
    1820             :     uint32_t name_length = decoder.consume_u32v("name length");
    1821             :     uint32_t name_offset = decoder.pc_offset();
    1822         158 :     decoder.consume_bytes(name_length, "section name");
    1823             :     uint32_t payload_offset = decoder.pc_offset();
    1824         158 :     if (section_length < (payload_offset - section_start)) {
    1825           9 :       decoder.error("invalid section length");
    1826           9 :       break;
    1827             :     }
    1828         149 :     uint32_t payload_length = section_length - (payload_offset - section_start);
    1829         149 :     decoder.consume_bytes(payload_length);
    1830         149 :     if (decoder.failed()) break;
    1831             :     result.push_back({{section_start, section_length},
    1832             :                       {name_offset, name_length},
    1833         149 :                       {payload_offset, payload_length}});
    1834             :   }
    1835             : 
    1836          56 :   return result;
    1837             : }
    1838             : 
    1839             : namespace {
    1840             : 
    1841      139775 : bool FindNameSection(Decoder& decoder) {
    1842             :   static constexpr int kModuleHeaderSize = 8;
    1843      139775 :   decoder.consume_bytes(kModuleHeaderSize, "module header");
    1844             : 
    1845             :   WasmSectionIterator section_iter(decoder);
    1846             : 
    1847      279205 :   while (decoder.ok() && section_iter.more() &&
    1848       45227 :          section_iter.section_code() != kNameSectionCode) {
    1849       41976 :     section_iter.advance(true);
    1850             :   }
    1851      279550 :   if (!section_iter.more()) return false;
    1852             : 
    1853             :   // Reset the decoder to not read beyond the name section end.
    1854             :   decoder.Reset(section_iter.payload(), decoder.pc_offset());
    1855        3251 :   return true;
    1856             : }
    1857             : 
    1858             : }  // namespace
    1859             : 
    1860      139750 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
    1861             :                          std::unordered_map<uint32_t, WireBytesRef>* names) {
    1862             :   DCHECK_NOT_NULL(names);
    1863             :   DCHECK(names->empty());
    1864             : 
    1865             :   Decoder decoder(module_start, module_end);
    1866      279500 :   if (!FindNameSection(decoder)) return;
    1867             : 
    1868        6467 :   while (decoder.ok() && decoder.more()) {
    1869             :     uint8_t name_type = decoder.consume_u8("name type");
    1870        3241 :     if (name_type & 0x80) break;  // no varuint7
    1871             : 
    1872             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    1873        3241 :     if (!decoder.checkAvailable(name_payload_len)) break;
    1874             : 
    1875        3241 :     if (name_type != NameSectionKindCode::kFunction) {
    1876          25 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    1877          25 :       continue;
    1878             :     }
    1879             :     uint32_t functions_count = decoder.consume_u32v("functions count");
    1880             : 
    1881       40148 :     for (; decoder.ok() && functions_count > 0; --functions_count) {
    1882             :       uint32_t function_index = decoder.consume_u32v("function index");
    1883       16858 :       WireBytesRef name = consume_string(decoder, false, "function name");
    1884             : 
    1885             :       // Be lenient with errors in the name section: Ignore non-UTF8 names. You
    1886             :       // can even assign to the same function multiple times (last valid one
    1887             :       // wins).
    1888       33716 :       if (decoder.ok() && validate_utf8(&decoder, name)) {
    1889       33698 :         names->insert(std::make_pair(function_index, name));
    1890             :       }
    1891             :     }
    1892             :   }
    1893             : }
    1894             : 
    1895          25 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
    1896             :                       LocalNames* result) {
    1897             :   DCHECK_NOT_NULL(result);
    1898             :   DCHECK(result->names.empty());
    1899             : 
    1900             :   Decoder decoder(module_start, module_end);
    1901          50 :   if (!FindNameSection(decoder)) return;
    1902             : 
    1903          55 :   while (decoder.ok() && decoder.more()) {
    1904             :     uint8_t name_type = decoder.consume_u8("name type");
    1905          30 :     if (name_type & 0x80) break;  // no varuint7
    1906             : 
    1907             :     uint32_t name_payload_len = decoder.consume_u32v("name payload length");
    1908          30 :     if (!decoder.checkAvailable(name_payload_len)) break;
    1909             : 
    1910          30 :     if (name_type != NameSectionKindCode::kLocal) {
    1911          25 :       decoder.consume_bytes(name_payload_len, "name subsection payload");
    1912          25 :       continue;
    1913             :     }
    1914             : 
    1915             :     uint32_t local_names_count = decoder.consume_u32v("local names count");
    1916          10 :     for (uint32_t i = 0; i < local_names_count; ++i) {
    1917             :       uint32_t func_index = decoder.consume_u32v("function index");
    1918           5 :       if (func_index > kMaxInt) continue;
    1919           5 :       result->names.emplace_back(static_cast<int>(func_index));
    1920             :       LocalNamesPerFunction& func_names = result->names.back();
    1921             :       result->max_function_index =
    1922          10 :           std::max(result->max_function_index, func_names.function_index);
    1923             :       uint32_t num_names = decoder.consume_u32v("namings count");
    1924          20 :       for (uint32_t k = 0; k < num_names; ++k) {
    1925             :         uint32_t local_index = decoder.consume_u32v("local index");
    1926          15 :         WireBytesRef name = consume_string(decoder, true, "local name");
    1927          15 :         if (!decoder.ok()) break;
    1928          15 :         if (local_index > kMaxInt) continue;
    1929             :         func_names.max_local_index =
    1930          30 :             std::max(func_names.max_local_index, static_cast<int>(local_index));
    1931          15 :         func_names.names.emplace_back(static_cast<int>(local_index), name);
    1932             :       }
    1933             :     }
    1934             :   }
    1935             : }
    1936             : 
    1937             : #undef TRACE
    1938             : 
    1939             : }  // namespace wasm
    1940             : }  // namespace internal
    1941      183867 : }  // namespace v8

Generated by: LCOV version 1.10