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