5 #include "src/wasm/module-decoder.h" 7 #include "src/base/functional.h" 8 #include "src/base/platform/platform.h" 9 #include "src/base/template-utils.h" 10 #include "src/counters.h" 11 #include "src/flags.h" 12 #include "src/macro-assembler.h" 13 #include "src/objects-inl.h" 14 #include "src/ostreams.h" 16 #include "src/wasm/decoder.h" 17 #include "src/wasm/function-body-decoder-impl.h" 18 #include "src/wasm/wasm-engine.h" 19 #include "src/wasm/wasm-limits.h" 27 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ 32 constexpr
char kNameString[] =
"name";
33 constexpr
char kSourceMappingURLString[] =
"sourceMappingURL";
34 constexpr
char kExceptionString[] =
"exception";
35 constexpr
char kUnknownString[] =
"<unknown>";
38 constexpr
size_t num_chars(
const char (&)[N]) {
42 const char* ExternalKindName(ImportExportKindCode kind) {
44 case kExternalFunction:
52 case kExternalException:
60 const char* SectionName(SectionCode code) {
62 case kUnknownSectionCode:
64 case kTypeSectionCode:
66 case kImportSectionCode:
68 case kFunctionSectionCode:
70 case kTableSectionCode:
72 case kMemorySectionCode:
74 case kGlobalSectionCode:
76 case kExportSectionCode:
78 case kStartSectionCode:
80 case kCodeSectionCode:
82 case kElementSectionCode:
84 case kDataSectionCode:
86 case kNameSectionCode:
88 case kSourceMappingURLSectionCode:
89 return kSourceMappingURLString;
90 case kExceptionSectionCode:
91 return kExceptionString;
93 return kUnknownString;
99 bool validate_utf8(Decoder* decoder, WireBytesRef
string) {
100 return unibrow::Utf8::ValidateEncoding(
101 decoder->start() + decoder->GetBufferRelativeOffset(
string.offset()),
105 ValueType TypeOf(
const WasmModule* module,
const WasmInitExpr& expr) {
107 case WasmInitExpr::kNone:
109 case WasmInitExpr::kGlobalIndex:
110 return expr.val.global_index < module->globals.size()
111 ? module->globals[expr.val.global_index].type
113 case WasmInitExpr::kI32Const:
115 case WasmInitExpr::kI64Const:
117 case WasmInitExpr::kF32Const:
119 case WasmInitExpr::kF64Const:
121 case WasmInitExpr::kAnyRefConst:
130 WireBytesRef consume_string(Decoder& decoder,
bool validate_utf8,
132 uint32_t length = decoder.consume_u32v(
"string length");
133 uint32_t offset = decoder.pc_offset();
134 const byte* string_start = decoder.pc();
137 decoder.consume_bytes(length, name);
138 if (decoder.ok() && validate_utf8 &&
139 !unibrow::Utf8::ValidateEncoding(string_start, length)) {
140 decoder.errorf(string_start,
"%s: no valid UTF-8 string", name);
143 return {offset, decoder.failed() ? 0 : length};
148 class WasmSectionIterator {
150 explicit WasmSectionIterator(Decoder& decoder)
152 section_code_(kUnknownSectionCode),
153 section_start_(decoder.pc()),
154 section_end_(decoder.pc()) {
158 inline bool more()
const {
return decoder_.ok() && decoder_.more(); }
160 inline SectionCode section_code()
const {
return section_code_; }
162 inline const byte* section_start()
const {
return section_start_; }
164 inline uint32_t section_length()
const {
165 return static_cast<uint32_t>(section_end_ - section_start_);
168 inline Vector<const uint8_t> payload()
const {
169 return {payload_start_, payload_length()};
172 inline const byte* payload_start()
const {
return payload_start_; }
174 inline uint32_t payload_length()
const {
175 return static_cast<uint32_t>(section_end_ - payload_start_);
178 inline const byte* section_end()
const {
return section_end_; }
182 void advance(
bool move_to_section_end =
false) {
183 if (move_to_section_end && decoder_.pc() < section_end_) {
184 decoder_.consume_bytes(
185 static_cast<uint32_t>(section_end_ - decoder_.pc()));
187 if (decoder_.pc() != section_end_) {
188 const char* msg = decoder_.pc() < section_end_ ?
"shorter" :
"longer";
189 decoder_.errorf(decoder_.pc(),
190 "section was %s than expected size " 191 "(%u bytes expected, %zu decoded)",
192 msg, section_length(),
193 static_cast<size_t>(decoder_.pc() - section_start_));
200 SectionCode section_code_;
201 const byte* section_start_;
202 const byte* payload_start_;
203 const byte* section_end_;
208 if (!decoder_.more()) {
209 section_code_ = kUnknownSectionCode;
212 section_start_ = decoder_.pc();
213 uint8_t section_code = decoder_.consume_u8(
"section code");
215 uint32_t section_length = decoder_.consume_u32v(
"section length");
217 payload_start_ = decoder_.pc();
218 if (decoder_.checkAvailable(section_length)) {
220 section_end_ = payload_start_ + section_length;
223 section_end_ = payload_start_;
226 if (section_code == kUnknownSectionCode) {
229 ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
232 payload_start_ = decoder_.pc();
233 }
else if (!IsValidSectionCode(section_code)) {
234 decoder_.errorf(decoder_.pc(),
"unknown section code #0x%02x",
236 section_code = kUnknownSectionCode;
238 section_code_ = decoder_.failed() ? kUnknownSectionCode
239 :
static_cast<SectionCode
>(section_code);
241 if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
244 decoder_.consume_bytes(remaining,
"section payload");
256 enabled_features_(enabled),
257 origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
260 const byte* module_end, ModuleOrigin origin)
261 :
Decoder(module_start, module_end),
262 enabled_features_(enabled),
263 origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
265 error(start_,
"end is less than start");
270 void onFirstError()
override {
276 if (FLAG_dump_wasm_module_path) {
277 path = FLAG_dump_wasm_module_path;
279 !base::OS::isDirectorySeparator(path[path.size() - 1])) {
280 path += base::OS::DirectorySeparator();
284 size_t hash = base::hash_range(module_bytes.start(), module_bytes.end());
286 SNPrintF(buf,
"%016zx.%s.wasm", hash, ok() ?
"ok" :
"failed");
287 std::string name(buf.start());
288 if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(),
"wb")) {
289 if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) !=
292 os <<
"Error while dumping wasm file" << std::endl;
300 SetCounters(counters);
302 new WasmModule(base::make_unique<Zone>(allocator,
"signatures")));
303 module_->initial_pages = 0;
304 module_->maximum_pages = 0;
305 module_->mem_export =
false;
306 module_->origin = origin_;
310 if (failed())
return;
311 Reset(bytes, offset);
313 const byte* pos = pc_;
314 uint32_t magic_word = consume_u32(
"wasm magic");
315 #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF 316 if (magic_word != kWasmMagic) {
318 "expected magic word %02x %02x %02x %02x, " 319 "found %02x %02x %02x %02x",
320 BYTES(kWasmMagic), BYTES(magic_word));
325 uint32_t magic_version = consume_u32(
"wasm version");
326 if (magic_version != kWasmVersion) {
328 "expected version %02x %02x %02x %02x, " 329 "found %02x %02x %02x %02x",
330 BYTES(kWasmVersion), BYTES(magic_version));
337 uint32_t offset,
bool verify_functions =
true) {
338 if (failed())
return;
339 Reset(bytes, offset);
340 TRACE(
"Section: %s\n", SectionName(section_code));
341 TRACE(
"Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()),
342 static_cast<const void*>(bytes.end()));
345 if (section_code < next_ordered_section_ &&
346 section_code < kFirstUnorderedSection) {
347 errorf(pc(),
"unexpected section: %s", SectionName(section_code));
351 switch (section_code) {
352 case kUnknownSectionCode:
354 case kExceptionSectionCode:
358 if (seen_unordered_sections_ & (1 << kExceptionSectionCode)) {
359 errorf(pc(),
"Multiple exception sections not allowed");
361 }
else if (next_ordered_section_ > kExportSectionCode) {
362 errorf(pc(),
"Exception section must appear before export section");
364 }
else if (next_ordered_section_ <= kImportSectionCode) {
365 next_ordered_section_ = kImportSectionCode + 1;
367 seen_unordered_sections_ |= 1 << kExceptionSectionCode;
369 case kSourceMappingURLSectionCode:
373 case kNameSectionCode:
379 next_ordered_section_ = section_code + 1;
383 switch (section_code) {
384 case kUnknownSectionCode:
386 case kTypeSectionCode:
389 case kImportSectionCode:
390 DecodeImportSection();
392 case kFunctionSectionCode:
393 DecodeFunctionSection();
395 case kTableSectionCode:
396 DecodeTableSection();
398 case kMemorySectionCode:
399 DecodeMemorySection();
401 case kGlobalSectionCode:
402 DecodeGlobalSection();
404 case kExportSectionCode:
405 DecodeExportSection();
407 case kStartSectionCode:
408 DecodeStartSection();
410 case kCodeSectionCode:
411 DecodeCodeSection(verify_functions);
413 case kElementSectionCode:
414 DecodeElementSection();
416 case kDataSectionCode:
419 case kNameSectionCode:
422 case kSourceMappingURLSectionCode:
423 DecodeSourceMappingURLSection();
425 case kExceptionSectionCode:
426 if (enabled_features_.eh) {
427 DecodeExceptionSection();
429 errorf(pc(),
"unexpected section: %s", SectionName(section_code));
433 errorf(pc(),
"unexpected section: %s", SectionName(section_code));
437 if (pc() != bytes.end()) {
438 const char* msg = pc() < bytes.end() ?
"shorter" :
"longer";
440 "section was %s than expected size " 441 "(%zu bytes expected, %zu decoded)",
442 msg, bytes.size(),
static_cast<size_t>(pc() - bytes.begin()));
446 void DecodeTypeSection() {
447 uint32_t signatures_count = consume_count(
"types count", kV8MaxWasmTypes);
448 module_->signatures.reserve(signatures_count);
449 for (
uint32_t i = 0; ok() &&
i < signatures_count; ++
i) {
450 TRACE(
"DecodeSignature[%d] module+%d\n",
i,
451 static_cast<int>(pc_ - start_));
452 FunctionSig* s = consume_sig(module_->signature_zone.get());
453 module_->signatures.push_back(s);
454 uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
455 module_->signature_ids.push_back(
id);
457 module_->signature_map.Freeze();
460 void DecodeImportSection() {
462 consume_count(
"imports count", kV8MaxWasmImports);
463 module_->import_table.reserve(import_table_count);
464 for (
uint32_t i = 0; ok() &&
i < import_table_count; ++
i) {
465 TRACE(
"DecodeImportTable[%d] module+%d\n",
i,
466 static_cast<int>(pc_ - start_));
468 module_->import_table.push_back({
474 WasmImport*
import = &module_->import_table.back();
475 const byte* pos = pc_;
476 import->module_name = consume_string(*
this,
true,
"module name");
477 import->field_name = consume_string(*
this,
true,
"field name");
479 static_cast<ImportExportKindCode
>(consume_u8(
"import kind"));
480 switch (import->kind) {
481 case kExternalFunction: {
483 import->index =
static_cast<uint32_t>(module_->functions.size());
484 module_->num_imported_functions++;
485 module_->functions.push_back({
nullptr,
492 function->sig_index =
493 consume_sig_index(module_.get(), &
function->sig);
496 case kExternalTable: {
498 if (!AddTable(module_.get()))
break;
499 import->index =
static_cast<uint32_t>(module_->tables.size());
500 module_->tables.emplace_back();
501 WasmTable* table = &module_->tables.back();
502 table->imported =
true;
503 ValueType
type = consume_reference_type();
504 if (!enabled_features_.anyref) {
505 if (
type != kWasmAnyFunc) {
506 error(pc_ - 1,
"invalid table type");
511 uint8_t flags = validate_table_flags(
"element count");
512 consume_resizable_limits(
513 "element count",
"elements", FLAG_wasm_max_table_size,
514 &table->initial_size, &table->has_maximum_size,
515 FLAG_wasm_max_table_size, &table->maximum_size, flags);
518 case kExternalMemory: {
520 if (!AddMemory(module_.get()))
break;
521 uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
522 consume_resizable_limits(
523 "memory",
"pages", kSpecMaxWasmMemoryPages,
524 &module_->initial_pages, &module_->has_maximum_pages,
525 kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
528 case kExternalGlobal: {
530 import->index =
static_cast<uint32_t>(module_->globals.size());
531 module_->globals.push_back(
533 WasmGlobal* global = &module_->globals.back();
534 global->type = consume_value_type();
535 global->mutability = consume_mutability();
536 if (global->mutability) {
537 if (enabled_features_.mut_global) {
538 module_->num_imported_mutable_globals++;
540 error(
"mutable globals cannot be imported");
545 case kExternalException: {
547 if (!enabled_features_.eh) {
548 errorf(pos,
"unknown import kind 0x%02x", import->kind);
551 import->index =
static_cast<uint32_t>(module_->exceptions.size());
553 consume_exception_attribute();
554 consume_exception_sig_index(module_.get(), &exception_sig);
555 module_->exceptions.emplace_back(exception_sig);
559 errorf(pos,
"unknown import kind 0x%02x", import->kind);
565 void DecodeFunctionSection() {
567 consume_count(
"functions count", kV8MaxWasmFunctions);
569 SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
570 counter->AddSample(static_cast<int>(functions_count));
571 DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
573 module_->num_imported_functions + functions_count;
574 module_->functions.reserve(total_function_count);
575 module_->num_declared_functions = functions_count;
578 module_->functions.push_back({
nullptr,
585 function->sig_index = consume_sig_index(module_.get(), &
function->sig);
588 DCHECK_EQ(module_->functions.size(), total_function_count);
591 void DecodeTableSection() {
594 uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
595 uint32_t table_count = consume_count(
"table count", max_count);
597 for (
uint32_t i = 0; ok() &&
i < table_count;
i++) {
598 if (!AddTable(module_.get()))
break;
599 module_->tables.emplace_back();
600 WasmTable* table = &module_->tables.back();
601 table->type = consume_reference_type();
602 uint8_t flags = validate_table_flags(
"table elements");
603 consume_resizable_limits(
604 "table elements",
"elements", FLAG_wasm_max_table_size,
605 &table->initial_size, &table->has_maximum_size,
606 FLAG_wasm_max_table_size, &table->maximum_size, flags);
610 void DecodeMemorySection() {
611 uint32_t memory_count = consume_count(
"memory count", kV8MaxWasmMemories);
613 for (
uint32_t i = 0; ok() &&
i < memory_count;
i++) {
614 if (!AddMemory(module_.get()))
break;
615 uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
616 consume_resizable_limits(
617 "memory",
"pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
618 &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
619 &module_->maximum_pages, flags);
623 void DecodeGlobalSection() {
624 uint32_t globals_count = consume_count(
"globals count", kV8MaxWasmGlobals);
626 module_->globals.reserve(imported_globals + globals_count);
627 for (
uint32_t i = 0; ok() &&
i < globals_count; ++
i) {
628 TRACE(
"DecodeGlobal[%d] module+%d\n",
i, static_cast<int>(pc_ - start_));
630 module_->globals.push_back(
632 WasmGlobal* global = &module_->globals.back();
633 DecodeGlobalInModule(module_.get(),
i + imported_globals, global);
635 if (ok()) CalculateGlobalOffsets(module_.get());
638 void DecodeExportSection() {
640 consume_count(
"exports count", kV8MaxWasmExports);
641 module_->export_table.reserve(export_table_count);
642 for (
uint32_t i = 0; ok() &&
i < export_table_count; ++
i) {
643 TRACE(
"DecodeExportTable[%d] module+%d\n",
i,
644 static_cast<int>(pc_ - start_));
646 module_->export_table.push_back({
651 WasmExport* exp = &module_->export_table.back();
653 exp->name = consume_string(*
this,
true,
"field name");
655 const byte* pos = pc();
656 exp->kind =
static_cast<ImportExportKindCode
>(consume_u8(
"export kind"));
658 case kExternalFunction: {
660 exp->index = consume_func_index(module_.get(), &func);
661 module_->num_exported_functions++;
662 if (func) func->exported =
true;
665 case kExternalTable: {
667 exp->index = consume_table_index(module_.get(), &table);
668 if (table) table->exported =
true;
671 case kExternalMemory: {
672 uint32_t index = consume_u32v(
"memory index");
675 if (!module_->has_memory || index != 0) {
676 error(
"invalid memory index != 0");
678 module_->mem_export =
true;
681 case kExternalGlobal: {
683 exp->index = consume_global_index(module_.get(), &global);
685 if (!enabled_features_.mut_global && global->mutability) {
686 error(
"mutable globals cannot be exported");
688 global->exported =
true;
692 case kExternalException: {
693 if (!enabled_features_.eh) {
694 errorf(pos,
"invalid export kind 0x%02x", exp->kind);
698 exp->index = consume_exception_index(module_.get(), &exception);
702 errorf(pos,
"invalid export kind 0x%02x", exp->kind);
707 if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
708 std::vector<WasmExport> sorted_exports(module_->export_table);
712 if (a.name.length() != b.name.length()) {
713 return a.name.length() < b.name.length();
715 const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
716 const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
717 return memcmp(left, right, a.name.length()) < 0;
719 std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
721 auto it = sorted_exports.begin();
723 for (
auto end = sorted_exports.end(); it != end; last = &*it++) {
724 DCHECK(!cmp_less(*it, *last));
725 if (!cmp_less(*last, *it)) {
726 const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
728 errorf(pc,
"Duplicate export name '%.*s' for %s %d and %s %d",
729 name.length(), name.start(), ExternalKindName(last->kind),
730 last->index, ExternalKindName(it->kind), it->index);
737 void DecodeStartSection() {
739 const byte* pos = pc_;
740 module_->start_function_index = consume_func_index(module_.get(), &func);
742 (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
743 error(pos,
"invalid start function: non-zero parameter or return count");
747 void DecodeElementSection() {
749 consume_count(
"element count", FLAG_wasm_max_table_size);
751 if (element_count > 0 && module_->tables.size() == 0) {
752 error(pc_,
"The element section requires a table");
754 for (
uint32_t i = 0; ok() &&
i < element_count; ++
i) {
755 const byte* pos = pc();
760 consume_segment_header(
"table index", &is_active, &table_index, &offset);
761 if (failed())
return;
764 if (table_index >= module_->tables.size()) {
765 errorf(pos,
"out of bounds table index %u", table_index);
768 if (module_->tables[table_index].type != kWasmAnyFunc) {
770 "Invalid element segment. Table %u is not of type AnyFunc",
777 consume_count(
"number of elements", kV8MaxWasmTableEntries);
779 module_->table_inits.emplace_back(table_index, offset);
781 module_->table_inits.emplace_back();
785 for (
uint32_t j = 0; j < num_elem; j++) {
787 uint32_t index = consume_func_index(module_.get(), &func);
788 DCHECK_IMPLIES(ok(), func !=
nullptr);
790 DCHECK_EQ(index, func->func_index);
791 init->entries.push_back(index);
796 void DecodeCodeSection(
bool verify_functions) {
798 uint32_t functions_count = consume_u32v(
"functions count");
799 CheckFunctionsCount(functions_count, pos);
800 for (
uint32_t i = 0; ok() &&
i < functions_count; ++
i) {
801 const byte* pos = pc();
802 uint32_t size = consume_u32v(
"body size");
803 if (size > kV8MaxWasmFunctionSize) {
804 errorf(pos,
"size %u > maximum function size %zu", size,
805 kV8MaxWasmFunctionSize);
809 consume_bytes(size,
"function body");
811 DecodeFunctionBody(
i, size, offset, verify_functions);
816 if (functions_count != module_->num_declared_functions) {
817 Reset(
nullptr,
nullptr, offset);
818 errorf(
nullptr,
"function body count %u mismatch (%u expected)",
819 functions_count, module_->num_declared_functions);
826 bool verify_functions) {
828 &module_->functions[index + module_->num_imported_functions];
829 function->code = {offset, length};
830 if (verify_functions) {
832 VerifyFunctionBody(module_->signature_zone->allocator(),
833 index + module_->num_imported_functions, bytes,
834 module_.get(),
function);
838 void DecodeDataSection() {
840 consume_count(
"data segments count", kV8MaxWasmDataSegments);
841 module_->data_segments.reserve(data_segments_count);
842 for (
uint32_t i = 0; ok() &&
i < data_segments_count; ++
i) {
843 const byte* pos = pc();
844 if (!module_->has_memory) {
845 error(
"cannot load data without memory");
848 TRACE(
"DecodeDataSegment[%d] module+%d\n",
i,
849 static_cast<int>(pc_ - start_));
854 consume_segment_header(
"memory index", &is_active, &memory_index,
858 if (is_active && memory_index != 0) {
859 errorf(pos,
"illegal memory index %u != 0", memory_index);
863 uint32_t source_length = consume_u32v(
"source size");
864 uint32_t source_offset = pc_offset();
867 module_->data_segments.emplace_back(dest_addr);
869 module_->data_segments.emplace_back();
874 consume_bytes(source_length,
"segment data");
877 segment->source = {source_offset, source_length};
881 void DecodeNameSection() {
884 if (!(seen_unordered_sections_ & (1 << kNameSectionCode))) {
885 seen_unordered_sections_ |= 1 << kNameSectionCode;
887 Decoder inner(start_, pc_, end_, buffer_offset_);
890 while (inner.ok() && inner.more()) {
891 uint8_t name_type = inner.consume_u8(
"name type");
892 if (name_type & 0x80) inner.error(
"name type if not varuint7");
894 uint32_t name_payload_len = inner.consume_u32v(
"name payload length");
895 if (!inner.checkAvailable(name_payload_len))
break;
899 if (name_type == NameSectionKindCode::kModule) {
900 WireBytesRef name = consume_string(inner,
false,
"module name");
901 if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
903 inner.consume_bytes(name_payload_len,
"name subsection payload");
908 consume_bytes(static_cast<uint32_t>(end_ - start_),
nullptr);
911 void DecodeSourceMappingURLSection() {
912 Decoder inner(start_, pc_, end_, buffer_offset_);
913 WireBytesRef url = wasm::consume_string(inner,
true,
"module name");
915 !(seen_unordered_sections_ & (1 << kSourceMappingURLSectionCode))) {
916 const byte* url_start =
917 inner.start() + inner.GetBufferRelativeOffset(url.offset());
918 module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
920 seen_unordered_sections_ |= 1 << kSourceMappingURLSectionCode;
922 consume_bytes(static_cast<uint32_t>(end_ - start_),
nullptr);
925 void DecodeExceptionSection() {
927 consume_count(
"exception count", kV8MaxWasmExceptions);
928 for (
uint32_t i = 0; ok() &&
i < exception_count; ++
i) {
929 TRACE(
"DecodeException[%d] module+%d\n",
i,
930 static_cast<int>(pc_ - start_));
932 consume_exception_attribute();
933 consume_exception_sig_index(module_.get(), &exception_sig);
934 module_->exceptions.emplace_back(exception_sig);
938 ModuleResult FinishDecoding(
bool verify_functions =
true) {
940 CalculateGlobalOffsets(module_.get());
943 if (verify_functions && result.ok() && intermediate_result_.failed()) {
945 result = ModuleResult::ErrorFrom(std::move(intermediate_result_));
952 bool verify_functions =
true) {
953 StartDecoding(counters, allocator);
958 return FinishDecoding(verify_functions);
962 Decoder decoder(start_ + offset, end_, offset);
964 WasmSectionIterator section_iter(decoder);
966 while (ok() && section_iter.more()) {
968 offset += section_iter.payload_start() - section_iter.section_start();
969 if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
970 DecodeSection(section_iter.section_code(), section_iter.payload(),
971 offset, verify_functions);
974 offset += section_iter.payload_length();
975 section_iter.advance(
true);
978 if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
980 if (decoder.failed()) {
981 return decoder.toResult<std::unique_ptr<WasmModule>>(
nullptr);
984 return FinishDecoding(verify_functions);
991 std::unique_ptr<WasmFunction>
function) {
993 function->sig = consume_sig(zone);
994 function->code = {off(pc_),
static_cast<uint32_t>(end_ - pc_)};
997 VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
1000 if (intermediate_result_.failed()) {
1001 return FunctionResult::ErrorFrom(std::move(intermediate_result_));
1011 return ok() ? result :
nullptr;
1016 return consume_init_expr(
nullptr, kWasmStmt);
1019 const std::shared_ptr<WasmModule>& shared_module()
const {
return module_; }
1022 DCHECK_NOT_NULL(counters_);
1026 void SetCounters(
Counters* counters) {
1027 DCHECK_NULL(counters_);
1028 counters_ = counters;
1033 std::shared_ptr<WasmModule> module_;
1036 uint8_t next_ordered_section_ = kFirstSectionInModule;
1040 static_assert(
sizeof(ModuleDecoderImpl::next_ordered_section_) ==
1041 sizeof(SectionCode),
1043 uint32_t seen_unordered_sections_ = 0;
1044 static_assert(kBitsPerByte *
1045 sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
1046 kLastKnownModuleSection,
1049 ModuleOrigin origin_;
1052 return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
1056 if (enabled_features_.anyref)
return true;
1057 if (module->tables.size() > 0) {
1058 error(
"At most one table is supported");
1066 if (module->has_memory) {
1067 error(
"At most one memory is supported");
1070 module->has_memory =
true;
1078 global->type = consume_value_type();
1079 global->mutability = consume_mutability();
1080 const byte* pos = pc();
1081 global->init = consume_init_expr(module, kWasmStmt);
1082 if (global->init.kind == WasmInitExpr::kGlobalIndex) {
1083 uint32_t other_index = global->init.val.global_index;
1084 if (other_index >= index) {
1086 "invalid global index in init expression, " 1087 "index %u, other_index %u",
1088 index, other_index);
1089 }
else if (module->globals[other_index].type != global->type) {
1091 "type mismatch in global initialization " 1092 "(from global #%u), expected %s, got %s",
1093 other_index, ValueTypes::TypeName(global->type),
1094 ValueTypes::TypeName(module->globals[other_index].type));
1097 if (global->type != TypeOf(module, global->init)) {
1098 errorf(pos,
"type error in global initialization, expected %s, got %s",
1099 ValueTypes::TypeName(global->type),
1100 ValueTypes::TypeName(TypeOf(module, global->init)));
1108 void CalculateGlobalOffsets(
WasmModule* module) {
1110 uint32_t num_imported_mutable_globals = 0;
1111 if (module->globals.size() == 0) {
1112 module->globals_buffer_size = 0;
1116 byte size = ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
1117 if (global.mutability && global.imported) {
1118 DCHECK(enabled_features_.mut_global);
1119 global.index = num_imported_mutable_globals++;
1121 offset = (offset + size - 1) & ~(size - 1);
1122 global.offset = offset;
1126 module->globals_buffer_size = offset;
1134 wire_bytes.GetNameOrNull(
function, module));
1135 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
1137 os <<
"Verifying wasm function " << func_name << std::endl;
1140 function->sig,
function->code.offset(),
1141 start_ + GetBufferRelativeOffset(function->code.offset()),
1142 start_ + GetBufferRelativeOffset(function->code.end_offset())};
1146 auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
1147 wasm_decode, function_time);
1151 result = VerifyWasmCode(allocator, enabled_features_, module,
1152 &unused_detected_features, body);
1157 if (result.failed() && intermediate_result_.ok()) {
1159 std::ostringstream error_msg;
1160 error_msg <<
"in function " << func_name <<
": " << result.error_msg();
1161 intermediate_result_ =
1162 VoidResult::Error(result.error_offset(), error_msg.str());
1167 const byte* pos = pc_;
1168 uint32_t sig_index = consume_u32v(
"signature index");
1169 if (sig_index >= module->signatures.size()) {
1170 errorf(pos,
"signature index %u out of bounds (%d signatures)", sig_index,
1171 static_cast<int>(module->signatures.size()));
1175 *sig = module->signatures[sig_index];
1180 const byte* pos = pc_;
1181 uint32_t sig_index = consume_sig_index(module, sig);
1182 if (*sig && (*sig)->return_count() != 0) {
1183 errorf(pos,
"exception signature %u has non-void return", sig_index);
1190 uint32_t consume_count(
const char* name,
size_t maximum) {
1191 const byte* p = pc_;
1192 uint32_t count = consume_u32v(name);
1193 if (count > maximum) {
1194 errorf(p,
"%s of %u exceeds internal limit of %zu", name, count, maximum);
1195 return static_cast<uint32_t>(maximum);
1201 return consume_index(
"function index", module->functions, func);
1205 return consume_index(
"global index", module->globals, global);
1209 return consume_index(
"table index", module->tables, table);
1213 return consume_index(
"exception index", module->exceptions, except);
1216 template <
typename T>
1217 uint32_t consume_index(
const char* name, std::vector<T>& vector,
T** ptr) {
1218 const byte* pos = pc_;
1219 uint32_t index = consume_u32v(name);
1220 if (index >= vector.size()) {
1221 errorf(pos,
"%s %u out of bounds (%d entr%s)", name, index,
1222 static_cast<int>(vector.size()), vector.size() == 1 ?
"y" :
"ies");
1226 *ptr = &vector[index];
1230 uint8_t validate_table_flags(
const char* name) {
1231 uint8_t flags = consume_u8(
"resizable limits flags");
1232 const byte* pos = pc();
1234 errorf(pos - 1,
"invalid %s limits flags", name);
1239 uint8_t validate_memory_flags(
bool* has_shared_memory) {
1240 uint8_t flags = consume_u8(
"resizable limits flags");
1241 const byte* pos = pc();
1242 *has_shared_memory =
false;
1243 if (enabled_features_.threads) {
1245 errorf(pos - 1,
"invalid memory limits flags");
1246 }
else if (flags == 3) {
1247 DCHECK_NOT_NULL(has_shared_memory);
1248 *has_shared_memory =
true;
1249 }
else if (flags == 2) {
1251 "memory limits flags should have maximum defined if shared is " 1256 errorf(pos - 1,
"invalid memory limits flags");
1262 void consume_resizable_limits(
const char* name,
const char* units,
1264 bool* has_max,
uint32_t max_maximum,
1265 uint32_t* maximum, uint8_t flags) {
1266 const byte* pos = pc();
1267 *initial = consume_u32v(
"initial size");
1269 if (*initial > max_initial) {
1271 "initial %s size (%u %s) is larger than implementation limit (%u)",
1272 name, *initial, units, max_initial);
1277 *maximum = consume_u32v(
"maximum size");
1278 if (*maximum > max_maximum) {
1281 "maximum %s size (%u %s) is larger than implementation limit (%u)",
1282 name, *maximum, units, max_maximum);
1284 if (*maximum < *initial) {
1285 errorf(pos,
"maximum %s size (%u %s) is less than initial (%u %s)",
1286 name, *maximum, units, *initial, units);
1290 *maximum = max_initial;
1294 bool expect_u8(
const char* name, uint8_t expected) {
1295 const byte* pos = pc();
1296 uint8_t value = consume_u8(name);
1297 if (value != expected) {
1298 errorf(pos,
"expected %s 0x%02x, got 0x%02x", name, expected, value);
1305 const byte* pos = pc();
1306 uint8_t opcode = consume_u8(
"opcode");
1310 case kExprGetGlobal: {
1312 if (module->globals.size() <= imm.index) {
1313 error(
"global index is out of bounds");
1314 expr.kind = WasmInitExpr::kNone;
1315 expr.val.i32_const = 0;
1318 WasmGlobal* global = &module->globals[imm.index];
1319 if (global->mutability || !global->imported) {
1321 "only immutable imported globals can be used in initializer " 1323 expr.kind = WasmInitExpr::kNone;
1324 expr.val.i32_const = 0;
1327 expr.kind = WasmInitExpr::kGlobalIndex;
1328 expr.val.global_index = imm.index;
1332 case kExprI32Const: {
1334 expr.kind = WasmInitExpr::kI32Const;
1335 expr.val.i32_const = imm.value;
1339 case kExprF32Const: {
1341 expr.kind = WasmInitExpr::kF32Const;
1342 expr.val.f32_const = imm.value;
1346 case kExprI64Const: {
1348 expr.kind = WasmInitExpr::kI64Const;
1349 expr.val.i64_const = imm.value;
1353 case kExprF64Const: {
1355 expr.kind = WasmInitExpr::kF64Const;
1356 expr.val.f64_const = imm.value;
1360 case kExprRefNull: {
1361 if (enabled_features_.anyref) {
1362 expr.kind = WasmInitExpr::kAnyRefConst;
1369 error(
"invalid opcode in initialization expression");
1370 expr.kind = WasmInitExpr::kNone;
1371 expr.val.i32_const = 0;
1374 consume_bytes(len,
"init code");
1375 if (!expect_u8(
"end opcode", kExprEnd)) {
1376 expr.kind = WasmInitExpr::kNone;
1378 if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
1379 errorf(pos,
"type error in init expression, expected %s, got %s",
1380 ValueTypes::TypeName(expected),
1381 ValueTypes::TypeName(TypeOf(module, expr)));
1387 bool consume_mutability() {
1388 byte val = consume_u8(
"mutability");
1389 if (val > 1) error(pc_ - 1,
"invalid mutability");
1394 ValueType consume_value_type() {
1395 byte val = consume_u8(
"value type");
1396 ValueTypeCode t =
static_cast<ValueTypeCode
>(val);
1407 if (origin_ == kWasmOrigin) {
1410 if (enabled_features_.simd)
return kWasmS128;
1413 if (enabled_features_.anyref)
return kWasmAnyFunc;
1416 if (enabled_features_.anyref)
return kWasmAnyRef;
1422 error(pc_ - 1,
"invalid local type");
1428 ValueType consume_reference_type() {
1429 byte val = consume_u8(
"reference type");
1430 ValueTypeCode t =
static_cast<ValueTypeCode
>(val);
1433 return kWasmAnyFunc;
1435 if (!enabled_features_.anyref) {
1437 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
1443 error(pc_ - 1,
"invalid reference type");
1448 if (!expect_u8(
"type form", kWasmFunctionTypeCode))
return nullptr;
1451 consume_count(
"param count", kV8MaxWasmFunctionParams);
1452 if (failed())
return nullptr;
1453 std::vector<ValueType> params;
1454 for (
uint32_t i = 0; ok() &&
i < param_count; ++
i) {
1455 ValueType param = consume_value_type();
1456 params.push_back(param);
1458 std::vector<ValueType> returns;
1460 const size_t max_return_count = enabled_features_.mv
1461 ? kV8MaxWasmFunctionMultiReturns
1462 : kV8MaxWasmFunctionReturns;
1463 uint32_t return_count = consume_count(
"return count", max_return_count);
1464 if (failed())
return nullptr;
1465 for (
uint32_t i = 0; ok() &&
i < return_count; ++
i) {
1466 ValueType ret = consume_value_type();
1467 returns.push_back(ret);
1470 if (failed())
return nullptr;
1473 ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
1475 for (
uint32_t i = 0;
i < return_count; ++
i) buffer[b++] = returns[
i];
1476 for (
uint32_t i = 0;
i < param_count; ++
i) buffer[b++] = params[
i];
1478 return new (zone)
FunctionSig(return_count, param_count, buffer);
1482 uint32_t consume_exception_attribute() {
1483 const byte* pos = pc_;
1484 uint32_t attribute = consume_u32v(
"exception attribute");
1485 if (attribute != kExceptionAttribute) {
1486 errorf(pos,
"exception attribute %u not supported", attribute);
1492 void consume_segment_header(
const char* name,
bool* is_active,
1494 const byte* pos = pc();
1498 if (enabled_features_.bulk_memory) {
1499 flags = consume_u32v(
"flags");
1500 if (failed())
return;
1502 flags = consume_u32v(name);
1503 if (failed())
return;
1506 errorf(pos,
"illegal %s %u != 0", name, flags);
1513 if (flags == SegmentFlags::kActiveNoIndex) {
1517 }
else if (flags == SegmentFlags::kPassive) {
1520 read_offset =
false;
1521 }
else if (flags == SegmentFlags::kActiveWithIndex) {
1526 errorf(pos,
"illegal flag value %u. Must be 0, 1, or 2", flags);
1531 *index = consume_u32v(name);
1537 *offset = consume_init_expr(module_.get(), kWasmI32);
1543 const byte* module_start,
const byte* module_end,
1544 bool verify_functions, ModuleOrigin origin,
1548 SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
1550 size_t size = module_end - module_start;
1551 CHECK_LE(module_start, module_end);
1552 if (size >= kV8MaxWasmModuleSize) {
1553 return ModuleResult::Error(0,
"size > maximum module size (%zu): %zu",
1554 kV8MaxWasmModuleSize, size);
1558 SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
1559 size_counter->AddSample(static_cast<int>(size));
1562 ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
1563 ModuleResult result =
1564 decoder.DecodeModule(counters, allocator, verify_functions);
1570 auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
1571 module_peak_memory_bytes);
1572 peak_counter->AddSample(
1573 static_cast<int>(result.value()->signature_zone->allocation_size()));
1578 ModuleDecoder::ModuleDecoder(
const WasmFeatures& enabled)
1579 : enabled_features_(enabled) {}
1581 ModuleDecoder::~ModuleDecoder() =
default;
1583 const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module()
const {
1584 return impl_->shared_module();
1587 void ModuleDecoder::StartDecoding(Counters* counters,
1588 AccountingAllocator* allocator,
1589 ModuleOrigin origin) {
1591 impl_.reset(
new ModuleDecoderImpl(enabled_features_, origin));
1592 impl_->StartDecoding(counters, allocator);
1595 void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
1597 impl_->DecodeModuleHeader(bytes, offset);
1600 void ModuleDecoder::DecodeSection(SectionCode section_code,
1601 Vector<const uint8_t> bytes,
uint32_t offset,
1602 bool verify_functions) {
1603 impl_->DecodeSection(section_code, bytes, offset, verify_functions);
1607 uint32_t offset,
bool verify_functions) {
1608 impl_->DecodeFunctionBody(index, length, offset, verify_functions);
1611 bool ModuleDecoder::CheckFunctionsCount(
uint32_t functions_count,
1613 return impl_->CheckFunctionsCount(functions_count, offset);
1616 ModuleResult ModuleDecoder::FinishDecoding(
bool verify_functions) {
1617 return impl_->FinishDecoding(verify_functions);
1620 SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
1622 WireBytesRef
string = consume_string(decoder,
true,
"section name");
1623 if (decoder.failed() || decoder.pc() > end) {
1624 return kUnknownSectionCode;
1626 const byte* section_name_start =
1627 decoder.start() + decoder.GetBufferRelativeOffset(
string.offset());
1629 TRACE(
" +%d section name : \"%.*s\"\n",
1630 static_cast<int>(section_name_start - decoder.start()),
1631 string.length() < 20 ?
string.length() : 20, section_name_start);
1633 if (
string.length() == num_chars(kNameString) &&
1634 strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
1635 num_chars(kNameString)) == 0) {
1636 return kNameSectionCode;
1637 }
else if (
string.length() == num_chars(kSourceMappingURLString) &&
1638 strncmp(reinterpret_cast<const char*>(section_name_start),
1639 kSourceMappingURLString,
1640 num_chars(kSourceMappingURLString)) == 0) {
1641 return kSourceMappingURLSectionCode;
1643 return kUnknownSectionCode;
1646 bool ModuleDecoder::ok() {
return impl_->ok(); }
1648 FunctionSig* DecodeWasmSignatureForTesting(
const WasmFeatures& enabled,
1649 Zone* zone,
const byte* start,
1651 ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1652 return decoder.DecodeFunctionSignature(zone, start);
1655 WasmInitExpr DecodeWasmInitExprForTesting(
const WasmFeatures& enabled,
1656 const byte* start,
const byte* end) {
1657 AccountingAllocator allocator;
1658 ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1659 return decoder.DecodeInitExpr(start);
1662 FunctionResult DecodeWasmFunctionForTesting(
1663 const WasmFeatures& enabled, Zone* zone,
const ModuleWireBytes& wire_bytes,
1664 const WasmModule* module,
const byte* function_start,
1665 const byte* function_end, Counters* counters) {
1666 size_t size = function_end - function_start;
1667 CHECK_LE(function_start, function_end);
1668 auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
1669 function_size_bytes);
1671 size_histogram->AddSample(static_cast<int>(size));
1672 if (size > kV8MaxWasmFunctionSize) {
1673 return FunctionResult::Error(0,
"size > maximum function size (%zu): %zu",
1674 kV8MaxWasmFunctionSize, size);
1676 ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
1677 decoder.SetCounters(counters);
1678 return decoder.DecodeSingleFunction(zone, wire_bytes, module,
1679 base::make_unique<WasmFunction>());
1682 AsmJsOffsetsResult DecodeAsmJsOffsets(
const byte* tables_start,
1683 const byte* tables_end) {
1686 Decoder decoder(tables_start, tables_end);
1687 uint32_t functions_count = decoder.consume_u32v(
"functions count");
1689 if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
1690 table.reserve(functions_count);
1693 for (
uint32_t i = 0;
i < functions_count && decoder.ok(); ++
i) {
1694 uint32_t size = decoder.consume_u32v(
"table size");
1696 table.emplace_back();
1699 if (!decoder.checkAvailable(size)) {
1700 decoder.error(
"illegal asm function offset table size");
1702 const byte* table_end = decoder.pc() + size;
1703 uint32_t locals_size = decoder.consume_u32v(
"locals size");
1704 int function_start_position = decoder.consume_u32v(
"function start pos");
1705 int last_byte_offset = locals_size;
1706 int last_asm_position = function_start_position;
1707 std::vector<AsmJsOffsetEntry> func_asm_offsets;
1708 func_asm_offsets.reserve(size / 4);
1710 func_asm_offsets.push_back(
1711 {0, function_start_position, function_start_position});
1712 while (decoder.ok() && decoder.pc() < table_end) {
1713 last_byte_offset += decoder.consume_u32v(
"byte offset delta");
1715 last_asm_position + decoder.consume_i32v(
"call position delta");
1716 int to_number_position =
1717 call_position + decoder.consume_i32v(
"to_number position delta");
1718 last_asm_position = to_number_position;
1719 func_asm_offsets.push_back(
1720 {last_byte_offset, call_position, to_number_position});
1722 if (decoder.pc() != table_end) {
1723 decoder.error(
"broken asm offset table");
1725 table.push_back(std::move(func_asm_offsets));
1727 if (decoder.more()) decoder.error(
"unexpected additional bytes");
1729 return decoder.toResult(std::move(table));
1732 std::vector<CustomSectionOffset> DecodeCustomSections(
const byte* start,
1734 Decoder decoder(start, end);
1735 decoder.consume_bytes(4,
"wasm magic");
1736 decoder.consume_bytes(4,
"wasm version");
1738 std::vector<CustomSectionOffset> result;
1740 while (decoder.more()) {
1741 byte section_code = decoder.consume_u8(
"section code");
1742 uint32_t section_length = decoder.consume_u32v(
"section length");
1743 uint32_t section_start = decoder.pc_offset();
1744 if (section_code != 0) {
1746 decoder.consume_bytes(section_length,
"section bytes");
1749 uint32_t name_length = decoder.consume_u32v(
"name length");
1750 uint32_t name_offset = decoder.pc_offset();
1751 decoder.consume_bytes(name_length,
"section name");
1752 uint32_t payload_offset = decoder.pc_offset();
1753 if (section_length < (payload_offset - section_start)) {
1754 decoder.error(
"invalid section length");
1757 uint32_t payload_length = section_length - (payload_offset - section_start);
1758 decoder.consume_bytes(payload_length);
1759 if (decoder.failed())
break;
1760 result.push_back({{section_start, section_length},
1761 {name_offset, name_length},
1762 {payload_offset, payload_length}});
1770 bool FindNameSection(Decoder& decoder) {
1771 static constexpr
int kModuleHeaderSize = 8;
1772 decoder.consume_bytes(kModuleHeaderSize,
"module header");
1774 WasmSectionIterator section_iter(decoder);
1776 while (decoder.ok() && section_iter.more() &&
1777 section_iter.section_code() != kNameSectionCode) {
1778 section_iter.advance(
true);
1780 if (!section_iter.more())
return false;
1783 decoder.Reset(section_iter.payload(), decoder.pc_offset());
1789 void DecodeFunctionNames(
const byte* module_start,
const byte* module_end,
1790 std::unordered_map<uint32_t, WireBytesRef>* names) {
1791 DCHECK_NOT_NULL(names);
1792 DCHECK(names->empty());
1794 Decoder decoder(module_start, module_end);
1795 if (!FindNameSection(decoder))
return;
1797 while (decoder.ok() && decoder.more()) {
1798 uint8_t name_type = decoder.consume_u8(
"name type");
1799 if (name_type & 0x80)
break;
1801 uint32_t name_payload_len = decoder.consume_u32v(
"name payload length");
1802 if (!decoder.checkAvailable(name_payload_len))
break;
1804 if (name_type != NameSectionKindCode::kFunction) {
1805 decoder.consume_bytes(name_payload_len,
"name subsection payload");
1808 uint32_t functions_count = decoder.consume_u32v(
"functions count");
1810 for (; decoder.ok() && functions_count > 0; --functions_count) {
1811 uint32_t function_index = decoder.consume_u32v(
"function index");
1812 WireBytesRef name = consume_string(decoder,
false,
"function name");
1817 if (decoder.ok() && validate_utf8(&decoder, name)) {
1818 names->insert(std::make_pair(function_index, name));
1824 void DecodeLocalNames(
const byte* module_start,
const byte* module_end,
1825 LocalNames* result) {
1826 DCHECK_NOT_NULL(result);
1827 DCHECK(result->names.empty());
1829 Decoder decoder(module_start, module_end);
1830 if (!FindNameSection(decoder))
return;
1832 while (decoder.ok() && decoder.more()) {
1833 uint8_t name_type = decoder.consume_u8(
"name type");
1834 if (name_type & 0x80)
break;
1836 uint32_t name_payload_len = decoder.consume_u32v(
"name payload length");
1837 if (!decoder.checkAvailable(name_payload_len))
break;
1839 if (name_type != NameSectionKindCode::kLocal) {
1840 decoder.consume_bytes(name_payload_len,
"name subsection payload");
1844 uint32_t local_names_count = decoder.consume_u32v(
"local names count");
1845 for (
uint32_t i = 0;
i < local_names_count; ++
i) {
1846 uint32_t func_index = decoder.consume_u32v(
"function index");
1847 if (func_index > kMaxInt)
continue;
1848 result->names.emplace_back(static_cast<int>(func_index));
1849 LocalNamesPerFunction& func_names = result->names.back();
1850 result->max_function_index =
1851 std::max(result->max_function_index, func_names.function_index);
1852 uint32_t num_names = decoder.consume_u32v(
"namings count");
1853 for (
uint32_t k = 0; k < num_names; ++k) {
1854 uint32_t local_index = decoder.consume_u32v(
"local index");
1855 WireBytesRef name = consume_string(decoder,
true,
"local name");
1856 if (!decoder.ok())
break;
1857 if (local_index > kMaxInt)
continue;
1858 func_names.max_local_index =
1859 std::max(func_names.max_local_index, static_cast<int>(local_index));
1860 func_names.names.emplace_back(static_cast<int>(local_index), name);