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/platform/wrappers.h"
10#include "src/flags/flags.h"
11#include "src/init/v8.h"
12#include "src/logging/counters.h"
13#include "src/logging/metrics.h"
14#include "src/objects/objects-inl.h"
15#include "src/utils/ostreams.h"
16#include "src/wasm/canonical-types.h"
17#include "src/wasm/decoder.h"
18#include "src/wasm/function-body-decoder-impl.h"
19#include "src/wasm/init-expr-interface.h"
20#include "src/wasm/struct-types.h"
21#include "src/wasm/wasm-constants.h"
22#include "src/wasm/wasm-engine.h"
23#include "src/wasm/wasm-limits.h"
24#include "src/wasm/wasm-opcodes-inl.h"
25
26namespace v8 {
27namespace internal {
28namespace wasm {
29
30#define TRACE(...)                                    \
31  do {                                                \
32    if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
33  } while (false)
34
35namespace {
36
37constexpr char kNameString[] = "name";
38constexpr char kSourceMappingURLString[] = "sourceMappingURL";
39constexpr char kCompilationHintsString[] = "compilationHints";
40constexpr char kBranchHintsString[] = "metadata.code.branch_hint";
41constexpr char kDebugInfoString[] = ".debug_info";
42constexpr char kExternalDebugInfoString[] = "external_debug_info";
43
44const char* ExternalKindName(ImportExportKindCode kind) {
45  switch (kind) {
46    case kExternalFunction:
47      return "function";
48    case kExternalTable:
49      return "table";
50    case kExternalMemory:
51      return "memory";
52    case kExternalGlobal:
53      return "global";
54    case kExternalTag:
55      return "tag";
56  }
57  return "unknown";
58}
59
60}  // namespace
61
62const char* SectionName(SectionCode code) {
63  switch (code) {
64    case kUnknownSectionCode:
65      return "Unknown";
66    case kTypeSectionCode:
67      return "Type";
68    case kImportSectionCode:
69      return "Import";
70    case kFunctionSectionCode:
71      return "Function";
72    case kTableSectionCode:
73      return "Table";
74    case kMemorySectionCode:
75      return "Memory";
76    case kGlobalSectionCode:
77      return "Global";
78    case kExportSectionCode:
79      return "Export";
80    case kStartSectionCode:
81      return "Start";
82    case kCodeSectionCode:
83      return "Code";
84    case kElementSectionCode:
85      return "Element";
86    case kDataSectionCode:
87      return "Data";
88    case kTagSectionCode:
89      return "Tag";
90    case kDataCountSectionCode:
91      return "DataCount";
92    case kNameSectionCode:
93      return kNameString;
94    case kSourceMappingURLSectionCode:
95      return kSourceMappingURLString;
96    case kDebugInfoSectionCode:
97      return kDebugInfoString;
98    case kExternalDebugInfoSectionCode:
99      return kExternalDebugInfoString;
100    case kCompilationHintsSectionCode:
101      return kCompilationHintsString;
102    case kBranchHintsSectionCode:
103      return kBranchHintsString;
104    default:
105      return "<unknown>";
106  }
107}
108
109namespace {
110
111bool validate_utf8(Decoder* decoder, WireBytesRef string) {
112  return unibrow::Utf8::ValidateEncoding(
113      decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
114      string.length());
115}
116
117// Reads a length-prefixed string, checking that it is within bounds. Returns
118// the offset of the string, and the length as an out parameter.
119WireBytesRef consume_string(Decoder* decoder, bool validate_utf8,
120                            const char* name) {
121  uint32_t length = decoder->consume_u32v("string length");
122  uint32_t offset = decoder->pc_offset();
123  const byte* string_start = decoder->pc();
124  // Consume bytes before validation to guarantee that the string is not oob.
125  if (length > 0) {
126    decoder->consume_bytes(length, name);
127    if (decoder->ok() && validate_utf8 &&
128        !unibrow::Utf8::ValidateEncoding(string_start, length)) {
129      decoder->errorf(string_start, "%s: no valid UTF-8 string", name);
130    }
131  }
132  return {offset, decoder->failed() ? 0 : length};
133}
134
135namespace {
136SectionCode IdentifyUnknownSectionInternal(Decoder* decoder) {
137  WireBytesRef string = consume_string(decoder, true, "section name");
138  if (decoder->failed()) {
139    return kUnknownSectionCode;
140  }
141  const byte* section_name_start =
142      decoder->start() + decoder->GetBufferRelativeOffset(string.offset());
143
144  TRACE("  +%d  section name        : \"%.*s\"\n",
145        static_cast<int>(section_name_start - decoder->start()),
146        string.length() < 20 ? string.length() : 20, section_name_start);
147
148  using SpecialSectionPair = std::pair<base::Vector<const char>, SectionCode>;
149  static constexpr SpecialSectionPair kSpecialSections[]{
150      {base::StaticCharVector(kNameString), kNameSectionCode},
151      {base::StaticCharVector(kSourceMappingURLString),
152       kSourceMappingURLSectionCode},
153      {base::StaticCharVector(kCompilationHintsString),
154       kCompilationHintsSectionCode},
155      {base::StaticCharVector(kBranchHintsString), kBranchHintsSectionCode},
156      {base::StaticCharVector(kDebugInfoString), kDebugInfoSectionCode},
157      {base::StaticCharVector(kExternalDebugInfoString),
158       kExternalDebugInfoSectionCode}};
159
160  auto name_vec = base::Vector<const char>::cast(
161      base::VectorOf(section_name_start, string.length()));
162  for (auto& special_section : kSpecialSections) {
163    if (name_vec == special_section.first) return special_section.second;
164  }
165
166  return kUnknownSectionCode;
167}
168}  // namespace
169
170// An iterator over the sections in a wasm binary module.
171// Automatically skips all unknown sections.
172class WasmSectionIterator {
173 public:
174  explicit WasmSectionIterator(Decoder* decoder)
175      : decoder_(decoder),
176        section_code_(kUnknownSectionCode),
177        section_start_(decoder->pc()),
178        section_end_(decoder->pc()) {
179    next();
180  }
181
182  bool more() const { return decoder_->ok() && decoder_->more(); }
183
184  SectionCode section_code() const { return section_code_; }
185
186  const byte* section_start() const { return section_start_; }
187
188  uint32_t section_length() const {
189    return static_cast<uint32_t>(section_end_ - section_start_);
190  }
191
192  base::Vector<const uint8_t> payload() const {
193    return {payload_start_, payload_length()};
194  }
195
196  const byte* payload_start() const { return payload_start_; }
197
198  uint32_t payload_length() const {
199    return static_cast<uint32_t>(section_end_ - payload_start_);
200  }
201
202  const byte* section_end() const { return section_end_; }
203
204  // Advances to the next section, checking that decoding the current section
205  // stopped at {section_end_}.
206  void advance(bool move_to_section_end = false) {
207    if (move_to_section_end && decoder_->pc() < section_end_) {
208      decoder_->consume_bytes(
209          static_cast<uint32_t>(section_end_ - decoder_->pc()));
210    }
211    if (decoder_->pc() != section_end_) {
212      const char* msg = decoder_->pc() < section_end_ ? "shorter" : "longer";
213      decoder_->errorf(decoder_->pc(),
214                       "section was %s than expected size "
215                       "(%u bytes expected, %zu decoded)",
216                       msg, section_length(),
217                       static_cast<size_t>(decoder_->pc() - section_start_));
218    }
219    next();
220  }
221
222 private:
223  Decoder* decoder_;
224  SectionCode section_code_;
225  const byte* section_start_;
226  const byte* payload_start_;
227  const byte* section_end_;
228
229  // Reads the section code/name at the current position and sets up
230  // the embedder fields.
231  void next() {
232    if (!decoder_->more()) {
233      section_code_ = kUnknownSectionCode;
234      return;
235    }
236    section_start_ = decoder_->pc();
237    uint8_t section_code = decoder_->consume_u8("section code");
238    // Read and check the section size.
239    uint32_t section_length = decoder_->consume_u32v("section length");
240
241    payload_start_ = decoder_->pc();
242    if (decoder_->checkAvailable(section_length)) {
243      // Get the limit of the section within the module.
244      section_end_ = payload_start_ + section_length;
245    } else {
246      // The section would extend beyond the end of the module.
247      section_end_ = payload_start_;
248    }
249
250    if (section_code == kUnknownSectionCode) {
251      // Check for the known "name", "sourceMappingURL", or "compilationHints"
252      // section.
253      // To identify the unknown section we set the end of the decoder bytes to
254      // the end of the custom section, so that we do not read the section name
255      // beyond the end of the section.
256      const byte* module_end = decoder_->end();
257      decoder_->set_end(section_end_);
258      section_code = IdentifyUnknownSectionInternal(decoder_);
259      if (decoder_->ok()) decoder_->set_end(module_end);
260      // As a side effect, the above function will forward the decoder to after
261      // the identifier string.
262      payload_start_ = decoder_->pc();
263    } else if (!IsValidSectionCode(section_code)) {
264      decoder_->errorf(decoder_->pc(), "unknown section code #0x%02x",
265                       section_code);
266      section_code = kUnknownSectionCode;
267    }
268    section_code_ = decoder_->failed() ? kUnknownSectionCode
269                                       : static_cast<SectionCode>(section_code);
270
271    if (section_code_ == kUnknownSectionCode && section_end_ > decoder_->pc()) {
272      // skip to the end of the unknown section.
273      uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_->pc());
274      decoder_->consume_bytes(remaining, "section payload");
275    }
276  }
277};
278
279}  // namespace
280
281// The main logic for decoding the bytes of a module.
282class ModuleDecoderImpl : public Decoder {
283 public:
284  explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
285      : Decoder(nullptr, nullptr),
286        enabled_features_(enabled),
287        origin_(origin) {}
288
289  ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start,
290                    const byte* module_end, ModuleOrigin origin)
291      : Decoder(module_start, module_end),
292        enabled_features_(enabled),
293        module_start_(module_start),
294        module_end_(module_end),
295        origin_(origin) {
296    if (end_ < start_) {
297      error(start_, "end is less than start");
298      end_ = start_;
299    }
300  }
301
302  void onFirstError() override {
303    pc_ = end_;  // On error, terminate section decoding loop.
304  }
305
306  void DumpModule(const base::Vector<const byte> module_bytes) {
307    std::string path;
308    if (FLAG_dump_wasm_module_path) {
309      path = FLAG_dump_wasm_module_path;
310      if (path.size() &&
311          !base::OS::isDirectorySeparator(path[path.size() - 1])) {
312        path += base::OS::DirectorySeparator();
313      }
314    }
315    // File are named `HASH.{ok,failed}.wasm`.
316    size_t hash = base::hash_range(module_bytes.begin(), module_bytes.end());
317    base::EmbeddedVector<char, 32> buf;
318    SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed");
319    path += buf.begin();
320    size_t rv = 0;
321    if (FILE* file = base::OS::FOpen(path.c_str(), "wb")) {
322      rv = fwrite(module_bytes.begin(), module_bytes.length(), 1, file);
323      base::Fclose(file);
324    }
325    if (rv != 1) {
326      OFStream os(stderr);
327      os << "Error while dumping wasm file to " << path << std::endl;
328    }
329  }
330
331  void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
332    CHECK_NULL(module_);
333    SetCounters(counters);
334    module_.reset(
335        new WasmModule(std::make_unique<Zone>(allocator, "signatures")));
336    module_->initial_pages = 0;
337    module_->maximum_pages = 0;
338    module_->mem_export = false;
339    module_->origin = origin_;
340  }
341
342  void DecodeModuleHeader(base::Vector<const uint8_t> bytes, uint8_t offset) {
343    if (failed()) return;
344    Reset(bytes, offset);
345
346    const byte* pos = pc_;
347    uint32_t magic_word = consume_u32("wasm magic");
348#define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
349    if (magic_word != kWasmMagic) {
350      errorf(pos,
351             "expected magic word %02x %02x %02x %02x, "
352             "found %02x %02x %02x %02x",
353             BYTES(kWasmMagic), BYTES(magic_word));
354    }
355
356    pos = pc_;
357    {
358      uint32_t magic_version = consume_u32("wasm version");
359      if (magic_version != kWasmVersion) {
360        errorf(pos,
361               "expected version %02x %02x %02x %02x, "
362               "found %02x %02x %02x %02x",
363               BYTES(kWasmVersion), BYTES(magic_version));
364      }
365    }
366#undef BYTES
367  }
368
369  bool CheckSectionOrder(SectionCode section_code,
370                         SectionCode prev_section_code,
371                         SectionCode next_section_code) {
372    if (next_ordered_section_ > next_section_code) {
373      errorf(pc(), "The %s section must appear before the %s section",
374             SectionName(section_code), SectionName(next_section_code));
375      return false;
376    }
377    if (next_ordered_section_ <= prev_section_code) {
378      next_ordered_section_ = prev_section_code + 1;
379    }
380    return true;
381  }
382
383  bool CheckUnorderedSection(SectionCode section_code) {
384    if (has_seen_unordered_section(section_code)) {
385      errorf(pc(), "Multiple %s sections not allowed",
386             SectionName(section_code));
387      return false;
388    }
389    set_seen_unordered_section(section_code);
390    return true;
391  }
392
393  void DecodeSection(SectionCode section_code,
394                     base::Vector<const uint8_t> bytes, uint32_t offset,
395                     bool verify_functions = true) {
396    if (failed()) return;
397    Reset(bytes, offset);
398    TRACE("Section: %s\n", SectionName(section_code));
399    TRACE("Decode Section %p - %p\n", bytes.begin(), bytes.end());
400
401    // Check if the section is out-of-order.
402    if (section_code < next_ordered_section_ &&
403        section_code < kFirstUnorderedSection) {
404      errorf(pc(), "unexpected section <%s>", SectionName(section_code));
405      return;
406    }
407
408    switch (section_code) {
409      case kUnknownSectionCode:
410        break;
411      case kDataCountSectionCode:
412        if (!CheckUnorderedSection(section_code)) return;
413        // If wasm-gc is enabled, we allow the data cound section anywhere in
414        // the module.
415        if (!enabled_features_.has_gc() &&
416            !CheckSectionOrder(section_code, kElementSectionCode,
417                               kCodeSectionCode)) {
418          return;
419        }
420        break;
421      case kTagSectionCode:
422        if (!CheckUnorderedSection(section_code)) return;
423        if (!CheckSectionOrder(section_code, kMemorySectionCode,
424                               kGlobalSectionCode)) {
425          return;
426        }
427        break;
428      case kNameSectionCode:
429        // TODO(titzer): report out of place name section as a warning.
430        // Be lenient with placement of name section. All except first
431        // occurrence are ignored.
432      case kSourceMappingURLSectionCode:
433        // sourceMappingURL is a custom section and currently can occur anywhere
434        // in the module. In case of multiple sourceMappingURL sections, all
435        // except the first occurrence are ignored.
436      case kDebugInfoSectionCode:
437        // .debug_info is a custom section containing core DWARF information
438        // if produced by compiler. Its presence likely means that Wasm was
439        // built in a debug mode.
440      case kExternalDebugInfoSectionCode:
441        // external_debug_info is a custom section containing a reference to an
442        // external symbol file.
443      case kCompilationHintsSectionCode:
444        // TODO(frgossen): report out of place compilation hints section as a
445        // warning.
446        // Be lenient with placement of compilation hints section. All except
447        // first occurrence after function section and before code section are
448        // ignored.
449        break;
450      case kBranchHintsSectionCode:
451        // TODO(yuri): report out of place branch hints section as a
452        // warning.
453        // Be lenient with placement of compilation hints section. All except
454        // first occurrence after function section and before code section are
455        // ignored.
456        break;
457      default:
458        next_ordered_section_ = section_code + 1;
459        break;
460    }
461
462    switch (section_code) {
463      case kUnknownSectionCode:
464        break;
465      case kTypeSectionCode:
466        DecodeTypeSection();
467        break;
468      case kImportSectionCode:
469        DecodeImportSection();
470        break;
471      case kFunctionSectionCode:
472        DecodeFunctionSection();
473        break;
474      case kTableSectionCode:
475        DecodeTableSection();
476        break;
477      case kMemorySectionCode:
478        DecodeMemorySection();
479        break;
480      case kGlobalSectionCode:
481        DecodeGlobalSection();
482        break;
483      case kExportSectionCode:
484        DecodeExportSection();
485        break;
486      case kStartSectionCode:
487        DecodeStartSection();
488        break;
489      case kCodeSectionCode:
490        DecodeCodeSection(verify_functions);
491        break;
492      case kElementSectionCode:
493        DecodeElementSection();
494        break;
495      case kDataSectionCode:
496        DecodeDataSection();
497        break;
498      case kNameSectionCode:
499        DecodeNameSection();
500        break;
501      case kSourceMappingURLSectionCode:
502        DecodeSourceMappingURLSection();
503        break;
504      case kDebugInfoSectionCode:
505        // If there is an explicit source map, prefer it over DWARF info.
506        if (module_->debug_symbols.type == WasmDebugSymbols::Type::None) {
507          module_->debug_symbols = {WasmDebugSymbols::Type::EmbeddedDWARF, {}};
508        }
509        consume_bytes(static_cast<uint32_t>(end_ - start_), ".debug_info");
510        break;
511      case kExternalDebugInfoSectionCode:
512        DecodeExternalDebugInfoSection();
513        break;
514      case kCompilationHintsSectionCode:
515        if (enabled_features_.has_compilation_hints()) {
516          DecodeCompilationHintsSection();
517        } else {
518          // Ignore this section when feature was disabled. It is an optional
519          // custom section anyways.
520          consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
521        }
522        break;
523      case kBranchHintsSectionCode:
524        if (enabled_features_.has_branch_hinting()) {
525          DecodeBranchHintsSection();
526        } else {
527          // Ignore this section when feature was disabled. It is an optional
528          // custom section anyways.
529          consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
530        }
531        break;
532      case kDataCountSectionCode:
533        DecodeDataCountSection();
534        break;
535      case kTagSectionCode:
536        if (enabled_features_.has_eh()) {
537          DecodeTagSection();
538        } else {
539          errorf(pc(),
540                 "unexpected section <%s> (enable with --experimental-wasm-eh)",
541                 SectionName(section_code));
542        }
543        break;
544      default:
545        errorf(pc(), "unexpected section <%s>", SectionName(section_code));
546        return;
547    }
548
549    if (pc() != bytes.end()) {
550      const char* msg = pc() < bytes.end() ? "shorter" : "longer";
551      errorf(pc(),
552             "section was %s than expected size "
553             "(%zu bytes expected, %zu decoded)",
554             msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
555    }
556  }
557
558  TypeDefinition consume_base_type_definition() {
559    DCHECK(enabled_features_.has_gc());
560    uint8_t kind = consume_u8("type kind");
561    switch (kind) {
562      case kWasmFunctionTypeCode: {
563        const FunctionSig* sig = consume_sig(module_->signature_zone.get());
564        return {sig, kNoSuperType};
565      }
566      case kWasmStructTypeCode: {
567        const StructType* type = consume_struct(module_->signature_zone.get());
568        return {type, kNoSuperType};
569      }
570      case kWasmArrayTypeCode: {
571        const ArrayType* type = consume_array(module_->signature_zone.get());
572        return {type, kNoSuperType};
573      }
574      case kWasmFunctionNominalCode:
575      case kWasmArrayNominalCode:
576      case kWasmStructNominalCode:
577        errorf(pc() - 1,
578               "mixing nominal and isorecursive types is not allowed");
579        return {};
580      default:
581        errorf(pc() - 1, "unknown type form: %d", kind);
582        return {};
583    }
584  }
585
586  bool check_supertype(uint32_t supertype) {
587    if (V8_UNLIKELY(supertype >= module_->types.size())) {
588      errorf(pc(), "type %zu: forward-declared supertype %d",
589             module_->types.size(), supertype);
590      return false;
591    }
592    return true;
593  }
594
595  TypeDefinition consume_nominal_type_definition() {
596    DCHECK(enabled_features_.has_gc());
597    size_t num_types = module_->types.size();
598    uint8_t kind = consume_u8("type kind");
599    switch (kind) {
600      case kWasmFunctionNominalCode: {
601        const FunctionSig* sig = consume_sig(module_->signature_zone.get());
602        uint32_t super_index = kNoSuperType;
603        HeapType super_type = consume_super_type();
604        if (super_type.is_index()) {
605          super_index = super_type.representation();
606        } else if (V8_UNLIKELY(super_type != HeapType::kFunc)) {
607          errorf(pc() - 1, "type %zu: invalid supertype %d", num_types,
608                 super_type.code());
609          return {};
610        }
611        return {sig, super_index};
612      }
613      case kWasmStructNominalCode: {
614        const StructType* type = consume_struct(module_->signature_zone.get());
615        uint32_t super_index = kNoSuperType;
616        HeapType super_type = consume_super_type();
617        if (super_type.is_index()) {
618          super_index = super_type.representation();
619        } else if (V8_UNLIKELY(super_type != HeapType::kData)) {
620          errorf(pc() - 1, "type %zu: invalid supertype %d", num_types,
621                 super_type.code());
622          return {};
623        }
624        return {type, super_index};
625      }
626      case kWasmArrayNominalCode: {
627        const ArrayType* type = consume_array(module_->signature_zone.get());
628        uint32_t super_index = kNoSuperType;
629        HeapType super_type = consume_super_type();
630        if (super_type.is_index()) {
631          super_index = super_type.representation();
632        } else if (V8_UNLIKELY(super_type != HeapType::kData)) {
633          errorf(pc() - 1, "type %zu: invalid supertype %d", num_types,
634                 super_type.code());
635          return {};
636        }
637        return {type, super_index};
638      }
639      case kWasmFunctionTypeCode:
640      case kWasmArrayTypeCode:
641      case kWasmStructTypeCode:
642      case kWasmSubtypeCode:
643      case kWasmRecursiveTypeGroupCode:
644        errorf(pc() - 1,
645               "mixing nominal and isorecursive types is not allowed");
646        return {};
647      default:
648        errorf(pc() - 1, "unknown type form: %d", kind);
649        return {};
650    }
651  }
652
653  TypeDefinition consume_subtype_definition() {
654    DCHECK(enabled_features_.has_gc());
655    uint8_t kind = read_u8<Decoder::kFullValidation>(pc(), "type kind");
656    if (kind == kWasmSubtypeCode) {
657      consume_bytes(1, "subtype definition");
658      constexpr uint32_t kMaximumSupertypes = 1;
659      uint32_t supertype_count =
660          consume_count("supertype count", kMaximumSupertypes);
661      uint32_t supertype =
662          supertype_count == 1 ? consume_u32v("supertype") : kNoSuperType;
663      if (!check_supertype(supertype)) return {};
664      TypeDefinition type = consume_base_type_definition();
665      type.supertype = supertype;
666      return type;
667    } else {
668      return consume_base_type_definition();
669    }
670  }
671
672  void DecodeTypeSection() {
673    TypeCanonicalizer* type_canon = GetTypeCanonicalizer();
674    uint32_t types_count = consume_count("types count", kV8MaxWasmTypes);
675
676    // Non wasm-gc type section decoding.
677    if (!enabled_features_.has_gc()) {
678      module_->types.reserve(types_count);
679      for (uint32_t i = 0; i < types_count; ++i) {
680        TRACE("DecodeSignature[%d] module+%d\n", i,
681              static_cast<int>(pc_ - start_));
682        expect_u8("signature definition", kWasmFunctionTypeCode);
683        const FunctionSig* sig = consume_sig(module_->signature_zone.get());
684        if (!ok()) break;
685        module_->add_signature(sig, kNoSuperType);
686        if (FLAG_wasm_type_canonicalization) {
687          type_canon->AddRecursiveGroup(module_.get(), 1);
688        }
689      }
690      return;
691    }
692
693    if (types_count > 0) {
694      uint8_t first_type_opcode = this->read_u8<Decoder::kFullValidation>(pc());
695      if (first_type_opcode == kWasmFunctionNominalCode ||
696          first_type_opcode == kWasmStructNominalCode ||
697          first_type_opcode == kWasmArrayNominalCode) {
698        // wasm-gc nominal type section decoding.
699        // In a nominal module, all types belong in the same recursive group. We
700        // use the type vector's capacity to mark the end of the current
701        // recursive group.
702        module_->types.reserve(types_count);
703        for (uint32_t i = 0; ok() && i < types_count; ++i) {
704          TRACE("DecodeType[%d] module+%d\n", i,
705                static_cast<int>(pc_ - start_));
706          TypeDefinition type = consume_nominal_type_definition();
707          if (ok()) module_->add_type(type);
708        }
709        if (ok() && FLAG_wasm_type_canonicalization) {
710          type_canon->AddRecursiveGroup(module_.get(), types_count);
711        }
712      } else {
713        // wasm-gc isorecursive type section decoding.
714        for (uint32_t i = 0; ok() && i < types_count; ++i) {
715          TRACE("DecodeType[%d] module+%d\n", i,
716                static_cast<int>(pc_ - start_));
717          uint8_t kind = read_u8<Decoder::kFullValidation>(pc(), "type kind");
718          if (kind == kWasmRecursiveTypeGroupCode) {
719            consume_bytes(1, "rec. group definition");
720            uint32_t group_size =
721                consume_count("recursive group size", kV8MaxWasmTypes);
722            if (module_->types.size() + group_size > kV8MaxWasmTypes) {
723              errorf(pc(), "Type definition count exeeds maximum %zu",
724                     kV8MaxWasmTypes);
725              return;
726            }
727            // Reserve space for the current recursive group, so we are
728            // allowed to reference its elements.
729            module_->types.reserve(module_->types.size() + group_size);
730            for (uint32_t i = 0; i < group_size; i++) {
731              TypeDefinition type = consume_subtype_definition();
732              if (ok()) module_->add_type(type);
733            }
734            if (ok() && FLAG_wasm_type_canonicalization) {
735              type_canon->AddRecursiveGroup(module_.get(), group_size);
736            }
737          } else {
738            TypeDefinition type = consume_subtype_definition();
739            if (ok()) {
740              module_->add_type(type);
741              if (FLAG_wasm_type_canonicalization) {
742                type_canon->AddRecursiveGroup(module_.get(), 1);
743              }
744            }
745          }
746        }
747      }
748    }
749
750    // Check validity of explicitly defined supertypes.
751    const WasmModule* module = module_.get();
752    for (uint32_t i = 0; ok() && i < types_count; ++i) {
753      uint32_t explicit_super = module_->supertype(i);
754      if (explicit_super == kNoSuperType) continue;
755      DCHECK_LT(explicit_super, types_count);  // {consume_super_type} checks.
756      int depth = GetSubtypingDepth(module, i);
757      if (depth > static_cast<int>(kV8MaxRttSubtypingDepth)) {
758        errorf("type %d: subtyping depth is greater than allowed", i);
759        continue;
760      }
761      // TODO(7748): Replace this with a DCHECK once we reject inheritance
762      // cycles for nominal modules.
763      if (depth == -1) {
764        errorf("type %d: cyclic inheritance", i);
765        continue;
766      }
767      if (!ValidSubtypeDefinition(i, explicit_super, module, module)) {
768        errorf("type %d has invalid explicit supertype %d", i, explicit_super);
769        continue;
770      }
771    }
772    module_->signature_map.Freeze();
773  }
774
775  void DecodeImportSection() {
776    uint32_t import_table_count =
777        consume_count("imports count", kV8MaxWasmImports);
778    module_->import_table.reserve(import_table_count);
779    for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
780      TRACE("DecodeImportTable[%d] module+%d\n", i,
781            static_cast<int>(pc_ - start_));
782
783      module_->import_table.push_back({
784          {0, 0},             // module_name
785          {0, 0},             // field_name
786          kExternalFunction,  // kind
787          0                   // index
788      });
789      WasmImport* import = &module_->import_table.back();
790      const byte* pos = pc_;
791      import->module_name = consume_string(this, true, "module name");
792      import->field_name = consume_string(this, true, "field name");
793      import->kind =
794          static_cast<ImportExportKindCode>(consume_u8("import kind"));
795      switch (import->kind) {
796        case kExternalFunction: {
797          // ===== Imported function ===========================================
798          import->index = static_cast<uint32_t>(module_->functions.size());
799          module_->num_imported_functions++;
800          module_->functions.push_back({nullptr,        // sig
801                                        import->index,  // func_index
802                                        0,              // sig_index
803                                        {0, 0},         // code
804                                        0,              // feedback slots
805                                        true,           // imported
806                                        false,          // exported
807                                        false});        // declared
808          WasmFunction* function = &module_->functions.back();
809          function->sig_index =
810              consume_sig_index(module_.get(), &function->sig);
811          break;
812        }
813        case kExternalTable: {
814          // ===== Imported table ==============================================
815          import->index = static_cast<uint32_t>(module_->tables.size());
816          module_->num_imported_tables++;
817          module_->tables.emplace_back();
818          WasmTable* table = &module_->tables.back();
819          table->imported = true;
820          const byte* type_position = pc();
821          ValueType type = consume_reference_type();
822          if (!WasmTable::IsValidTableType(type, module_.get())) {
823            errorf(type_position, "Invalid table type %s", type.name().c_str());
824            break;
825          }
826          table->type = type;
827          uint8_t flags = validate_table_flags("element count");
828          consume_resizable_limits(
829              "element count", "elements", std::numeric_limits<uint32_t>::max(),
830              &table->initial_size, &table->has_maximum_size,
831              std::numeric_limits<uint32_t>::max(), &table->maximum_size,
832              flags);
833          break;
834        }
835        case kExternalMemory: {
836          // ===== Imported memory =============================================
837          if (!AddMemory(module_.get())) break;
838          uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
839                                                &module_->is_memory64);
840          consume_resizable_limits(
841              "memory", "pages", kSpecMaxMemoryPages, &module_->initial_pages,
842              &module_->has_maximum_pages, kSpecMaxMemoryPages,
843              &module_->maximum_pages, flags);
844          break;
845        }
846        case kExternalGlobal: {
847          // ===== Imported global =============================================
848          import->index = static_cast<uint32_t>(module_->globals.size());
849          module_->globals.push_back({kWasmVoid, false, {}, {0}, true, false});
850          WasmGlobal* global = &module_->globals.back();
851          global->type = consume_value_type();
852          global->mutability = consume_mutability();
853          if (global->mutability) {
854            module_->num_imported_mutable_globals++;
855          }
856          break;
857        }
858        case kExternalTag: {
859          // ===== Imported tag ================================================
860          if (!enabled_features_.has_eh()) {
861            errorf(pos, "unknown import kind 0x%02x", import->kind);
862            break;
863          }
864          import->index = static_cast<uint32_t>(module_->tags.size());
865          const WasmTagSig* tag_sig = nullptr;
866          consume_exception_attribute();  // Attribute ignored for now.
867          consume_tag_sig_index(module_.get(), &tag_sig);
868          module_->tags.emplace_back(tag_sig);
869          break;
870        }
871        default:
872          errorf(pos, "unknown import kind 0x%02x", import->kind);
873          break;
874      }
875    }
876  }
877
878  void DecodeFunctionSection() {
879    uint32_t functions_count =
880        consume_count("functions count", kV8MaxWasmFunctions);
881    auto counter =
882        SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
883    counter->AddSample(static_cast<int>(functions_count));
884    DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
885    uint32_t total_function_count =
886        module_->num_imported_functions + functions_count;
887    module_->functions.reserve(total_function_count);
888    module_->num_declared_functions = functions_count;
889    for (uint32_t i = 0; i < functions_count; ++i) {
890      uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
891      module_->functions.push_back({nullptr,     // sig
892                                    func_index,  // func_index
893                                    0,           // sig_index
894                                    {0, 0},      // code
895                                    0,           // feedback slots
896                                    false,       // imported
897                                    false,       // exported
898                                    false});     // declared
899      WasmFunction* function = &module_->functions.back();
900      function->sig_index = consume_sig_index(module_.get(), &function->sig);
901      if (!ok()) return;
902    }
903    DCHECK_EQ(module_->functions.size(), total_function_count);
904  }
905
906  void DecodeTableSection() {
907    uint32_t table_count = consume_count("table count", kV8MaxWasmTables);
908
909    for (uint32_t i = 0; ok() && i < table_count; i++) {
910      module_->tables.emplace_back();
911      WasmTable* table = &module_->tables.back();
912      const byte* type_position = pc();
913      ValueType table_type = consume_reference_type();
914      if (!WasmTable::IsValidTableType(table_type, module_.get())) {
915        error(type_position,
916              "Currently, only externref and function references are allowed "
917              "as table types");
918        continue;
919      }
920      table->type = table_type;
921      uint8_t flags = validate_table_flags("table elements");
922      consume_resizable_limits(
923          "table elements", "elements", std::numeric_limits<uint32_t>::max(),
924          &table->initial_size, &table->has_maximum_size,
925          std::numeric_limits<uint32_t>::max(), &table->maximum_size, flags);
926      if (!table_type.is_defaultable()) {
927        table->initial_value = consume_init_expr(module_.get(), table_type);
928      }
929    }
930  }
931
932  void DecodeMemorySection() {
933    uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
934
935    for (uint32_t i = 0; ok() && i < memory_count; i++) {
936      if (!AddMemory(module_.get())) break;
937      uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
938                                            &module_->is_memory64);
939      consume_resizable_limits("memory", "pages", kSpecMaxMemoryPages,
940                               &module_->initial_pages,
941                               &module_->has_maximum_pages, kSpecMaxMemoryPages,
942                               &module_->maximum_pages, flags);
943    }
944  }
945
946  void DecodeGlobalSection() {
947    uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
948    uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
949    // It is important to not resize the globals vector from the beginning,
950    // because we use its current size when decoding the initializer.
951    module_->globals.reserve(imported_globals + globals_count);
952    for (uint32_t i = 0; ok() && i < globals_count; ++i) {
953      TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
954      ValueType type = consume_value_type();
955      bool mutability = consume_mutability();
956      if (failed()) break;
957      ConstantExpression init = consume_init_expr(module_.get(), type);
958      module_->globals.push_back({type, mutability, init, {0}, false, false});
959    }
960    if (ok()) CalculateGlobalOffsets(module_.get());
961  }
962
963  void DecodeExportSection() {
964    uint32_t export_table_count =
965        consume_count("exports count", kV8MaxWasmExports);
966    module_->export_table.reserve(export_table_count);
967    for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
968      TRACE("DecodeExportTable[%d] module+%d\n", i,
969            static_cast<int>(pc_ - start_));
970
971      module_->export_table.push_back({
972          {0, 0},             // name
973          kExternalFunction,  // kind
974          0                   // index
975      });
976      WasmExport* exp = &module_->export_table.back();
977
978      exp->name = consume_string(this, true, "field name");
979
980      const byte* pos = pc();
981      exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
982      switch (exp->kind) {
983        case kExternalFunction: {
984          WasmFunction* func = nullptr;
985          exp->index =
986              consume_func_index(module_.get(), &func, "export function index");
987
988          if (failed()) break;
989          DCHECK_NOT_NULL(func);
990
991          module_->num_exported_functions++;
992          func->exported = true;
993          // Exported functions are considered "declared".
994          func->declared = true;
995          break;
996        }
997        case kExternalTable: {
998          WasmTable* table = nullptr;
999          exp->index = consume_table_index(module_.get(), &table);
1000          if (table) table->exported = true;
1001          break;
1002        }
1003        case kExternalMemory: {
1004          uint32_t index = consume_u32v("memory index");
1005          // TODO(titzer): This should become more regular
1006          // once we support multiple memories.
1007          if (!module_->has_memory || index != 0) {
1008            error("invalid memory index != 0");
1009          }
1010          module_->mem_export = true;
1011          break;
1012        }
1013        case kExternalGlobal: {
1014          WasmGlobal* global = nullptr;
1015          exp->index = consume_global_index(module_.get(), &global);
1016          if (global) {
1017            global->exported = true;
1018          }
1019          break;
1020        }
1021        case kExternalTag: {
1022          if (!enabled_features_.has_eh()) {
1023            errorf(pos, "invalid export kind 0x%02x", exp->kind);
1024            break;
1025          }
1026          WasmTag* tag = nullptr;
1027          exp->index = consume_tag_index(module_.get(), &tag);
1028          break;
1029        }
1030        default:
1031          errorf(pos, "invalid export kind 0x%02x", exp->kind);
1032          break;
1033      }
1034    }
1035    // Check for duplicate exports (except for asm.js).
1036    if (ok() && origin_ == kWasmOrigin && module_->export_table.size() > 1) {
1037      std::vector<WasmExport> sorted_exports(module_->export_table);
1038
1039      auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
1040        // Return true if a < b.
1041        if (a.name.length() != b.name.length()) {
1042          return a.name.length() < b.name.length();
1043        }
1044        const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
1045        const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
1046        return memcmp(left, right, a.name.length()) < 0;
1047      };
1048      std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
1049
1050      auto it = sorted_exports.begin();
1051      WasmExport* last = &*it++;
1052      for (auto end = sorted_exports.end(); it != end; last = &*it++) {
1053        DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
1054        if (!cmp_less(*last, *it)) {
1055          const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
1056          TruncatedUserString<> name(pc, it->name.length());
1057          errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
1058                 name.length(), name.start(), ExternalKindName(last->kind),
1059                 last->index, ExternalKindName(it->kind), it->index);
1060          break;
1061        }
1062      }
1063    }
1064  }
1065
1066  void DecodeStartSection() {
1067    WasmFunction* func;
1068    const byte* pos = pc_;
1069    module_->start_function_index =
1070        consume_func_index(module_.get(), &func, "start function index");
1071    if (func &&
1072        (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
1073      error(pos, "invalid start function: non-zero parameter or return count");
1074    }
1075  }
1076
1077  void DecodeElementSection() {
1078    uint32_t element_count =
1079        consume_count("element count", FLAG_wasm_max_table_size);
1080
1081    for (uint32_t i = 0; i < element_count; ++i) {
1082      WasmElemSegment segment = consume_element_segment_header();
1083      if (failed()) return;
1084      DCHECK_NE(segment.type, kWasmBottom);
1085
1086      uint32_t num_elem =
1087          consume_count("number of elements", max_table_init_entries());
1088
1089      for (uint32_t j = 0; j < num_elem; j++) {
1090        ConstantExpression entry =
1091            segment.element_type == WasmElemSegment::kExpressionElements
1092                ? consume_init_expr(module_.get(), segment.type)
1093                : ConstantExpression::RefFunc(
1094                      consume_element_func_index(segment.type));
1095        if (failed()) return;
1096        segment.entries.push_back(entry);
1097      }
1098      module_->elem_segments.push_back(std::move(segment));
1099    }
1100  }
1101
1102  void DecodeCodeSection(bool verify_functions) {
1103    StartCodeSection();
1104    uint32_t code_section_start = pc_offset();
1105    uint32_t functions_count = consume_u32v("functions count");
1106    CheckFunctionsCount(functions_count, code_section_start);
1107    for (uint32_t i = 0; ok() && i < functions_count; ++i) {
1108      const byte* pos = pc();
1109      uint32_t size = consume_u32v("body size");
1110      if (size > kV8MaxWasmFunctionSize) {
1111        errorf(pos, "size %u > maximum function size %zu", size,
1112               kV8MaxWasmFunctionSize);
1113        return;
1114      }
1115      uint32_t offset = pc_offset();
1116      consume_bytes(size, "function body");
1117      if (failed()) break;
1118      DecodeFunctionBody(i, size, offset, verify_functions);
1119    }
1120    DCHECK_GE(pc_offset(), code_section_start);
1121    set_code_section(code_section_start, pc_offset() - code_section_start);
1122  }
1123
1124  void StartCodeSection() {
1125    if (ok()) {
1126      // Make sure global offset were calculated before they get accessed during
1127      // function compilation.
1128      CalculateGlobalOffsets(module_.get());
1129    }
1130  }
1131
1132  bool CheckFunctionsCount(uint32_t functions_count, uint32_t error_offset) {
1133    if (functions_count != module_->num_declared_functions) {
1134      errorf(error_offset, "function body count %u mismatch (%u expected)",
1135             functions_count, module_->num_declared_functions);
1136      return false;
1137    }
1138    return true;
1139  }
1140
1141  void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
1142                          bool verify_functions) {
1143    WasmFunction* function =
1144        &module_->functions[index + module_->num_imported_functions];
1145    function->code = {offset, length};
1146    if (verify_functions) {
1147      ModuleWireBytes bytes(module_start_, module_end_);
1148      VerifyFunctionBody(module_->signature_zone->allocator(),
1149                         index + module_->num_imported_functions, bytes,
1150                         module_.get(), function);
1151    }
1152  }
1153
1154  bool CheckDataSegmentsCount(uint32_t data_segments_count) {
1155    if (has_seen_unordered_section(kDataCountSectionCode) &&
1156        data_segments_count != module_->num_declared_data_segments) {
1157      errorf(pc(), "data segments count %u mismatch (%u expected)",
1158             data_segments_count, module_->num_declared_data_segments);
1159      return false;
1160    }
1161    return true;
1162  }
1163
1164  void DecodeDataSection() {
1165    uint32_t data_segments_count =
1166        consume_count("data segments count", kV8MaxWasmDataSegments);
1167    if (!CheckDataSegmentsCount(data_segments_count)) return;
1168
1169    module_->data_segments.reserve(data_segments_count);
1170    for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
1171      const byte* pos = pc();
1172      TRACE("DecodeDataSegment[%d] module+%d\n", i,
1173            static_cast<int>(pc_ - start_));
1174
1175      bool is_active;
1176      uint32_t memory_index;
1177      ConstantExpression dest_addr;
1178      consume_data_segment_header(&is_active, &memory_index, &dest_addr);
1179      if (failed()) break;
1180
1181      if (is_active) {
1182        if (!module_->has_memory) {
1183          error("cannot load data without memory");
1184          break;
1185        }
1186        if (memory_index != 0) {
1187          errorf(pos, "illegal memory index %u != 0", memory_index);
1188          break;
1189        }
1190      }
1191
1192      uint32_t source_length = consume_u32v("source size");
1193      uint32_t source_offset = pc_offset();
1194
1195      if (is_active) {
1196        module_->data_segments.emplace_back(std::move(dest_addr));
1197      } else {
1198        module_->data_segments.emplace_back();
1199      }
1200
1201      WasmDataSegment* segment = &module_->data_segments.back();
1202
1203      consume_bytes(source_length, "segment data");
1204      if (failed()) break;
1205
1206      segment->source = {source_offset, source_length};
1207    }
1208  }
1209
1210  void DecodeNameSection() {
1211    // TODO(titzer): find a way to report name errors as warnings.
1212    // Ignore all but the first occurrence of name section.
1213    if (!has_seen_unordered_section(kNameSectionCode)) {
1214      set_seen_unordered_section(kNameSectionCode);
1215      // Use an inner decoder so that errors don't fail the outer decoder.
1216      Decoder inner(start_, pc_, end_, buffer_offset_);
1217      // Decode all name subsections.
1218      // Be lenient with their order.
1219      while (inner.ok() && inner.more()) {
1220        uint8_t name_type = inner.consume_u8("name type");
1221        if (name_type & 0x80) inner.error("name type if not varuint7");
1222
1223        uint32_t name_payload_len = inner.consume_u32v("name payload length");
1224        if (!inner.checkAvailable(name_payload_len)) break;
1225
1226        // Decode module name, ignore the rest.
1227        // Function and local names will be decoded when needed.
1228        if (name_type == NameSectionKindCode::kModuleCode) {
1229          WireBytesRef name = consume_string(&inner, false, "module name");
1230          if (inner.ok() && validate_utf8(&inner, name)) {
1231            module_->name = name;
1232          }
1233        } else {
1234          inner.consume_bytes(name_payload_len, "name subsection payload");
1235        }
1236      }
1237    }
1238    // Skip the whole names section in the outer decoder.
1239    consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1240  }
1241
1242  void DecodeSourceMappingURLSection() {
1243    Decoder inner(start_, pc_, end_, buffer_offset_);
1244    WireBytesRef url = wasm::consume_string(&inner, true, "module name");
1245    if (inner.ok() &&
1246        module_->debug_symbols.type != WasmDebugSymbols::Type::SourceMap) {
1247      module_->debug_symbols = {WasmDebugSymbols::Type::SourceMap, url};
1248    }
1249    set_seen_unordered_section(kSourceMappingURLSectionCode);
1250    consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1251  }
1252
1253  void DecodeExternalDebugInfoSection() {
1254    Decoder inner(start_, pc_, end_, buffer_offset_);
1255    WireBytesRef url =
1256        wasm::consume_string(&inner, true, "external symbol file");
1257    // If there is an explicit source map, prefer it over DWARF info.
1258    if (inner.ok() &&
1259        module_->debug_symbols.type != WasmDebugSymbols::Type::SourceMap) {
1260      module_->debug_symbols = {WasmDebugSymbols::Type::ExternalDWARF, url};
1261      set_seen_unordered_section(kExternalDebugInfoSectionCode);
1262    }
1263    consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1264  }
1265
1266  void DecodeCompilationHintsSection() {
1267    TRACE("DecodeCompilationHints module+%d\n", static_cast<int>(pc_ - start_));
1268
1269    // TODO(frgossen): Find a way to report compilation hint errors as warnings.
1270    // All except first occurrence after function section and before code
1271    // section are ignored.
1272    const bool before_function_section =
1273        next_ordered_section_ <= kFunctionSectionCode;
1274    const bool after_code_section = next_ordered_section_ > kCodeSectionCode;
1275    if (before_function_section || after_code_section ||
1276        has_seen_unordered_section(kCompilationHintsSectionCode)) {
1277      return;
1278    }
1279    set_seen_unordered_section(kCompilationHintsSectionCode);
1280
1281    // TODO(frgossen) Propagate errors to outer decoder in experimental phase.
1282    // We should use an inner decoder later and propagate its errors as
1283    // warnings.
1284    Decoder& decoder = *this;
1285    // Decoder decoder(start_, pc_, end_, buffer_offset_);
1286
1287    // Ensure exactly one compilation hint per function.
1288    uint32_t hint_count = decoder.consume_u32v("compilation hint count");
1289    if (hint_count != module_->num_declared_functions) {
1290      decoder.errorf(decoder.pc(), "Expected %u compilation hints (%u found)",
1291                     module_->num_declared_functions, hint_count);
1292    }
1293
1294    // Decode sequence of compilation hints.
1295    if (decoder.ok()) {
1296      module_->compilation_hints.reserve(hint_count);
1297    }
1298    for (uint32_t i = 0; decoder.ok() && i < hint_count; i++) {
1299      TRACE("DecodeCompilationHints[%d] module+%d\n", i,
1300            static_cast<int>(pc_ - start_));
1301
1302      // Compilation hints are encoded in one byte each.
1303      // +-------+----------+---------------+----------+
1304      // | 2 bit | 2 bit    | 2 bit         | 2 bit    |
1305      // | ...   | Top tier | Baseline tier | Strategy |
1306      // +-------+----------+---------------+----------+
1307      uint8_t hint_byte = decoder.consume_u8("compilation hint");
1308      if (!decoder.ok()) break;
1309
1310      // Validate the hint_byte.
1311      // For the compilation strategy, all 2-bit values are valid. For the tier,
1312      // only 0x0, 0x1, and 0x2 are allowed.
1313      static_assert(
1314          static_cast<int>(WasmCompilationHintTier::kDefault) == 0 &&
1315              static_cast<int>(WasmCompilationHintTier::kBaseline) == 1 &&
1316              static_cast<int>(WasmCompilationHintTier::kOptimized) == 2,
1317          "The check below assumes that 0x03 is the only invalid 2-bit number "
1318          "for a compilation tier");
1319      if (((hint_byte >> 2) & 0x03) == 0x03 ||
1320          ((hint_byte >> 4) & 0x03) == 0x03) {
1321        decoder.errorf(decoder.pc(),
1322                       "Invalid compilation hint %#04x (invalid tier 0x03)",
1323                       hint_byte);
1324        break;
1325      }
1326
1327      // Decode compilation hint.
1328      WasmCompilationHint hint;
1329      hint.strategy =
1330          static_cast<WasmCompilationHintStrategy>(hint_byte & 0x03);
1331      hint.baseline_tier =
1332          static_cast<WasmCompilationHintTier>((hint_byte >> 2) & 0x03);
1333      hint.top_tier =
1334          static_cast<WasmCompilationHintTier>((hint_byte >> 4) & 0x03);
1335
1336      // Ensure that the top tier never downgrades a compilation result. If
1337      // baseline and top tier are the same compilation will be invoked only
1338      // once.
1339      if (hint.top_tier < hint.baseline_tier &&
1340          hint.top_tier != WasmCompilationHintTier::kDefault) {
1341        decoder.errorf(decoder.pc(),
1342                       "Invalid compilation hint %#04x (forbidden downgrade)",
1343                       hint_byte);
1344      }
1345
1346      // Happily accept compilation hint.
1347      if (decoder.ok()) {
1348        module_->compilation_hints.push_back(std::move(hint));
1349      }
1350    }
1351
1352    // If section was invalid reset compilation hints.
1353    if (decoder.failed()) {
1354      module_->compilation_hints.clear();
1355    }
1356
1357    // @TODO(frgossen) Skip the whole compilation hints section in the outer
1358    // decoder if inner decoder was used.
1359    // consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1360  }
1361
1362  void DecodeBranchHintsSection() {
1363    TRACE("DecodeBranchHints module+%d\n", static_cast<int>(pc_ - start_));
1364    if (!has_seen_unordered_section(kBranchHintsSectionCode)) {
1365      set_seen_unordered_section(kBranchHintsSectionCode);
1366      // Use an inner decoder so that errors don't fail the outer decoder.
1367      Decoder inner(start_, pc_, end_, buffer_offset_);
1368      BranchHintInfo branch_hints;
1369
1370      uint32_t func_count = inner.consume_u32v("number of functions");
1371      // Keep track of the previous function index to validate the ordering
1372      int64_t last_func_idx = -1;
1373      for (uint32_t i = 0; i < func_count; i++) {
1374        uint32_t func_idx = inner.consume_u32v("function index");
1375        if (int64_t(func_idx) <= last_func_idx) {
1376          inner.errorf("Invalid function index: %d", func_idx);
1377          break;
1378        }
1379        last_func_idx = func_idx;
1380        uint32_t num_hints = inner.consume_u32v("number of hints");
1381        BranchHintMap func_branch_hints;
1382        TRACE("DecodeBranchHints[%d] module+%d\n", func_idx,
1383              static_cast<int>(inner.pc() - inner.start()));
1384        // Keep track of the previous branch offset to validate the ordering
1385        int64_t last_br_off = -1;
1386        for (uint32_t j = 0; j < num_hints; ++j) {
1387          uint32_t br_off = inner.consume_u32v("branch instruction offset");
1388          if (int64_t(br_off) <= last_br_off) {
1389            inner.errorf("Invalid branch offset: %d", br_off);
1390            break;
1391          }
1392          last_br_off = br_off;
1393          uint32_t data_size = inner.consume_u32v("data size");
1394          if (data_size != 1) {
1395            inner.errorf("Invalid data size: %#x. Expected 1.", data_size);
1396            break;
1397          }
1398          uint32_t br_dir = inner.consume_u8("branch direction");
1399          TRACE("DecodeBranchHints[%d][%d] module+%d\n", func_idx, br_off,
1400                static_cast<int>(inner.pc() - inner.start()));
1401          WasmBranchHint hint;
1402          switch (br_dir) {
1403            case 0:
1404              hint = WasmBranchHint::kUnlikely;
1405              break;
1406            case 1:
1407              hint = WasmBranchHint::kLikely;
1408              break;
1409            default:
1410              hint = WasmBranchHint::kNoHint;
1411              inner.errorf(inner.pc(), "Invalid branch hint %#x", br_dir);
1412              break;
1413          }
1414          if (!inner.ok()) {
1415            break;
1416          }
1417          func_branch_hints.insert(br_off, hint);
1418        }
1419        if (!inner.ok()) {
1420          break;
1421        }
1422        branch_hints.emplace(func_idx, std::move(func_branch_hints));
1423      }
1424      // Extra unexpected bytes are an error.
1425      if (inner.more()) {
1426        inner.errorf("Unexpected extra bytes: %d\n",
1427                     static_cast<int>(inner.pc() - inner.start()));
1428      }
1429      // If everything went well, accept the hints for the module.
1430      if (inner.ok()) {
1431        module_->branch_hints = std::move(branch_hints);
1432      }
1433    }
1434    // Skip the whole branch hints section in the outer decoder.
1435    consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1436  }
1437
1438  void DecodeDataCountSection() {
1439    module_->num_declared_data_segments =
1440        consume_count("data segments count", kV8MaxWasmDataSegments);
1441  }
1442
1443  void DecodeTagSection() {
1444    uint32_t tag_count = consume_count("tag count", kV8MaxWasmTags);
1445    for (uint32_t i = 0; ok() && i < tag_count; ++i) {
1446      TRACE("DecodeTag[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
1447      const WasmTagSig* tag_sig = nullptr;
1448      consume_exception_attribute();  // Attribute ignored for now.
1449      consume_tag_sig_index(module_.get(), &tag_sig);
1450      module_->tags.emplace_back(tag_sig);
1451    }
1452  }
1453
1454  bool CheckMismatchedCounts() {
1455    // The declared vs. defined function count is normally checked when
1456    // decoding the code section, but we have to check it here too in case the
1457    // code section is absent.
1458    if (module_->num_declared_functions != 0) {
1459      DCHECK_LT(module_->num_imported_functions, module_->functions.size());
1460      // We know that the code section has been decoded if the first
1461      // non-imported function has its code set.
1462      if (!module_->functions[module_->num_imported_functions].code.is_set()) {
1463        errorf(pc(), "function count is %u, but code section is absent",
1464               module_->num_declared_functions);
1465        return false;
1466      }
1467    }
1468    // Perform a similar check for the DataCount and Data sections, where data
1469    // segments are declared but the Data section is absent.
1470    if (!CheckDataSegmentsCount(
1471            static_cast<uint32_t>(module_->data_segments.size()))) {
1472      return false;
1473    }
1474    return true;
1475  }
1476
1477  ModuleResult FinishDecoding(bool verify_functions = true) {
1478    if (ok() && CheckMismatchedCounts()) {
1479      // We calculate the global offsets here, because there may not be a
1480      // global section and code section that would have triggered the
1481      // calculation before. Even without the globals section the calculation
1482      // is needed because globals can also be defined in the import section.
1483      CalculateGlobalOffsets(module_.get());
1484    }
1485
1486    ModuleResult result = toResult(std::move(module_));
1487    if (verify_functions && result.ok() && intermediate_error_.has_error()) {
1488      // Copy error message and location.
1489      return ModuleResult{std::move(intermediate_error_)};
1490    }
1491    return result;
1492  }
1493
1494  void set_code_section(uint32_t offset, uint32_t size) {
1495    module_->code = {offset, size};
1496  }
1497
1498  // Decodes an entire module.
1499  ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
1500                            bool verify_functions = true) {
1501    StartDecoding(counters, allocator);
1502    uint32_t offset = 0;
1503    base::Vector<const byte> orig_bytes(start(), end() - start());
1504    DecodeModuleHeader(base::VectorOf(start(), end() - start()), offset);
1505    if (failed()) {
1506      return FinishDecoding(verify_functions);
1507    }
1508    // Size of the module header.
1509    offset += 8;
1510    Decoder decoder(start_ + offset, end_, offset);
1511
1512    WasmSectionIterator section_iter(&decoder);
1513
1514    while (ok()) {
1515      // Shift the offset by the section header length
1516      offset += section_iter.payload_start() - section_iter.section_start();
1517      if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
1518        DecodeSection(section_iter.section_code(), section_iter.payload(),
1519                      offset, verify_functions);
1520      }
1521      // Shift the offset by the remaining section payload
1522      offset += section_iter.payload_length();
1523      if (!section_iter.more()) break;
1524      section_iter.advance(true);
1525    }
1526
1527    if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
1528
1529    if (decoder.failed()) {
1530      return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
1531    }
1532
1533    return FinishDecoding(verify_functions);
1534  }
1535
1536  // Decodes a single anonymous function starting at {start_}.
1537  FunctionResult DecodeSingleFunction(Zone* zone,
1538                                      const ModuleWireBytes& wire_bytes,
1539                                      const WasmModule* module,
1540                                      std::unique_ptr<WasmFunction> function) {
1541    pc_ = start_;
1542    expect_u8("type form", kWasmFunctionTypeCode);
1543    if (!ok()) return FunctionResult{std::move(intermediate_error_)};
1544    function->sig = consume_sig(zone);
1545    function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
1546
1547    if (ok())
1548      VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
1549                         function.get());
1550
1551    if (intermediate_error_.has_error()) {
1552      return FunctionResult{std::move(intermediate_error_)};
1553    }
1554
1555    return FunctionResult(std::move(function));
1556  }
1557
1558  // Decodes a single function signature at {start}.
1559  const FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
1560    pc_ = start;
1561    if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
1562    const FunctionSig* result = consume_sig(zone);
1563    return ok() ? result : nullptr;
1564  }
1565
1566  ConstantExpression DecodeInitExprForTesting(ValueType expected) {
1567    return consume_init_expr(module_.get(), expected);
1568  }
1569
1570  const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
1571
1572  Counters* GetCounters() const {
1573    DCHECK_NOT_NULL(counters_);
1574    return counters_;
1575  }
1576
1577  void SetCounters(Counters* counters) {
1578    DCHECK_NULL(counters_);
1579    counters_ = counters;
1580  }
1581
1582 private:
1583  const WasmFeatures enabled_features_;
1584  std::shared_ptr<WasmModule> module_;
1585  const byte* module_start_ = nullptr;
1586  const byte* module_end_ = nullptr;
1587  Counters* counters_ = nullptr;
1588  // The type section is the first section in a module.
1589  uint8_t next_ordered_section_ = kFirstSectionInModule;
1590  // We store next_ordered_section_ as uint8_t instead of SectionCode so that
1591  // we can increment it. This static_assert should make sure that SectionCode
1592  // does not get bigger than uint8_t accidentially.
1593  static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
1594                    sizeof(SectionCode),
1595                "type mismatch");
1596  uint32_t seen_unordered_sections_ = 0;
1597  static_assert(kBitsPerByte *
1598                        sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
1599                    kLastKnownModuleSection,
1600                "not enough bits");
1601  WasmError intermediate_error_;
1602  ModuleOrigin origin_;
1603  AccountingAllocator allocator_;
1604  Zone init_expr_zone_{&allocator_, "initializer expression zone"};
1605
1606  bool has_seen_unordered_section(SectionCode section_code) {
1607    return seen_unordered_sections_ & (1 << section_code);
1608  }
1609
1610  void set_seen_unordered_section(SectionCode section_code) {
1611    seen_unordered_sections_ |= 1 << section_code;
1612  }
1613
1614  uint32_t off(const byte* ptr) {
1615    return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
1616  }
1617
1618  bool AddMemory(WasmModule* module) {
1619    if (module->has_memory) {
1620      error("At most one memory is supported");
1621      return false;
1622    } else {
1623      module->has_memory = true;
1624      return true;
1625    }
1626  }
1627
1628  // Calculate individual global offsets and total size of globals table. This
1629  // function should be called after all globals have been defined, which is
1630  // after the import section and the global section, but before the global
1631  // offsets are accessed, e.g. by the function compilers. The moment when this
1632  // function should be called is not well-defined, as the global section may
1633  // not exist. Therefore this function is called multiple times.
1634  void CalculateGlobalOffsets(WasmModule* module) {
1635    if (module->globals.empty() || module->untagged_globals_buffer_size != 0 ||
1636        module->tagged_globals_buffer_size != 0) {
1637      // This function has already been executed before, so we don't have to
1638      // execute it again.
1639      return;
1640    }
1641    uint32_t untagged_offset = 0;
1642    uint32_t tagged_offset = 0;
1643    uint32_t num_imported_mutable_globals = 0;
1644    for (WasmGlobal& global : module->globals) {
1645      if (global.mutability && global.imported) {
1646        global.index = num_imported_mutable_globals++;
1647      } else if (global.type.is_reference()) {
1648        global.offset = tagged_offset;
1649        // All entries in the tagged_globals_buffer have size 1.
1650        tagged_offset++;
1651      } else {
1652        int size = global.type.value_kind_size();
1653        untagged_offset = (untagged_offset + size - 1) & ~(size - 1);  // align
1654        global.offset = untagged_offset;
1655        untagged_offset += size;
1656      }
1657    }
1658    module->untagged_globals_buffer_size = untagged_offset;
1659    module->tagged_globals_buffer_size = tagged_offset;
1660  }
1661
1662  // Verifies the body (code) of a given function.
1663  void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
1664                          const ModuleWireBytes& wire_bytes,
1665                          const WasmModule* module, WasmFunction* function) {
1666    WasmFunctionName func_name(function,
1667                               wire_bytes.GetNameOrNull(function, module));
1668    if (FLAG_trace_wasm_decoder) {
1669      StdoutStream{} << "Verifying wasm function " << func_name << std::endl;
1670    }
1671    FunctionBody body = {
1672        function->sig, function->code.offset(),
1673        start_ + GetBufferRelativeOffset(function->code.offset()),
1674        start_ + GetBufferRelativeOffset(function->code.end_offset())};
1675
1676    WasmFeatures unused_detected_features = WasmFeatures::None();
1677    DecodeResult result = VerifyWasmCode(allocator, enabled_features_, module,
1678                                         &unused_detected_features, body);
1679
1680    // If the decode failed and this is the first error, set error code and
1681    // location.
1682    if (result.failed() && intermediate_error_.empty()) {
1683      // Wrap the error message from the function decoder.
1684      std::ostringstream error_msg;
1685      error_msg << "in function " << func_name << ": "
1686                << result.error().message();
1687      intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
1688    }
1689  }
1690
1691  uint32_t consume_sig_index(WasmModule* module, const FunctionSig** sig) {
1692    const byte* pos = pc_;
1693    uint32_t sig_index = consume_u32v("signature index");
1694    if (!module->has_signature(sig_index)) {
1695      errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
1696             static_cast<int>(module->types.size()));
1697      *sig = nullptr;
1698      return 0;
1699    }
1700    *sig = module->signature(sig_index);
1701    return sig_index;
1702  }
1703
1704  uint32_t consume_tag_sig_index(WasmModule* module, const FunctionSig** sig) {
1705    const byte* pos = pc_;
1706    uint32_t sig_index = consume_sig_index(module, sig);
1707    if (*sig && (*sig)->return_count() != 0) {
1708      errorf(pos, "tag signature %u has non-void return", sig_index);
1709      *sig = nullptr;
1710      return 0;
1711    }
1712    return sig_index;
1713  }
1714
1715  uint32_t consume_count(const char* name, size_t maximum) {
1716    const byte* p = pc_;
1717    uint32_t count = consume_u32v(name);
1718    if (count > maximum) {
1719      errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
1720      return static_cast<uint32_t>(maximum);
1721    }
1722    return count;
1723  }
1724
1725  uint32_t consume_func_index(WasmModule* module, WasmFunction** func,
1726                              const char* name) {
1727    return consume_index(name, &module->functions, func);
1728  }
1729
1730  uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
1731    return consume_index("global index", &module->globals, global);
1732  }
1733
1734  uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
1735    return consume_index("table index", &module->tables, table);
1736  }
1737
1738  uint32_t consume_tag_index(WasmModule* module, WasmTag** tag) {
1739    return consume_index("tag index", &module->tags, tag);
1740  }
1741
1742  template <typename T>
1743  uint32_t consume_index(const char* name, std::vector<T>* vector, T** ptr) {
1744    const byte* pos = pc_;
1745    uint32_t index = consume_u32v(name);
1746    if (index >= vector->size()) {
1747      errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
1748             static_cast<int>(vector->size()),
1749             vector->size() == 1 ? "y" : "ies");
1750      *ptr = nullptr;
1751      return 0;
1752    }
1753    *ptr = &(*vector)[index];
1754    return index;
1755  }
1756
1757  uint8_t validate_table_flags(const char* name) {
1758    uint8_t flags = consume_u8("table limits flags");
1759    STATIC_ASSERT(kNoMaximum < kWithMaximum);
1760    if (V8_UNLIKELY(flags > kWithMaximum)) {
1761      errorf(pc() - 1, "invalid %s limits flags", name);
1762    }
1763    return flags;
1764  }
1765
1766  uint8_t validate_memory_flags(bool* has_shared_memory, bool* is_memory64) {
1767    uint8_t flags = consume_u8("memory limits flags");
1768    *has_shared_memory = false;
1769    switch (flags) {
1770      case kNoMaximum:
1771      case kWithMaximum:
1772        break;
1773      case kSharedNoMaximum:
1774      case kSharedWithMaximum:
1775        if (!enabled_features_.has_threads()) {
1776          errorf(pc() - 1,
1777                 "invalid memory limits flags 0x%x (enable via "
1778                 "--experimental-wasm-threads)",
1779                 flags);
1780        }
1781        *has_shared_memory = true;
1782        // V8 does not support shared memory without a maximum.
1783        if (flags == kSharedNoMaximum) {
1784          errorf(pc() - 1,
1785                 "memory limits flags must have maximum defined if shared is "
1786                 "true");
1787        }
1788        break;
1789      case kMemory64NoMaximum:
1790      case kMemory64WithMaximum:
1791        if (!enabled_features_.has_memory64()) {
1792          errorf(pc() - 1,
1793                 "invalid memory limits flags 0x%x (enable via "
1794                 "--experimental-wasm-memory64)",
1795                 flags);
1796        }
1797        *is_memory64 = true;
1798        break;
1799      default:
1800        errorf(pc() - 1, "invalid memory limits flags 0x%x", flags);
1801        break;
1802    }
1803    return flags;
1804  }
1805
1806  void consume_resizable_limits(const char* name, const char* units,
1807                                uint32_t max_initial, uint32_t* initial,
1808                                bool* has_max, uint32_t max_maximum,
1809                                uint32_t* maximum, uint8_t flags) {
1810    const byte* pos = pc();
1811    // For memory64 we need to read the numbers as LEB-encoded 64-bit unsigned
1812    // integer. All V8 limits are still within uint32_t range though.
1813    const bool is_memory64 =
1814        flags == kMemory64NoMaximum || flags == kMemory64WithMaximum;
1815    uint64_t initial_64 = is_memory64 ? consume_u64v("initial size")
1816                                      : consume_u32v("initial size");
1817    if (initial_64 > max_initial) {
1818      errorf(pos,
1819             "initial %s size (%" PRIu64
1820             " %s) is larger than implementation limit (%u)",
1821             name, initial_64, units, max_initial);
1822    }
1823    *initial = static_cast<uint32_t>(initial_64);
1824    if (flags & 1) {
1825      *has_max = true;
1826      pos = pc();
1827      uint64_t maximum_64 = is_memory64 ? consume_u64v("maximum size")
1828                                        : consume_u32v("maximum size");
1829      if (maximum_64 > max_maximum) {
1830        errorf(pos,
1831               "maximum %s size (%" PRIu64
1832               " %s) is larger than implementation limit (%u)",
1833               name, maximum_64, units, max_maximum);
1834      }
1835      if (maximum_64 < *initial) {
1836        errorf(pos,
1837               "maximum %s size (%" PRIu64 " %s) is less than initial (%u %s)",
1838               name, maximum_64, units, *initial, units);
1839      }
1840      *maximum = static_cast<uint32_t>(maximum_64);
1841    } else {
1842      *has_max = false;
1843      *maximum = max_initial;
1844    }
1845  }
1846
1847  // Consumes a byte, and emits an error if it does not equal {expected}.
1848  bool expect_u8(const char* name, uint8_t expected) {
1849    const byte* pos = pc();
1850    uint8_t value = consume_u8(name);
1851    if (value != expected) {
1852      errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
1853      return false;
1854    }
1855    return true;
1856  }
1857
1858  ConstantExpression consume_init_expr(WasmModule* module, ValueType expected) {
1859    uint32_t length;
1860
1861    // The error message mimics the one generated by the {WasmFullDecoder}.
1862#define TYPE_CHECK(found)                                             \
1863  if (V8_UNLIKELY(!IsSubtypeOf(found, expected, module_.get()))) {    \
1864    errorf(pc() + 1,                                                  \
1865           "type error in init. expression[0] (expected %s, got %s)", \
1866           expected.name().c_str(), found.name().c_str());            \
1867    return {};                                                        \
1868  }
1869
1870    // To avoid initializing a {WasmFullDecoder} for the most common
1871    // expressions, we replicate their decoding and validation here. The
1872    // manually handled cases correspond to {ConstantExpression}'s kinds.
1873    // We need to make sure to check that the expression ends in {kExprEnd};
1874    // otherwise, it is just the first operand of a composite expression, and we
1875    // fall back to the default case.
1876    if (!more()) {
1877      error("Beyond end of code");
1878      return {};
1879    }
1880    switch (static_cast<WasmOpcode>(*pc())) {
1881      case kExprI32Const: {
1882        int32_t value =
1883            read_i32v<kFullValidation>(pc() + 1, &length, "i32.const");
1884        if (V8_UNLIKELY(failed())) return {};
1885        if (V8_LIKELY(lookahead(1 + length, kExprEnd))) {
1886          TYPE_CHECK(kWasmI32)
1887          consume_bytes(length + 2);
1888          return ConstantExpression::I32Const(value);
1889        }
1890        break;
1891      }
1892      case kExprRefFunc: {
1893        uint32_t index =
1894            read_u32v<kFullValidation>(pc() + 1, &length, "ref.func");
1895        if (V8_UNLIKELY(failed())) return {};
1896        if (V8_LIKELY(lookahead(1 + length, kExprEnd))) {
1897          if (V8_UNLIKELY(index >= module_->functions.size())) {
1898            errorf(pc() + 1, "function index %u out of bounds", index);
1899            return {};
1900          }
1901          ValueType type =
1902              enabled_features_.has_typed_funcref()
1903                  ? ValueType::Ref(module_->functions[index].sig_index,
1904                                   kNonNullable)
1905                  : kWasmFuncRef;
1906          TYPE_CHECK(type)
1907          module_->functions[index].declared = true;
1908          consume_bytes(length + 2);
1909          return ConstantExpression::RefFunc(index);
1910        }
1911        break;
1912      }
1913      case kExprRefNull: {
1914        HeapType type = value_type_reader::read_heap_type<kFullValidation>(
1915            this, pc() + 1, &length, module_.get(), enabled_features_);
1916        if (V8_UNLIKELY(failed())) return {};
1917        if (V8_LIKELY(lookahead(1 + length, kExprEnd))) {
1918          TYPE_CHECK(ValueType::Ref(type, kNullable))
1919          consume_bytes(length + 2);
1920          return ConstantExpression::RefNull(type.representation());
1921        }
1922        break;
1923      }
1924      default:
1925        break;
1926    }
1927#undef TYPE_CHECK
1928
1929    auto sig = FixedSizeSignature<ValueType>::Returns(expected);
1930    FunctionBody body(&sig, buffer_offset_, pc_, end_);
1931    WasmFeatures detected;
1932    WasmFullDecoder<Decoder::kFullValidation, InitExprInterface,
1933                    kInitExpression>
1934        decoder(&init_expr_zone_, module, enabled_features_, &detected, body,
1935                module);
1936
1937    uint32_t offset = this->pc_offset();
1938
1939    decoder.DecodeFunctionBody();
1940
1941    this->pc_ = decoder.end();
1942
1943    if (decoder.failed()) {
1944      error(decoder.error().offset(), decoder.error().message().c_str());
1945      return {};
1946    }
1947
1948    if (!decoder.interface().end_found()) {
1949      error("Initializer expression is missing 'end'");
1950      return {};
1951    }
1952
1953    return ConstantExpression::WireBytes(
1954        offset, static_cast<uint32_t>(decoder.end() - decoder.start()));
1955  }
1956
1957  // Read a mutability flag
1958  bool consume_mutability() {
1959    byte val = consume_u8("mutability");
1960    if (val > 1) error(pc_ - 1, "invalid mutability");
1961    return val != 0;
1962  }
1963
1964  ValueType consume_value_type() {
1965    uint32_t type_length;
1966    ValueType result = value_type_reader::read_value_type<kFullValidation>(
1967        this, this->pc(), &type_length, module_.get(),
1968        origin_ == kWasmOrigin ? enabled_features_ : WasmFeatures::None());
1969    consume_bytes(type_length, "value type");
1970    return result;
1971  }
1972
1973  HeapType consume_super_type() {
1974    return value_type_reader::consume_heap_type(this, module_.get(),
1975                                                enabled_features_);
1976  }
1977
1978  ValueType consume_storage_type() {
1979    uint8_t opcode = read_u8<kFullValidation>(this->pc());
1980    switch (opcode) {
1981      case kI8Code:
1982        consume_bytes(1, "i8");
1983        return kWasmI8;
1984      case kI16Code:
1985        consume_bytes(1, "i16");
1986        return kWasmI16;
1987      default:
1988        // It is not a packed type, so it has to be a value type.
1989        return consume_value_type();
1990    }
1991  }
1992
1993  // Reads a reference type for tables and element segment headers.
1994  ValueType consume_reference_type() {
1995    const byte* position = pc();
1996    ValueType result = consume_value_type();
1997    if (!result.is_reference()) {
1998      error(position, "expected reference type");
1999    }
2000    return result;
2001  }
2002
2003  const FunctionSig* consume_sig(Zone* zone) {
2004    // Parse parameter types.
2005    uint32_t param_count =
2006        consume_count("param count", kV8MaxWasmFunctionParams);
2007    if (failed()) return nullptr;
2008    std::vector<ValueType> params;
2009    for (uint32_t i = 0; ok() && i < param_count; ++i) {
2010      params.push_back(consume_value_type());
2011    }
2012    std::vector<ValueType> returns;
2013
2014    // Parse return types.
2015    uint32_t return_count =
2016        consume_count("return count", kV8MaxWasmFunctionReturns);
2017    if (failed()) return nullptr;
2018    for (uint32_t i = 0; ok() && i < return_count; ++i) {
2019      returns.push_back(consume_value_type());
2020    }
2021    if (failed()) return nullptr;
2022
2023    // FunctionSig stores the return types first.
2024    ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
2025    uint32_t b = 0;
2026    for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
2027    for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
2028
2029    return zone->New<FunctionSig>(return_count, param_count, buffer);
2030  }
2031
2032  const StructType* consume_struct(Zone* zone) {
2033    uint32_t field_count = consume_count("field count", kV8MaxWasmStructFields);
2034    if (failed()) return nullptr;
2035    ValueType* fields = zone->NewArray<ValueType>(field_count);
2036    bool* mutabilities = zone->NewArray<bool>(field_count);
2037    for (uint32_t i = 0; ok() && i < field_count; ++i) {
2038      fields[i] = consume_storage_type();
2039      mutabilities[i] = consume_mutability();
2040    }
2041    if (failed()) return nullptr;
2042    uint32_t* offsets = zone->NewArray<uint32_t>(field_count);
2043    return zone->New<StructType>(field_count, offsets, fields, mutabilities);
2044  }
2045
2046  const ArrayType* consume_array(Zone* zone) {
2047    ValueType element_type = consume_storage_type();
2048    bool mutability = consume_mutability();
2049    if (failed()) return nullptr;
2050    return zone->New<ArrayType>(element_type, mutability);
2051  }
2052
2053  // Consume the attribute field of an exception.
2054  uint32_t consume_exception_attribute() {
2055    const byte* pos = pc_;
2056    uint32_t attribute = consume_u32v("exception attribute");
2057    if (attribute != kExceptionAttribute) {
2058      errorf(pos, "exception attribute %u not supported", attribute);
2059      return 0;
2060    }
2061    return attribute;
2062  }
2063
2064  WasmElemSegment consume_element_segment_header() {
2065    const byte* pos = pc();
2066
2067    // The mask for the bit in the flag which indicates if the segment is
2068    // active or not (0 is active).
2069    constexpr uint8_t kNonActiveMask = 1 << 0;
2070    // The mask for the bit in the flag which indicates:
2071    // - for active tables, if the segment has an explicit table index field.
2072    // - for non-active tables, whether the table is declarative (vs. passive).
2073    constexpr uint8_t kHasTableIndexOrIsDeclarativeMask = 1 << 1;
2074    // The mask for the bit in the flag which indicates if the functions of this
2075    // segment are defined as function indices (0) or init. expressions (1).
2076    constexpr uint8_t kExpressionsAsElementsMask = 1 << 2;
2077    constexpr uint8_t kFullMask = kNonActiveMask |
2078                                  kHasTableIndexOrIsDeclarativeMask |
2079                                  kExpressionsAsElementsMask;
2080
2081    uint32_t flag = consume_u32v("flag");
2082    if ((flag & kFullMask) != flag) {
2083      errorf(pos, "illegal flag value %u. Must be between 0 and 7", flag);
2084      return {};
2085    }
2086
2087    const WasmElemSegment::Status status =
2088        (flag & kNonActiveMask) ? (flag & kHasTableIndexOrIsDeclarativeMask)
2089                                      ? WasmElemSegment::kStatusDeclarative
2090                                      : WasmElemSegment::kStatusPassive
2091                                : WasmElemSegment::kStatusActive;
2092    const bool is_active = status == WasmElemSegment::kStatusActive;
2093
2094    WasmElemSegment::ElementType element_type =
2095        flag & kExpressionsAsElementsMask
2096            ? WasmElemSegment::kExpressionElements
2097            : WasmElemSegment::kFunctionIndexElements;
2098
2099    const bool has_table_index =
2100        is_active && (flag & kHasTableIndexOrIsDeclarativeMask);
2101    uint32_t table_index = has_table_index ? consume_u32v("table index") : 0;
2102    if (is_active && table_index >= module_->tables.size()) {
2103      errorf(pos, "out of bounds%s table index %u",
2104             has_table_index ? " implicit" : "", table_index);
2105      return {};
2106    }
2107    ValueType table_type =
2108        is_active ? module_->tables[table_index].type : kWasmBottom;
2109
2110    ConstantExpression offset;
2111    if (is_active) {
2112      offset = consume_init_expr(module_.get(), kWasmI32);
2113      // Failed to parse offset initializer, return early.
2114      if (failed()) return {};
2115    }
2116
2117    // Denotes an active segment without table index, type, or element kind.
2118    const bool backwards_compatible_mode =
2119        is_active && !(flag & kHasTableIndexOrIsDeclarativeMask);
2120    ValueType type;
2121    if (element_type == WasmElemSegment::kExpressionElements) {
2122      type =
2123          backwards_compatible_mode ? kWasmFuncRef : consume_reference_type();
2124      if (is_active && !IsSubtypeOf(type, table_type, this->module_.get())) {
2125        errorf(pos,
2126               "Element segment of type %s is not a subtype of referenced "
2127               "table %u (of type %s)",
2128               type.name().c_str(), table_index, table_type.name().c_str());
2129        return {};
2130      }
2131    } else {
2132      if (!backwards_compatible_mode) {
2133        // We have to check that there is an element kind of type Function. All
2134        // other element kinds are not valid yet.
2135        uint8_t val = consume_u8("element kind");
2136        if (static_cast<ImportExportKindCode>(val) != kExternalFunction) {
2137          errorf(pos, "illegal element kind 0x%x. Must be 0x%x", val,
2138                 kExternalFunction);
2139          return {};
2140        }
2141      }
2142      if (!is_active) {
2143        // Declarative and passive segments without explicit type are funcref.
2144        type = kWasmFuncRef;
2145      } else {
2146        type = table_type;
2147        // Active segments with function indices must reference a function
2148        // table. TODO(7748): Add support for anyref tables when we have them.
2149        if (!IsSubtypeOf(table_type, kWasmFuncRef, this->module_.get())) {
2150          errorf(pos,
2151                 "An active element segment with function indices as elements "
2152                 "must reference a table of %s. Instead, table %u of type %s "
2153                 "is referenced.",
2154                 enabled_features_.has_typed_funcref()
2155                     ? "a subtype of type funcref"
2156                     : "type funcref",
2157                 table_index, table_type.name().c_str());
2158          return {};
2159        }
2160      }
2161    }
2162
2163    if (is_active) {
2164      return {type, table_index, std::move(offset), element_type};
2165    } else {
2166      return {type, status, element_type};
2167    }
2168  }
2169
2170  void consume_data_segment_header(bool* is_active, uint32_t* index,
2171                                   ConstantExpression* offset) {
2172    const byte* pos = pc();
2173    uint32_t flag = consume_u32v("flag");
2174
2175    // Some flag values are only valid for specific proposals.
2176    if (flag != SegmentFlags::kActiveNoIndex &&
2177        flag != SegmentFlags::kPassive &&
2178        flag != SegmentFlags::kActiveWithIndex) {
2179      errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flag);
2180      return;
2181    }
2182
2183    // We know now that the flag is valid. Time to read the rest.
2184    ValueType expected_type = module_->is_memory64 ? kWasmI64 : kWasmI32;
2185    if (flag == SegmentFlags::kActiveNoIndex) {
2186      *is_active = true;
2187      *index = 0;
2188      *offset = consume_init_expr(module_.get(), expected_type);
2189      return;
2190    }
2191    if (flag == SegmentFlags::kPassive) {
2192      *is_active = false;
2193      return;
2194    }
2195    if (flag == SegmentFlags::kActiveWithIndex) {
2196      *is_active = true;
2197      *index = consume_u32v("memory index");
2198      *offset = consume_init_expr(module_.get(), expected_type);
2199    }
2200  }
2201
2202  uint32_t consume_element_func_index(ValueType expected) {
2203    WasmFunction* func = nullptr;
2204    const byte* initial_pc = pc();
2205    uint32_t index =
2206        consume_func_index(module_.get(), &func, "element function index");
2207    if (failed()) return index;
2208    DCHECK_NOT_NULL(func);
2209    DCHECK_EQ(index, func->func_index);
2210    ValueType entry_type = ValueType::Ref(func->sig_index, kNonNullable);
2211    if (V8_UNLIKELY(!IsSubtypeOf(entry_type, expected, module_.get()))) {
2212      errorf(initial_pc,
2213             "Invalid type in element entry: expected %s, got %s instead.",
2214             expected.name().c_str(), entry_type.name().c_str());
2215      return index;
2216    }
2217    func->declared = true;
2218    return index;
2219  }
2220};
2221
2222ModuleResult DecodeWasmModule(
2223    const WasmFeatures& enabled, const byte* module_start,
2224    const byte* module_end, bool verify_functions, ModuleOrigin origin,
2225    Counters* counters, std::shared_ptr<metrics::Recorder> metrics_recorder,
2226    v8::metrics::Recorder::ContextId context_id, DecodingMethod decoding_method,
2227    AccountingAllocator* allocator) {
2228  size_t size = module_end - module_start;
2229  CHECK_LE(module_start, module_end);
2230  size_t max_size = max_module_size();
2231  if (size > max_size) {
2232    return ModuleResult{
2233        WasmError{0, "size > maximum module size (%zu): %zu", max_size, size}};
2234  }
2235  // TODO(bradnelson): Improve histogram handling of size_t.
2236  auto size_counter =
2237      SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
2238  size_counter->AddSample(static_cast<int>(size));
2239  // Signatures are stored in zone memory, which have the same lifetime
2240  // as the {module}.
2241  ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
2242  v8::metrics::WasmModuleDecoded metrics_event;
2243  base::ElapsedTimer timer;
2244  timer.Start();
2245  base::ThreadTicks thread_ticks = base::ThreadTicks::IsSupported()
2246                                       ? base::ThreadTicks::Now()
2247                                       : base::ThreadTicks();
2248  ModuleResult result =
2249      decoder.DecodeModule(counters, allocator, verify_functions);
2250
2251  // Record event metrics.
2252  metrics_event.wall_clock_duration_in_us = timer.Elapsed().InMicroseconds();
2253  timer.Stop();
2254  if (!thread_ticks.IsNull()) {
2255    metrics_event.cpu_duration_in_us =
2256        (base::ThreadTicks::Now() - thread_ticks).InMicroseconds();
2257  }
2258  metrics_event.success = decoder.ok() && result.ok();
2259  metrics_event.async = decoding_method == DecodingMethod::kAsync ||
2260                        decoding_method == DecodingMethod::kAsyncStream;
2261  metrics_event.streamed = decoding_method == DecodingMethod::kSyncStream ||
2262                           decoding_method == DecodingMethod::kAsyncStream;
2263  if (result.ok()) {
2264    metrics_event.function_count = result.value()->num_declared_functions;
2265  } else if (auto&& module = decoder.shared_module()) {
2266    metrics_event.function_count = module->num_declared_functions;
2267  }
2268  metrics_event.module_size_in_bytes = size;
2269  metrics_recorder->DelayMainThreadEvent(metrics_event, context_id);
2270
2271  return result;
2272}
2273
2274ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
2275    : enabled_features_(enabled) {}
2276
2277ModuleDecoder::~ModuleDecoder() = default;
2278
2279const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
2280  return impl_->shared_module();
2281}
2282
2283void ModuleDecoder::StartDecoding(
2284    Counters* counters, std::shared_ptr<metrics::Recorder> metrics_recorder,
2285    v8::metrics::Recorder::ContextId context_id, AccountingAllocator* allocator,
2286    ModuleOrigin origin) {
2287  DCHECK_NULL(impl_);
2288  impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
2289  impl_->StartDecoding(counters, allocator);
2290}
2291
2292void ModuleDecoder::DecodeModuleHeader(base::Vector<const uint8_t> bytes,
2293                                       uint32_t offset) {
2294  impl_->DecodeModuleHeader(bytes, offset);
2295}
2296
2297void ModuleDecoder::DecodeSection(SectionCode section_code,
2298                                  base::Vector<const uint8_t> bytes,
2299                                  uint32_t offset, bool verify_functions) {
2300  impl_->DecodeSection(section_code, bytes, offset, verify_functions);
2301}
2302
2303void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
2304                                       uint32_t offset, bool verify_functions) {
2305  impl_->DecodeFunctionBody(index, length, offset, verify_functions);
2306}
2307
2308void ModuleDecoder::StartCodeSection() { impl_->StartCodeSection(); }
2309
2310bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
2311                                        uint32_t error_offset) {
2312  return impl_->CheckFunctionsCount(functions_count, error_offset);
2313}
2314
2315ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
2316  return impl_->FinishDecoding(verify_functions);
2317}
2318
2319void ModuleDecoder::set_code_section(uint32_t offset, uint32_t size) {
2320  return impl_->set_code_section(offset, size);
2321}
2322
2323size_t ModuleDecoder::IdentifyUnknownSection(ModuleDecoder* decoder,
2324                                             base::Vector<const uint8_t> bytes,
2325                                             uint32_t offset,
2326                                             SectionCode* result) {
2327  if (!decoder->ok()) return 0;
2328  decoder->impl_->Reset(bytes, offset);
2329  *result = IdentifyUnknownSectionInternal(decoder->impl_.get());
2330  return decoder->impl_->pc() - bytes.begin();
2331}
2332
2333bool ModuleDecoder::ok() { return impl_->ok(); }
2334
2335const FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
2336                                                 Zone* zone, const byte* start,
2337                                                 const byte* end) {
2338  ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
2339  return decoder.DecodeFunctionSignature(zone, start);
2340}
2341
2342ConstantExpression DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
2343                                                const byte* start,
2344                                                const byte* end,
2345                                                ValueType expected) {
2346  ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
2347  AccountingAllocator allocator;
2348  decoder.StartDecoding(nullptr, &allocator);
2349  return decoder.DecodeInitExprForTesting(expected);
2350}
2351
2352FunctionResult DecodeWasmFunctionForTesting(
2353    const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
2354    const WasmModule* module, const byte* function_start,
2355    const byte* function_end, Counters* counters) {
2356  size_t size = function_end - function_start;
2357  CHECK_LE(function_start, function_end);
2358  if (size > kV8MaxWasmFunctionSize) {
2359    return FunctionResult{WasmError{0,
2360                                    "size > maximum function size (%zu): %zu",
2361                                    kV8MaxWasmFunctionSize, size}};
2362  }
2363  ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
2364  decoder.SetCounters(counters);
2365  return decoder.DecodeSingleFunction(zone, wire_bytes, module,
2366                                      std::make_unique<WasmFunction>());
2367}
2368
2369AsmJsOffsetsResult DecodeAsmJsOffsets(
2370    base::Vector<const uint8_t> encoded_offsets) {
2371  std::vector<AsmJsOffsetFunctionEntries> functions;
2372
2373  Decoder decoder(encoded_offsets);
2374  uint32_t functions_count = decoder.consume_u32v("functions count");
2375  // Consistency check.
2376  DCHECK_GE(encoded_offsets.size(), functions_count);
2377  functions.reserve(functions_count);
2378
2379  for (uint32_t i = 0; i < functions_count; ++i) {
2380    uint32_t size = decoder.consume_u32v("table size");
2381    if (size == 0) {
2382      functions.emplace_back();
2383      continue;
2384    }
2385    DCHECK(decoder.checkAvailable(size));
2386    const byte* table_end = decoder.pc() + size;
2387    uint32_t locals_size = decoder.consume_u32v("locals size");
2388    int function_start_position = decoder.consume_u32v("function start pos");
2389    int function_end_position = function_start_position;
2390    int last_byte_offset = locals_size;
2391    int last_asm_position = function_start_position;
2392    std::vector<AsmJsOffsetEntry> func_asm_offsets;
2393    func_asm_offsets.reserve(size / 4);  // conservative estimation
2394    // Add an entry for the stack check, associated with position 0.
2395    func_asm_offsets.push_back(
2396        {0, function_start_position, function_start_position});
2397    while (decoder.pc() < table_end) {
2398      DCHECK(decoder.ok());
2399      last_byte_offset += decoder.consume_u32v("byte offset delta");
2400      int call_position =
2401          last_asm_position + decoder.consume_i32v("call position delta");
2402      int to_number_position =
2403          call_position + decoder.consume_i32v("to_number position delta");
2404      last_asm_position = to_number_position;
2405      if (decoder.pc() == table_end) {
2406        // The last entry is the function end marker.
2407        DCHECK_EQ(call_position, to_number_position);
2408        function_end_position = call_position;
2409      } else {
2410        func_asm_offsets.push_back(
2411            {last_byte_offset, call_position, to_number_position});
2412      }
2413    }
2414    DCHECK_EQ(decoder.pc(), table_end);
2415    functions.emplace_back(AsmJsOffsetFunctionEntries{
2416        function_start_position, function_end_position,
2417        std::move(func_asm_offsets)});
2418  }
2419  DCHECK(decoder.ok());
2420  DCHECK(!decoder.more());
2421
2422  return decoder.toResult(AsmJsOffsets{std::move(functions)});
2423}
2424
2425std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
2426                                                      const byte* end) {
2427  Decoder decoder(start, end);
2428  decoder.consume_bytes(4, "wasm magic");
2429  decoder.consume_bytes(4, "wasm version");
2430
2431  std::vector<CustomSectionOffset> result;
2432
2433  while (decoder.more()) {
2434    byte section_code = decoder.consume_u8("section code");
2435    uint32_t section_length = decoder.consume_u32v("section length");
2436    uint32_t section_start = decoder.pc_offset();
2437    if (section_code != 0) {
2438      // Skip known sections.
2439      decoder.consume_bytes(section_length, "section bytes");
2440      continue;
2441    }
2442    uint32_t name_length = decoder.consume_u32v("name length");
2443    uint32_t name_offset = decoder.pc_offset();
2444    decoder.consume_bytes(name_length, "section name");
2445    uint32_t payload_offset = decoder.pc_offset();
2446    if (section_length < (payload_offset - section_start)) {
2447      decoder.error("invalid section length");
2448      break;
2449    }
2450    uint32_t payload_length = section_length - (payload_offset - section_start);
2451    decoder.consume_bytes(payload_length);
2452    if (decoder.failed()) break;
2453    result.push_back({{section_start, section_length},
2454                      {name_offset, name_length},
2455                      {payload_offset, payload_length}});
2456  }
2457
2458  return result;
2459}
2460
2461namespace {
2462
2463bool FindNameSection(Decoder* decoder) {
2464  static constexpr int kModuleHeaderSize = 8;
2465  decoder->consume_bytes(kModuleHeaderSize, "module header");
2466
2467  WasmSectionIterator section_iter(decoder);
2468
2469  while (decoder->ok() && section_iter.more() &&
2470         section_iter.section_code() != kNameSectionCode) {
2471    section_iter.advance(true);
2472  }
2473  if (!section_iter.more()) return false;
2474
2475  // Reset the decoder to not read beyond the name section end.
2476  decoder->Reset(section_iter.payload(), decoder->pc_offset());
2477  return true;
2478}
2479
2480}  // namespace
2481
2482void DecodeFunctionNames(const byte* module_start, const byte* module_end,
2483                         std::unordered_map<uint32_t, WireBytesRef>* names) {
2484  DCHECK_NOT_NULL(names);
2485  DCHECK(names->empty());
2486
2487  Decoder decoder(module_start, module_end);
2488  if (FindNameSection(&decoder)) {
2489    while (decoder.ok() && decoder.more()) {
2490      uint8_t name_type = decoder.consume_u8("name type");
2491      if (name_type & 0x80) break;  // no varuint7
2492
2493      uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2494      if (!decoder.checkAvailable(name_payload_len)) break;
2495
2496      if (name_type != NameSectionKindCode::kFunctionCode) {
2497        decoder.consume_bytes(name_payload_len, "name subsection payload");
2498        continue;
2499      }
2500      uint32_t functions_count = decoder.consume_u32v("functions count");
2501
2502      for (; decoder.ok() && functions_count > 0; --functions_count) {
2503        uint32_t function_index = decoder.consume_u32v("function index");
2504        WireBytesRef name = consume_string(&decoder, false, "function name");
2505
2506        // Be lenient with errors in the name section: Ignore non-UTF8 names.
2507        // You can even assign to the same function multiple times (last valid
2508        // one wins).
2509        if (decoder.ok() && validate_utf8(&decoder, name)) {
2510          names->insert(std::make_pair(function_index, name));
2511        }
2512      }
2513    }
2514  }
2515}
2516
2517NameMap DecodeNameMap(base::Vector<const uint8_t> module_bytes,
2518                      uint8_t name_section_kind) {
2519  Decoder decoder(module_bytes);
2520  if (!FindNameSection(&decoder)) return NameMap{{}};
2521
2522  std::vector<NameAssoc> names;
2523  while (decoder.ok() && decoder.more()) {
2524    uint8_t name_type = decoder.consume_u8("name type");
2525    if (name_type & 0x80) break;  // no varuint7
2526
2527    uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2528    if (!decoder.checkAvailable(name_payload_len)) break;
2529
2530    if (name_type != name_section_kind) {
2531      decoder.consume_bytes(name_payload_len, "name subsection payload");
2532      continue;
2533    }
2534
2535    uint32_t count = decoder.consume_u32v("names count");
2536    for (uint32_t i = 0; i < count; i++) {
2537      uint32_t index = decoder.consume_u32v("index");
2538      WireBytesRef name = consume_string(&decoder, false, "name");
2539      if (!decoder.ok()) break;
2540      if (index > kMaxInt) continue;
2541      if (!validate_utf8(&decoder, name)) continue;
2542      names.emplace_back(static_cast<int>(index), name);
2543    }
2544  }
2545  std::stable_sort(names.begin(), names.end(), NameAssoc::IndexLess{});
2546  return NameMap{std::move(names)};
2547}
2548
2549IndirectNameMap DecodeIndirectNameMap(base::Vector<const uint8_t> module_bytes,
2550                                      uint8_t name_section_kind) {
2551  Decoder decoder(module_bytes);
2552  if (!FindNameSection(&decoder)) return IndirectNameMap{{}};
2553
2554  std::vector<IndirectNameMapEntry> entries;
2555  while (decoder.ok() && decoder.more()) {
2556    uint8_t name_type = decoder.consume_u8("name type");
2557    if (name_type & 0x80) break;  // no varuint7
2558
2559    uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2560    if (!decoder.checkAvailable(name_payload_len)) break;
2561
2562    if (name_type != name_section_kind) {
2563      decoder.consume_bytes(name_payload_len, "name subsection payload");
2564      continue;
2565    }
2566
2567    uint32_t outer_count = decoder.consume_u32v("outer count");
2568    for (uint32_t i = 0; i < outer_count; ++i) {
2569      uint32_t outer_index = decoder.consume_u32v("outer index");
2570      if (outer_index > kMaxInt) continue;
2571      std::vector<NameAssoc> names;
2572      uint32_t inner_count = decoder.consume_u32v("inner count");
2573      for (uint32_t k = 0; k < inner_count; ++k) {
2574        uint32_t inner_index = decoder.consume_u32v("inner index");
2575        WireBytesRef name = consume_string(&decoder, false, "name");
2576        if (!decoder.ok()) break;
2577        if (inner_index > kMaxInt) continue;
2578        // Ignore non-utf8 names.
2579        if (!validate_utf8(&decoder, name)) continue;
2580        names.emplace_back(static_cast<int>(inner_index), name);
2581      }
2582      // Use stable sort to get deterministic names (the first one declared)
2583      // even in the presence of duplicates.
2584      std::stable_sort(names.begin(), names.end(), NameAssoc::IndexLess{});
2585      entries.emplace_back(static_cast<int>(outer_index), std::move(names));
2586    }
2587  }
2588  std::stable_sort(entries.begin(), entries.end(),
2589                   IndirectNameMapEntry::IndexLess{});
2590  return IndirectNameMap{std::move(entries)};
2591}
2592
2593#undef TRACE
2594
2595}  // namespace wasm
2596}  // namespace internal
2597}  // namespace v8
2598