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/flags.h"
10 #include "src/macro-assembler.h"
11 #include "src/objects.h"
12 #include "src/v8.h"
13 
14 #include "src/wasm/decoder.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace wasm {
19 
20 #if DEBUG
21 #define TRACE(...)                                    \
22   do {                                                \
23     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
24   } while (false)
25 #else
26 #define TRACE(...)
27 #endif
28 
29 namespace {
30 
31 const char* kNameString = "name";
32 const size_t kNameStringLength = 4;
33 
TypeOf(const WasmModule * module,const WasmInitExpr & expr)34 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
35   switch (expr.kind) {
36     case WasmInitExpr::kNone:
37       return kAstStmt;
38     case WasmInitExpr::kGlobalIndex:
39       return expr.val.global_index < module->globals.size()
40                  ? module->globals[expr.val.global_index].type
41                  : kAstStmt;
42     case WasmInitExpr::kI32Const:
43       return kAstI32;
44     case WasmInitExpr::kI64Const:
45       return kAstI64;
46     case WasmInitExpr::kF32Const:
47       return kAstF32;
48     case WasmInitExpr::kF64Const:
49       return kAstF64;
50     default:
51       UNREACHABLE();
52       return kAstStmt;
53   }
54 }
55 
56 // An iterator over the sections in a WASM binary module.
57 // Automatically skips all unknown sections.
58 class WasmSectionIterator {
59  public:
WasmSectionIterator(Decoder & decoder)60   explicit WasmSectionIterator(Decoder& decoder)
61       : decoder_(decoder),
62         section_code_(kUnknownSectionCode),
63         section_start_(decoder.pc()),
64         section_end_(decoder.pc()) {
65     next();
66   }
67 
more() const68   inline bool more() const {
69     return section_code_ != kUnknownSectionCode && decoder_.more();
70   }
71 
section_code() const72   inline WasmSectionCode section_code() const { return section_code_; }
73 
section_start() const74   inline const byte* section_start() const { return section_start_; }
75 
section_length() const76   inline uint32_t section_length() const {
77     return static_cast<uint32_t>(section_end_ - section_start_);
78   }
79 
payload_start() const80   inline const byte* payload_start() const { return payload_start_; }
81 
payload_length() const82   inline uint32_t payload_length() const {
83     return static_cast<uint32_t>(section_end_ - payload_start_);
84   }
85 
section_end() const86   inline const byte* section_end() const { return section_end_; }
87 
88   // Advances to the next section, checking that decoding the current section
89   // stopped at {section_end_}.
advance()90   void advance() {
91     if (decoder_.pc() != section_end_) {
92       const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
93       decoder_.error(decoder_.pc(), decoder_.pc(),
94                      "section was %s than expected size "
95                      "(%u bytes expected, %zu decoded)",
96                      msg, section_length(),
97                      static_cast<size_t>(decoder_.pc() - section_start_));
98     }
99     next();
100   }
101 
102  private:
103   Decoder& decoder_;
104   WasmSectionCode section_code_;
105   const byte* section_start_;
106   const byte* payload_start_;
107   const byte* section_end_;
108 
109   // Reads the section code/name at the current position and sets up
110   // the internal fields.
next()111   void next() {
112     while (true) {
113       if (!decoder_.more()) {
114         section_code_ = kUnknownSectionCode;
115         return;
116       }
117       uint8_t section_code = decoder_.consume_u8("section code");
118       // Read and check the section size.
119       uint32_t section_length = decoder_.consume_u32v("section length");
120       section_start_ = decoder_.pc();
121       payload_start_ = section_start_;
122       if (decoder_.checkAvailable(section_length)) {
123         // Get the limit of the section within the module.
124         section_end_ = section_start_ + section_length;
125       } else {
126         // The section would extend beyond the end of the module.
127         section_end_ = section_start_;
128       }
129 
130       if (section_code == kUnknownSectionCode) {
131         // Check for the known "name" section.
132         uint32_t string_length = decoder_.consume_u32v("section name length");
133         const byte* section_name_start = decoder_.pc();
134         decoder_.consume_bytes(string_length, "section name");
135         if (decoder_.failed() || decoder_.pc() > section_end_) {
136           TRACE("Section name of length %u couldn't be read\n", string_length);
137           section_code_ = kUnknownSectionCode;
138           return;
139         }
140         payload_start_ = decoder_.pc();
141 
142         TRACE("  +%d  section name        : \"%.*s\"\n",
143               static_cast<int>(section_name_start - decoder_.start()),
144               string_length < 20 ? string_length : 20, section_name_start);
145 
146         if (string_length == kNameStringLength &&
147             strncmp(reinterpret_cast<const char*>(section_name_start),
148                     kNameString, kNameStringLength) == 0) {
149           section_code = kNameSectionCode;
150         } else {
151           section_code = kUnknownSectionCode;
152         }
153       } else if (!IsValidSectionCode(section_code)) {
154         decoder_.error(decoder_.pc(), decoder_.pc(),
155                        "unknown section code #0x%02x", section_code);
156         section_code = kUnknownSectionCode;
157       }
158       section_code_ = static_cast<WasmSectionCode>(section_code);
159 
160       TRACE("Section: %s\n", SectionName(section_code_));
161       if (section_code_ == kUnknownSectionCode &&
162           section_end_ > decoder_.pc()) {
163         // skip to the end of the unknown section.
164         uint32_t remaining =
165             static_cast<uint32_t>(section_end_ - decoder_.pc());
166         decoder_.consume_bytes(remaining, "section payload");
167         // fall through and continue to the next section.
168       } else {
169         return;
170       }
171     }
172   }
173 };
174 
175 // The main logic for decoding the bytes of a module.
176 class ModuleDecoder : public Decoder {
177  public:
ModuleDecoder(Zone * zone,const byte * module_start,const byte * module_end,ModuleOrigin origin)178   ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
179                 ModuleOrigin origin)
180       : Decoder(module_start, module_end), module_zone(zone), origin_(origin) {
181     result_.start = start_;
182     if (limit_ < start_) {
183       error(start_, "end is less than start");
184       limit_ = start_;
185     }
186   }
187 
onFirstError()188   virtual void onFirstError() {
189     pc_ = limit_;  // On error, terminate section decoding loop.
190   }
191 
DumpModule(WasmModule * module,const ModuleResult & result)192   static void DumpModule(WasmModule* module, const ModuleResult& result) {
193     std::string path;
194     if (FLAG_dump_wasm_module_path) {
195       path = FLAG_dump_wasm_module_path;
196       if (path.size() &&
197           !base::OS::isDirectorySeparator(path[path.size() - 1])) {
198         path += base::OS::DirectorySeparator();
199       }
200     }
201     // File are named `HASH.{ok,failed}.wasm`.
202     size_t hash = base::hash_range(module->module_start, module->module_end);
203     char buf[32] = {'\0'};
204 #if V8_OS_WIN && _MSC_VER < 1900
205 #define snprintf sprintf_s
206 #endif
207     snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash,
208              result.ok() ? "ok" : "failed");
209     std::string name(buf);
210     if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
211       fwrite(module->module_start, module->module_end - module->module_start, 1,
212              wasm_file);
213       fclose(wasm_file);
214     }
215   }
216 
217   // Decodes an entire module.
DecodeModule(WasmModule * module,bool verify_functions=true)218   ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
219     pc_ = start_;
220     module->module_start = start_;
221     module->module_end = limit_;
222     module->min_mem_pages = 0;
223     module->max_mem_pages = 0;
224     module->mem_export = false;
225     module->origin = origin_;
226 
227     const byte* pos = pc_;
228     uint32_t magic_word = consume_u32("wasm magic");
229 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
230     if (magic_word != kWasmMagic) {
231       error(pos, pos,
232             "expected magic word %02x %02x %02x %02x, "
233             "found %02x %02x %02x %02x",
234             BYTES(kWasmMagic), BYTES(magic_word));
235     }
236 
237     pos = pc_;
238     {
239       uint32_t magic_version = consume_u32("wasm version");
240       if (magic_version != kWasmVersion) {
241         error(pos, pos,
242               "expected version %02x %02x %02x %02x, "
243               "found %02x %02x %02x %02x",
244               BYTES(kWasmVersion), BYTES(magic_version));
245       }
246     }
247 
248     WasmSectionIterator section_iter(*this);
249 
250     // ===== Type section ====================================================
251     if (section_iter.section_code() == kTypeSectionCode) {
252       uint32_t signatures_count = consume_u32v("signatures count");
253       module->signatures.reserve(SafeReserve(signatures_count));
254       for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
255         TRACE("DecodeSignature[%d] module+%d\n", i,
256               static_cast<int>(pc_ - start_));
257         FunctionSig* s = consume_sig();
258         module->signatures.push_back(s);
259       }
260       section_iter.advance();
261     }
262 
263     // ===== Import section ==================================================
264     if (section_iter.section_code() == kImportSectionCode) {
265       uint32_t import_table_count = consume_u32v("import table count");
266       module->import_table.reserve(SafeReserve(import_table_count));
267       for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
268         TRACE("DecodeImportTable[%d] module+%d\n", i,
269               static_cast<int>(pc_ - start_));
270 
271         module->import_table.push_back({
272             0,                  // module_name_length
273             0,                  // module_name_offset
274             0,                  // field_name_offset
275             0,                  // field_name_length
276             kExternalFunction,  // kind
277             0                   // index
278         });
279         WasmImport* import = &module->import_table.back();
280         const byte* pos = pc_;
281         import->module_name_offset =
282             consume_string(&import->module_name_length, true);
283         if (import->module_name_length == 0) {
284           error(pos, "import module name cannot be NULL");
285         }
286         import->field_name_offset =
287             consume_string(&import->field_name_length, true);
288 
289         import->kind = static_cast<WasmExternalKind>(consume_u8("import kind"));
290         switch (import->kind) {
291           case kExternalFunction: {
292             // ===== Imported function =======================================
293             import->index = static_cast<uint32_t>(module->functions.size());
294             module->num_imported_functions++;
295             module->functions.push_back({nullptr,        // sig
296                                          import->index,  // func_index
297                                          0,              // sig_index
298                                          0,              // name_offset
299                                          0,              // name_length
300                                          0,              // code_start_offset
301                                          0,              // code_end_offset
302                                          true,           // imported
303                                          false});        // exported
304             WasmFunction* function = &module->functions.back();
305             function->sig_index = consume_sig_index(module, &function->sig);
306             break;
307           }
308           case kExternalTable: {
309             // ===== Imported table ==========================================
310             import->index =
311                 static_cast<uint32_t>(module->function_tables.size());
312             module->function_tables.push_back({0, 0, false,
313                                                std::vector<int32_t>(), true,
314                                                false, SignatureMap()});
315             expect_u8("element type", kWasmAnyFunctionTypeForm);
316             WasmIndirectFunctionTable* table = &module->function_tables.back();
317             consume_resizable_limits(
318                 "element count", "elements", WasmModule::kV8MaxTableSize,
319                 &table->min_size, &table->has_max, WasmModule::kV8MaxTableSize,
320                 &table->max_size);
321             break;
322           }
323           case kExternalMemory: {
324             // ===== Imported memory =========================================
325             bool has_max = false;
326             consume_resizable_limits("memory", "pages", WasmModule::kV8MaxPages,
327                                      &module->min_mem_pages, &has_max,
328                                      WasmModule::kSpecMaxPages,
329                                      &module->max_mem_pages);
330             module->has_memory = true;
331             break;
332           }
333           case kExternalGlobal: {
334             // ===== Imported global =========================================
335             import->index = static_cast<uint32_t>(module->globals.size());
336             module->globals.push_back(
337                 {kAstStmt, false, WasmInitExpr(), 0, true, false});
338             WasmGlobal* global = &module->globals.back();
339             global->type = consume_value_type();
340             global->mutability = consume_u8("mutability") != 0;
341             if (global->mutability) {
342               error("mutable globals cannot be imported");
343             }
344             break;
345           }
346           default:
347             error(pos, pos, "unknown import kind 0x%02x", import->kind);
348             break;
349         }
350       }
351       section_iter.advance();
352     }
353 
354     // ===== Function section ================================================
355     if (section_iter.section_code() == kFunctionSectionCode) {
356       uint32_t functions_count = consume_u32v("functions count");
357       module->functions.reserve(SafeReserve(functions_count));
358       module->num_declared_functions = functions_count;
359       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
360         uint32_t func_index = static_cast<uint32_t>(module->functions.size());
361         module->functions.push_back({nullptr,     // sig
362                                      func_index,  // func_index
363                                      0,           // sig_index
364                                      0,           // name_offset
365                                      0,           // name_length
366                                      0,           // code_start_offset
367                                      0,           // code_end_offset
368                                      false,       // imported
369                                      false});     // exported
370         WasmFunction* function = &module->functions.back();
371         function->sig_index = consume_sig_index(module, &function->sig);
372       }
373       section_iter.advance();
374     }
375 
376     // ===== Table section ===================================================
377     if (section_iter.section_code() == kTableSectionCode) {
378       const byte* pos = pc_;
379       uint32_t table_count = consume_u32v("table count");
380       // Require at most one table for now.
381       if (table_count > 1) {
382         error(pos, pos, "invalid table count %d, maximum 1", table_count);
383       }
384       if (module->function_tables.size() < 1) {
385         module->function_tables.push_back({0, 0, false, std::vector<int32_t>(),
386                                            false, false, SignatureMap()});
387       }
388 
389       for (uint32_t i = 0; ok() && i < table_count; i++) {
390         WasmIndirectFunctionTable* table = &module->function_tables.back();
391         expect_u8("table type", kWasmAnyFunctionTypeForm);
392         consume_resizable_limits("table elements", "elements",
393                                  WasmModule::kV8MaxTableSize, &table->min_size,
394                                  &table->has_max, WasmModule::kV8MaxTableSize,
395                                  &table->max_size);
396       }
397       section_iter.advance();
398     }
399 
400     // ===== Memory section ==================================================
401     if (section_iter.section_code() == kMemorySectionCode) {
402       const byte* pos = pc_;
403       uint32_t memory_count = consume_u32v("memory count");
404       // Require at most one memory for now.
405       if (memory_count > 1) {
406         error(pos, pos, "invalid memory count %d, maximum 1", memory_count);
407       }
408 
409       for (uint32_t i = 0; ok() && i < memory_count; i++) {
410         bool has_max = false;
411         consume_resizable_limits(
412             "memory", "pages", WasmModule::kV8MaxPages, &module->min_mem_pages,
413             &has_max, WasmModule::kSpecMaxPages, &module->max_mem_pages);
414       }
415       module->has_memory = true;
416       section_iter.advance();
417     }
418 
419     // ===== Global section ==================================================
420     if (section_iter.section_code() == kGlobalSectionCode) {
421       uint32_t globals_count = consume_u32v("globals count");
422       uint32_t imported_globals = static_cast<uint32_t>(module->globals.size());
423       if (!IsWithinLimit(std::numeric_limits<int32_t>::max(), globals_count,
424                          imported_globals)) {
425         error(pos, pos, "too many imported+defined globals: %u + %u",
426               imported_globals, globals_count);
427       }
428       module->globals.reserve(SafeReserve(imported_globals + globals_count));
429       for (uint32_t i = 0; ok() && i < globals_count; ++i) {
430         TRACE("DecodeGlobal[%d] module+%d\n", i,
431               static_cast<int>(pc_ - start_));
432         // Add an uninitialized global and pass a pointer to it.
433         module->globals.push_back(
434             {kAstStmt, false, WasmInitExpr(), 0, false, false});
435         WasmGlobal* global = &module->globals.back();
436         DecodeGlobalInModule(module, i + imported_globals, global);
437       }
438       section_iter.advance();
439     }
440 
441     // ===== Export section ==================================================
442     if (section_iter.section_code() == kExportSectionCode) {
443       uint32_t export_table_count = consume_u32v("export table count");
444       module->export_table.reserve(SafeReserve(export_table_count));
445       for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
446         TRACE("DecodeExportTable[%d] module+%d\n", i,
447               static_cast<int>(pc_ - start_));
448 
449         module->export_table.push_back({
450             0,                  // name_length
451             0,                  // name_offset
452             kExternalFunction,  // kind
453             0                   // index
454         });
455         WasmExport* exp = &module->export_table.back();
456 
457         exp->name_offset = consume_string(&exp->name_length, true);
458         const byte* pos = pc();
459         exp->kind = static_cast<WasmExternalKind>(consume_u8("export kind"));
460         switch (exp->kind) {
461           case kExternalFunction: {
462             WasmFunction* func = nullptr;
463             exp->index = consume_func_index(module, &func);
464             module->num_exported_functions++;
465             if (func) func->exported = true;
466             break;
467           }
468           case kExternalTable: {
469             WasmIndirectFunctionTable* table = nullptr;
470             exp->index = consume_table_index(module, &table);
471             if (table) table->exported = true;
472             break;
473           }
474           case kExternalMemory: {
475             uint32_t index = consume_u32v("memory index");
476             if (index != 0) error("invalid memory index != 0");
477             module->mem_export = true;
478             break;
479           }
480           case kExternalGlobal: {
481             WasmGlobal* global = nullptr;
482             exp->index = consume_global_index(module, &global);
483             if (global) {
484               if (global->mutability) {
485                 error("mutable globals cannot be exported");
486               }
487               global->exported = true;
488             }
489             break;
490           }
491           default:
492             error(pos, pos, "invalid export kind 0x%02x", exp->kind);
493             break;
494         }
495       }
496       // Check for duplicate exports.
497       if (ok() && module->export_table.size() > 1) {
498         std::vector<WasmExport> sorted_exports(module->export_table);
499         const byte* base = start_;
500         auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
501           // Return true if a < b.
502           if (a.name_length != b.name_length) {
503             return a.name_length < b.name_length;
504           }
505           return memcmp(base + a.name_offset, base + b.name_offset,
506                         a.name_length) < 0;
507         };
508         std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
509                          cmp_less);
510         auto it = sorted_exports.begin();
511         WasmExport* last = &*it++;
512         for (auto end = sorted_exports.end(); it != end; last = &*it++) {
513           DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
514           if (!cmp_less(*last, *it)) {
515             const byte* pc = start_ + it->name_offset;
516             error(pc, pc,
517                   "Duplicate export name '%.*s' for functions %d and %d",
518                   it->name_length, pc, last->index, it->index);
519             break;
520           }
521         }
522       }
523       section_iter.advance();
524     }
525 
526     // ===== Start section ===================================================
527     if (section_iter.section_code() == kStartSectionCode) {
528       WasmFunction* func;
529       const byte* pos = pc_;
530       module->start_function_index = consume_func_index(module, &func);
531       if (func &&
532           (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
533         error(pos,
534               "invalid start function: non-zero parameter or return count");
535       }
536       section_iter.advance();
537     }
538 
539     // ===== Elements section ================================================
540     if (section_iter.section_code() == kElementSectionCode) {
541       uint32_t element_count = consume_u32v("element count");
542       for (uint32_t i = 0; ok() && i < element_count; ++i) {
543         const byte* pos = pc();
544         uint32_t table_index = consume_u32v("table index");
545         if (table_index != 0) {
546           error(pos, pos, "illegal table index %u != 0", table_index);
547         }
548         WasmIndirectFunctionTable* table = nullptr;
549         if (table_index >= module->function_tables.size()) {
550           error(pos, pos, "out of bounds table index %u", table_index);
551         } else {
552           table = &module->function_tables[table_index];
553         }
554         WasmInitExpr offset = consume_init_expr(module, kAstI32);
555         uint32_t num_elem = consume_u32v("number of elements");
556         std::vector<uint32_t> vector;
557         module->table_inits.push_back({table_index, offset, vector});
558         WasmTableInit* init = &module->table_inits.back();
559         init->entries.reserve(SafeReserve(num_elem));
560         for (uint32_t j = 0; ok() && j < num_elem; j++) {
561           WasmFunction* func = nullptr;
562           uint32_t index = consume_func_index(module, &func);
563           init->entries.push_back(index);
564           if (table && index < module->functions.size()) {
565             // Canonicalize signature indices during decoding.
566             // TODO(titzer): suboptimal, redundant when verifying only.
567             table->map.FindOrInsert(module->functions[index].sig);
568           }
569         }
570       }
571 
572       section_iter.advance();
573     }
574 
575     // ===== Code section ====================================================
576     if (section_iter.section_code() == kCodeSectionCode) {
577       const byte* pos = pc_;
578       uint32_t functions_count = consume_u32v("functions count");
579       if (functions_count != module->num_declared_functions) {
580         error(pos, pos, "function body count %u mismatch (%u expected)",
581               functions_count, module->num_declared_functions);
582       }
583       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
584         WasmFunction* function =
585             &module->functions[i + module->num_imported_functions];
586         uint32_t size = consume_u32v("body size");
587         function->code_start_offset = pc_offset();
588         function->code_end_offset = pc_offset() + size;
589         if (verify_functions) {
590           ModuleEnv module_env;
591           module_env.module = module;
592           module_env.origin = module->origin;
593 
594           VerifyFunctionBody(i + module->num_imported_functions, &module_env,
595                              function);
596         }
597         consume_bytes(size, "function body");
598       }
599       section_iter.advance();
600     }
601 
602     // ===== Data section ====================================================
603     if (section_iter.section_code() == kDataSectionCode) {
604       uint32_t data_segments_count = consume_u32v("data segments count");
605       module->data_segments.reserve(SafeReserve(data_segments_count));
606       for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
607         if (!module->has_memory) {
608           error("cannot load data without memory");
609           break;
610         }
611         TRACE("DecodeDataSegment[%d] module+%d\n", i,
612               static_cast<int>(pc_ - start_));
613         module->data_segments.push_back({
614             WasmInitExpr(),  // dest_addr
615             0,               // source_offset
616             0                // source_size
617         });
618         WasmDataSegment* segment = &module->data_segments.back();
619         DecodeDataSegmentInModule(module, segment);
620       }
621       section_iter.advance();
622     }
623 
624     // ===== Name section ====================================================
625     if (section_iter.section_code() == kNameSectionCode) {
626       uint32_t functions_count = consume_u32v("functions count");
627 
628       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
629         uint32_t function_name_length = 0;
630         uint32_t name_offset = consume_string(&function_name_length, false);
631         uint32_t func_index = i;
632         if (func_index < module->functions.size()) {
633           module->functions[func_index].name_offset = name_offset;
634           module->functions[func_index].name_length = function_name_length;
635         }
636 
637         uint32_t local_names_count = consume_u32v("local names count");
638         for (uint32_t j = 0; ok() && j < local_names_count; j++) {
639           skip_string();
640         }
641       }
642       section_iter.advance();
643     }
644 
645     // ===== Remaining sections ==============================================
646     if (section_iter.more() && ok()) {
647       error(pc(), pc(), "unexpected section: %s",
648             SectionName(section_iter.section_code()));
649     }
650 
651     if (ok()) {
652       CalculateGlobalOffsets(module);
653     }
654     const WasmModule* finished_module = module;
655     ModuleResult result = toResult(finished_module);
656     if (verify_functions && result.ok()) {
657       result.MoveFrom(result_);  // Copy error code and location.
658     }
659     if (FLAG_dump_wasm_module) DumpModule(module, result);
660     return result;
661   }
662 
SafeReserve(uint32_t count)663   uint32_t SafeReserve(uint32_t count) {
664     // Avoid OOM by only reserving up to a certain size.
665     const uint32_t kMaxReserve = 20000;
666     return count < kMaxReserve ? count : kMaxReserve;
667   }
668 
669   // Decodes a single anonymous function starting at {start_}.
DecodeSingleFunction(ModuleEnv * module_env,WasmFunction * function)670   FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
671                                       WasmFunction* function) {
672     pc_ = start_;
673     function->sig = consume_sig();            // read signature
674     function->name_offset = 0;                // ---- name
675     function->name_length = 0;                // ---- name length
676     function->code_start_offset = off(pc_);   // ---- code start
677     function->code_end_offset = off(limit_);  // ---- code end
678 
679     if (ok()) VerifyFunctionBody(0, module_env, function);
680 
681     FunctionResult result;
682     result.MoveFrom(result_);  // Copy error code and location.
683     result.val = function;
684     return result;
685   }
686 
687   // Decodes a single function signature at {start}.
DecodeFunctionSignature(const byte * start)688   FunctionSig* DecodeFunctionSignature(const byte* start) {
689     pc_ = start;
690     FunctionSig* result = consume_sig();
691     return ok() ? result : nullptr;
692   }
693 
DecodeInitExpr(const byte * start)694   WasmInitExpr DecodeInitExpr(const byte* start) {
695     pc_ = start;
696     return consume_init_expr(nullptr, kAstStmt);
697   }
698 
699  private:
700   Zone* module_zone;
701   ModuleResult result_;
702   ModuleOrigin origin_;
703 
off(const byte * ptr)704   uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
705 
706   // Decodes a single global entry inside a module starting at {pc_}.
DecodeGlobalInModule(WasmModule * module,uint32_t index,WasmGlobal * global)707   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
708                             WasmGlobal* global) {
709     global->type = consume_value_type();
710     global->mutability = consume_u8("mutability") != 0;
711     const byte* pos = pc();
712     global->init = consume_init_expr(module, kAstStmt);
713     switch (global->init.kind) {
714       case WasmInitExpr::kGlobalIndex: {
715         uint32_t other_index = global->init.val.global_index;
716         if (other_index >= index) {
717           error(pos, pos,
718                 "invalid global index in init expression, "
719                 "index %u, other_index %u",
720                 index, other_index);
721         } else if (module->globals[other_index].type != global->type) {
722           error(pos, pos,
723                 "type mismatch in global initialization "
724                 "(from global #%u), expected %s, got %s",
725                 other_index, WasmOpcodes::TypeName(global->type),
726                 WasmOpcodes::TypeName(module->globals[other_index].type));
727         }
728         break;
729       }
730       default:
731         if (global->type != TypeOf(module, global->init)) {
732           error(pos, pos,
733                 "type error in global initialization, expected %s, got %s",
734                 WasmOpcodes::TypeName(global->type),
735                 WasmOpcodes::TypeName(TypeOf(module, global->init)));
736         }
737     }
738   }
739 
IsWithinLimit(uint32_t limit,uint32_t offset,uint32_t size)740   bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
741     if (offset > limit) return false;
742     if ((offset + size) < offset) return false;  // overflow
743     return (offset + size) <= limit;
744   }
745 
746   // Decodes a single data segment entry inside a module starting at {pc_}.
DecodeDataSegmentInModule(WasmModule * module,WasmDataSegment * segment)747   void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
748     const byte* start = pc_;
749     expect_u8("linear memory index", 0);
750     segment->dest_addr = consume_init_expr(module, kAstI32);
751     segment->source_size = consume_u32v("source size");
752     segment->source_offset = static_cast<uint32_t>(pc_ - start_);
753 
754     // Validate the data is in the module.
755     uint32_t module_limit = static_cast<uint32_t>(limit_ - start_);
756     if (!IsWithinLimit(module_limit, segment->source_offset,
757                        segment->source_size)) {
758       error(start, "segment out of bounds of module");
759     }
760 
761     consume_bytes(segment->source_size, "segment data");
762   }
763 
764   // Calculate individual global offsets and total size of globals table.
CalculateGlobalOffsets(WasmModule * module)765   void CalculateGlobalOffsets(WasmModule* module) {
766     uint32_t offset = 0;
767     if (module->globals.size() == 0) {
768       module->globals_size = 0;
769       return;
770     }
771     for (WasmGlobal& global : module->globals) {
772       byte size =
773           WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type));
774       offset = (offset + size - 1) & ~(size - 1);  // align
775       global.offset = offset;
776       offset += size;
777     }
778     module->globals_size = offset;
779   }
780 
781   // Verifies the body (code) of a given function.
VerifyFunctionBody(uint32_t func_num,ModuleEnv * menv,WasmFunction * function)782   void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
783                           WasmFunction* function) {
784     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
785       OFStream os(stdout);
786       os << "Verifying WASM function " << WasmFunctionName(function, menv)
787          << std::endl;
788     }
789     FunctionBody body = {menv, function->sig, start_,
790                          start_ + function->code_start_offset,
791                          start_ + function->code_end_offset};
792     DecodeResult result = VerifyWasmCode(module_zone->allocator(), body);
793     if (result.failed()) {
794       // Wrap the error message from the function decoder.
795       std::ostringstream str;
796       str << "in function " << WasmFunctionName(function, menv) << ": ";
797       str << result;
798       std::string strval = str.str();
799       const char* raw = strval.c_str();
800       size_t len = strlen(raw);
801       char* buffer = new char[len];
802       strncpy(buffer, raw, len);
803       buffer[len - 1] = 0;
804 
805       // Copy error code and location.
806       result_.MoveFrom(result);
807       result_.error_msg.reset(buffer);
808     }
809   }
810 
811   // Reads a length-prefixed string, checking that it is within bounds. Returns
812   // the offset of the string, and the length as an out parameter.
consume_string(uint32_t * length,bool validate_utf8)813   uint32_t consume_string(uint32_t* length, bool validate_utf8) {
814     *length = consume_u32v("string length");
815     uint32_t offset = pc_offset();
816     const byte* string_start = pc_;
817     // Consume bytes before validation to guarantee that the string is not oob.
818     if (*length > 0) consume_bytes(*length, "string");
819     if (ok() && validate_utf8 &&
820         !unibrow::Utf8::Validate(string_start, *length)) {
821       error(string_start, "no valid UTF-8 string");
822     }
823     return offset;
824   }
825 
826   // Skips over a length-prefixed string, but checks that it is within bounds.
skip_string()827   void skip_string() {
828     uint32_t length = consume_u32v("string length");
829     consume_bytes(length, "string");
830   }
831 
consume_sig_index(WasmModule * module,FunctionSig ** sig)832   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
833     const byte* pos = pc_;
834     uint32_t sig_index = consume_u32v("signature index");
835     if (sig_index >= module->signatures.size()) {
836       error(pos, pos, "signature index %u out of bounds (%d signatures)",
837             sig_index, static_cast<int>(module->signatures.size()));
838       *sig = nullptr;
839       return 0;
840     }
841     *sig = module->signatures[sig_index];
842     return sig_index;
843   }
844 
consume_func_index(WasmModule * module,WasmFunction ** func)845   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
846     return consume_index("function index", module->functions, func);
847   }
848 
consume_global_index(WasmModule * module,WasmGlobal ** global)849   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
850     return consume_index("global index", module->globals, global);
851   }
852 
consume_table_index(WasmModule * module,WasmIndirectFunctionTable ** table)853   uint32_t consume_table_index(WasmModule* module,
854                                WasmIndirectFunctionTable** table) {
855     return consume_index("table index", module->function_tables, table);
856   }
857 
858   template <typename T>
consume_index(const char * name,std::vector<T> & vector,T ** ptr)859   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
860     const byte* pos = pc_;
861     uint32_t index = consume_u32v(name);
862     if (index >= vector.size()) {
863       error(pos, pos, "%s %u out of bounds (%d entries)", name, index,
864             static_cast<int>(vector.size()));
865       *ptr = nullptr;
866       return 0;
867     }
868     *ptr = &vector[index];
869     return index;
870   }
871 
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)872   void consume_resizable_limits(const char* name, const char* units,
873                                 uint32_t max_initial, uint32_t* initial,
874                                 bool* has_max, uint32_t max_maximum,
875                                 uint32_t* maximum) {
876     uint32_t flags = consume_u32v("resizable limits flags");
877     const byte* pos = pc();
878     *initial = consume_u32v("initial size");
879     *has_max = false;
880     if (*initial > max_initial) {
881       error(pos, pos,
882             "initial %s size (%u %s) is larger than implementation limit (%u)",
883             name, *initial, units, max_initial);
884     }
885     if (flags & 1) {
886       *has_max = true;
887       pos = pc();
888       *maximum = consume_u32v("maximum size");
889       if (*maximum > max_maximum) {
890         error(
891             pos, pos,
892             "maximum %s size (%u %s) is larger than implementation limit (%u)",
893             name, *maximum, units, max_maximum);
894       }
895       if (*maximum < *initial) {
896         error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)",
897               name, *maximum, units, *initial, units);
898       }
899     } else {
900       *has_max = false;
901       *maximum = max_initial;
902     }
903   }
904 
expect_u8(const char * name,uint8_t expected)905   bool expect_u8(const char* name, uint8_t expected) {
906     const byte* pos = pc();
907     uint8_t value = consume_u8(name);
908     if (value != expected) {
909       error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
910       return false;
911     }
912     return true;
913   }
914 
consume_init_expr(WasmModule * module,LocalType expected)915   WasmInitExpr consume_init_expr(WasmModule* module, LocalType expected) {
916     const byte* pos = pc();
917     uint8_t opcode = consume_u8("opcode");
918     WasmInitExpr expr;
919     unsigned len = 0;
920     switch (opcode) {
921       case kExprGetGlobal: {
922         GlobalIndexOperand operand(this, pc() - 1);
923         if (module->globals.size() <= operand.index) {
924           error("global index is out of bounds");
925           expr.kind = WasmInitExpr::kNone;
926           expr.val.i32_const = 0;
927           break;
928         }
929         WasmGlobal* global = &module->globals[operand.index];
930         if (global->mutability || !global->imported) {
931           error(
932               "only immutable imported globals can be used in initializer "
933               "expressions");
934           expr.kind = WasmInitExpr::kNone;
935           expr.val.i32_const = 0;
936           break;
937         }
938         expr.kind = WasmInitExpr::kGlobalIndex;
939         expr.val.global_index = operand.index;
940         len = operand.length;
941         break;
942       }
943       case kExprI32Const: {
944         ImmI32Operand operand(this, pc() - 1);
945         expr.kind = WasmInitExpr::kI32Const;
946         expr.val.i32_const = operand.value;
947         len = operand.length;
948         break;
949       }
950       case kExprF32Const: {
951         ImmF32Operand operand(this, pc() - 1);
952         expr.kind = WasmInitExpr::kF32Const;
953         expr.val.f32_const = operand.value;
954         len = operand.length;
955         break;
956       }
957       case kExprI64Const: {
958         ImmI64Operand operand(this, pc() - 1);
959         expr.kind = WasmInitExpr::kI64Const;
960         expr.val.i64_const = operand.value;
961         len = operand.length;
962         break;
963       }
964       case kExprF64Const: {
965         ImmF64Operand operand(this, pc() - 1);
966         expr.kind = WasmInitExpr::kF64Const;
967         expr.val.f64_const = operand.value;
968         len = operand.length;
969         break;
970       }
971       default: {
972         error("invalid opcode in initialization expression");
973         expr.kind = WasmInitExpr::kNone;
974         expr.val.i32_const = 0;
975       }
976     }
977     consume_bytes(len, "init code");
978     if (!expect_u8("end opcode", kExprEnd)) {
979       expr.kind = WasmInitExpr::kNone;
980     }
981     if (expected != kAstStmt && TypeOf(module, expr) != kAstI32) {
982       error(pos, pos, "type error in init expression, expected %s, got %s",
983             WasmOpcodes::TypeName(expected),
984             WasmOpcodes::TypeName(TypeOf(module, expr)));
985     }
986     return expr;
987   }
988 
989   // Reads a single 8-bit integer, interpreting it as a local type.
consume_value_type()990   LocalType consume_value_type() {
991     byte val = consume_u8("value type");
992     LocalTypeCode t = static_cast<LocalTypeCode>(val);
993     switch (t) {
994       case kLocalI32:
995         return kAstI32;
996       case kLocalI64:
997         return kAstI64;
998       case kLocalF32:
999         return kAstF32;
1000       case kLocalF64:
1001         return kAstF64;
1002       case kLocalS128:
1003         if (origin_ != kAsmJsOrigin && FLAG_wasm_simd_prototype) {
1004           return kAstS128;
1005         } else {
1006           error(pc_ - 1, "invalid local type");
1007           return kAstStmt;
1008         }
1009       default:
1010         error(pc_ - 1, "invalid local type");
1011         return kAstStmt;
1012     }
1013   }
1014 
1015   // Parses a type entry, which is currently limited to functions only.
consume_sig()1016   FunctionSig* consume_sig() {
1017     if (!expect_u8("type form", kWasmFunctionTypeForm)) return nullptr;
1018     // parse parameter types
1019     uint32_t param_count = consume_u32v("param count");
1020     std::vector<LocalType> params;
1021     for (uint32_t i = 0; ok() && i < param_count; ++i) {
1022       LocalType param = consume_value_type();
1023       params.push_back(param);
1024     }
1025 
1026     // parse return types
1027     const byte* pt = pc_;
1028     uint32_t return_count = consume_u32v("return count");
1029     if (return_count > kMaxReturnCount) {
1030       error(pt, pt, "return count of %u exceeds maximum of %u", return_count,
1031             kMaxReturnCount);
1032       return nullptr;
1033     }
1034     std::vector<LocalType> returns;
1035     for (uint32_t i = 0; ok() && i < return_count; ++i) {
1036       LocalType ret = consume_value_type();
1037       returns.push_back(ret);
1038     }
1039 
1040     if (failed()) {
1041       // Decoding failed, return void -> void
1042       return new (module_zone) FunctionSig(0, 0, nullptr);
1043     }
1044 
1045     // FunctionSig stores the return types first.
1046     LocalType* buffer =
1047         module_zone->NewArray<LocalType>(param_count + return_count);
1048     uint32_t b = 0;
1049     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
1050     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
1051 
1052     return new (module_zone) FunctionSig(return_count, param_count, buffer);
1053   }
1054 };
1055 
1056 // Helpers for nice error messages.
1057 class ModuleError : public ModuleResult {
1058  public:
ModuleError(const char * msg)1059   explicit ModuleError(const char* msg) {
1060     error_code = kError;
1061     size_t len = strlen(msg) + 1;
1062     char* result = new char[len];
1063     strncpy(result, msg, len);
1064     result[len - 1] = 0;
1065     error_msg.reset(result);
1066   }
1067 };
1068 
1069 // Helpers for nice error messages.
1070 class FunctionError : public FunctionResult {
1071  public:
FunctionError(const char * msg)1072   explicit FunctionError(const char* msg) {
1073     error_code = kError;
1074     size_t len = strlen(msg) + 1;
1075     char* result = new char[len];
1076     strncpy(result, msg, len);
1077     result[len - 1] = 0;
1078     error_msg.reset(result);
1079   }
1080 };
1081 
1082 // Find section with given section code. Return Vector of the payload, or null
1083 // Vector if section is not found or module bytes are invalid.
FindSection(const byte * module_start,const byte * module_end,WasmSectionCode code)1084 Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
1085                                WasmSectionCode code) {
1086   Decoder decoder(module_start, module_end);
1087 
1088   uint32_t magic_word = decoder.consume_u32("wasm magic");
1089   if (magic_word != kWasmMagic) decoder.error("wrong magic word");
1090 
1091   uint32_t magic_version = decoder.consume_u32("wasm version");
1092   if (magic_version != kWasmVersion) decoder.error("wrong wasm version");
1093 
1094   WasmSectionIterator section_iter(decoder);
1095   while (section_iter.more()) {
1096     if (section_iter.section_code() == code) {
1097       return Vector<const uint8_t>(section_iter.payload_start(),
1098                                    section_iter.payload_length());
1099     }
1100     decoder.consume_bytes(section_iter.payload_length(), "section payload");
1101     section_iter.advance();
1102   }
1103 
1104   return Vector<const uint8_t>();
1105 }
1106 
1107 }  // namespace
1108 
DecodeWasmModule(Isolate * isolate,const byte * module_start,const byte * module_end,bool verify_functions,ModuleOrigin origin)1109 ModuleResult DecodeWasmModule(Isolate* isolate, const byte* module_start,
1110                               const byte* module_end, bool verify_functions,
1111                               ModuleOrigin origin) {
1112   HistogramTimerScope wasm_decode_module_time_scope(
1113       isolate->counters()->wasm_decode_module_time());
1114   size_t size = module_end - module_start;
1115   if (module_start > module_end) return ModuleError("start > end");
1116   if (size >= kMaxModuleSize) return ModuleError("size > maximum module size");
1117   // TODO(bradnelson): Improve histogram handling of size_t.
1118   isolate->counters()->wasm_module_size_bytes()->AddSample(
1119       static_cast<int>(size));
1120   // Signatures are stored in zone memory, which have the same lifetime
1121   // as the {module}.
1122   Zone* zone = new Zone(isolate->allocator(), ZONE_NAME);
1123   WasmModule* module = new WasmModule(zone, module_start);
1124   ModuleDecoder decoder(zone, module_start, module_end, origin);
1125   ModuleResult result = decoder.DecodeModule(module, verify_functions);
1126   // TODO(bradnelson): Improve histogram handling of size_t.
1127   // TODO(titzer): this isn't accurate, since it doesn't count the data
1128   // allocated on the C++ heap.
1129   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
1130   isolate->counters()->wasm_decode_module_peak_memory_bytes()->AddSample(
1131       static_cast<int>(zone->allocation_size()));
1132   return result;
1133 }
1134 
DecodeWasmSignatureForTesting(Zone * zone,const byte * start,const byte * end)1135 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
1136                                            const byte* end) {
1137   ModuleDecoder decoder(zone, start, end, kWasmOrigin);
1138   return decoder.DecodeFunctionSignature(start);
1139 }
1140 
DecodeWasmInitExprForTesting(const byte * start,const byte * end)1141 WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) {
1142   AccountingAllocator allocator;
1143   Zone zone(&allocator, ZONE_NAME);
1144   ModuleDecoder decoder(&zone, start, end, kWasmOrigin);
1145   return decoder.DecodeInitExpr(start);
1146 }
1147 
DecodeWasmFunction(Isolate * isolate,Zone * zone,ModuleEnv * module_env,const byte * function_start,const byte * function_end)1148 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
1149                                   ModuleEnv* module_env,
1150                                   const byte* function_start,
1151                                   const byte* function_end) {
1152   HistogramTimerScope wasm_decode_function_time_scope(
1153       isolate->counters()->wasm_decode_function_time());
1154   size_t size = function_end - function_start;
1155   if (function_start > function_end) return FunctionError("start > end");
1156   if (size > kMaxFunctionSize)
1157     return FunctionError("size > maximum function size");
1158   isolate->counters()->wasm_function_size_bytes()->AddSample(
1159       static_cast<int>(size));
1160   WasmFunction* function = new WasmFunction();
1161   ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
1162   return decoder.DecodeSingleFunction(module_env, function);
1163 }
1164 
DecodeWasmFunctionOffsets(const byte * module_start,const byte * module_end)1165 FunctionOffsetsResult DecodeWasmFunctionOffsets(const byte* module_start,
1166                                                 const byte* module_end) {
1167   // Find and decode the code section.
1168   Vector<const byte> code_section =
1169       FindSection(module_start, module_end, kCodeSectionCode);
1170   Decoder decoder(code_section.start(), code_section.end());
1171   FunctionOffsets table;
1172   if (!code_section.start()) {
1173     decoder.error("no code section");
1174     return decoder.toResult(std::move(table));
1175   }
1176 
1177   uint32_t functions_count = decoder.consume_u32v("functions count");
1178   // Reserve space for the entries, taking care of invalid input.
1179   if (functions_count < static_cast<unsigned>(code_section.length()) / 2) {
1180     table.reserve(functions_count);
1181   }
1182 
1183   int section_offset = static_cast<int>(code_section.start() - module_start);
1184   DCHECK_LE(0, section_offset);
1185   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1186     uint32_t size = decoder.consume_u32v("body size");
1187     int offset = static_cast<int>(section_offset + decoder.pc_offset());
1188     table.push_back(std::make_pair(offset, static_cast<int>(size)));
1189     DCHECK(table.back().first >= 0 && table.back().second >= 0);
1190     decoder.consume_bytes(size);
1191   }
1192   if (decoder.more()) decoder.error("unexpected additional bytes");
1193 
1194   return decoder.toResult(std::move(table));
1195 }
1196 
DecodeAsmJsOffsets(const byte * tables_start,const byte * tables_end)1197 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
1198                                       const byte* tables_end) {
1199   AsmJsOffsets table;
1200 
1201   Decoder decoder(tables_start, tables_end);
1202   uint32_t functions_count = decoder.consume_u32v("functions count");
1203   // Reserve space for the entries, taking care of invalid input.
1204   if (functions_count < static_cast<unsigned>(tables_end - tables_start)) {
1205     table.reserve(functions_count);
1206   }
1207 
1208   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1209     uint32_t size = decoder.consume_u32v("table size");
1210     if (size == 0) {
1211       table.push_back(std::vector<std::pair<int, int>>());
1212       continue;
1213     }
1214     if (!decoder.checkAvailable(size)) {
1215       decoder.error("illegal asm function offset table size");
1216     }
1217     const byte* table_end = decoder.pc() + size;
1218     uint32_t locals_size = decoder.consume_u32("locals size");
1219     int last_byte_offset = locals_size;
1220     int last_asm_position = 0;
1221     std::vector<std::pair<int, int>> func_asm_offsets;
1222     func_asm_offsets.reserve(size / 4);  // conservative estimation
1223     while (decoder.ok() && decoder.pc() < table_end) {
1224       last_byte_offset += decoder.consume_u32v("byte offset delta");
1225       last_asm_position += decoder.consume_i32v("asm position delta");
1226       func_asm_offsets.push_back({last_byte_offset, last_asm_position});
1227     }
1228     if (decoder.pc() != table_end) {
1229       decoder.error("broken asm offset table");
1230     }
1231     table.push_back(std::move(func_asm_offsets));
1232   }
1233   if (decoder.more()) decoder.error("unexpected additional bytes");
1234 
1235   return decoder.toResult(std::move(table));
1236 }
1237 
1238 }  // namespace wasm
1239 }  // namespace internal
1240 }  // namespace v8
1241