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/macro-assembler.h"
6#include "src/objects.h"
7#include "src/v8.h"
8
9#include "src/wasm/decoder.h"
10#include "src/wasm/module-decoder.h"
11
12namespace v8 {
13namespace internal {
14namespace wasm {
15
16#if DEBUG
17#define TRACE(...)                                    \
18  do {                                                \
19    if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
20  } while (false)
21#else
22#define TRACE(...)
23#endif
24
25
26// The main logic for decoding the bytes of a module.
27class ModuleDecoder : public Decoder {
28 public:
29  ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
30                bool asm_js)
31      : Decoder(module_start, module_end), module_zone(zone), asm_js_(asm_js) {
32    result_.start = start_;
33    if (limit_ < start_) {
34      error(start_, "end is less than start");
35      limit_ = start_;
36    }
37  }
38
39  virtual void onFirstError() {
40    pc_ = limit_;  // On error, terminate section decoding loop.
41  }
42
43  // Decodes an entire module.
44  ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
45    pc_ = start_;
46    module->module_start = start_;
47    module->module_end = limit_;
48    module->min_mem_size_log2 = 0;
49    module->max_mem_size_log2 = 0;
50    module->mem_export = false;
51    module->mem_external = false;
52    module->globals = new std::vector<WasmGlobal>();
53    module->signatures = new std::vector<FunctionSig*>();
54    module->functions = new std::vector<WasmFunction>();
55    module->data_segments = new std::vector<WasmDataSegment>();
56    module->function_table = new std::vector<uint16_t>();
57
58    bool sections[kMaxModuleSectionCode];
59    memset(sections, 0, sizeof(sections));
60
61    // Decode the module sections.
62    while (pc_ < limit_) {
63      TRACE("DecodeSection\n");
64      WasmSectionDeclCode section =
65          static_cast<WasmSectionDeclCode>(u8("section"));
66      // Each section should appear at most once.
67      if (section < kMaxModuleSectionCode) {
68        CheckForPreviousSection(sections, section, false);
69        sections[section] = true;
70      }
71
72      switch (section) {
73        case kDeclEnd:
74          // Terminate section decoding.
75          limit_ = pc_;
76          break;
77        case kDeclMemory:
78          module->min_mem_size_log2 = u8("min memory");
79          module->max_mem_size_log2 = u8("max memory");
80          module->mem_export = u8("export memory") != 0;
81          break;
82        case kDeclSignatures: {
83          int length;
84          uint32_t signatures_count = u32v(&length, "signatures count");
85          module->signatures->reserve(SafeReserve(signatures_count));
86          // Decode signatures.
87          for (uint32_t i = 0; i < signatures_count; i++) {
88            if (failed()) break;
89            TRACE("DecodeSignature[%d] module+%d\n", i,
90                  static_cast<int>(pc_ - start_));
91            FunctionSig* s = sig();  // read function sig.
92            module->signatures->push_back(s);
93          }
94          break;
95        }
96        case kDeclFunctions: {
97          // Functions require a signature table first.
98          CheckForPreviousSection(sections, kDeclSignatures, true);
99          int length;
100          uint32_t functions_count = u32v(&length, "functions count");
101          module->functions->reserve(SafeReserve(functions_count));
102          // Set up module environment for verification.
103          ModuleEnv menv;
104          menv.module = module;
105          menv.globals_area = 0;
106          menv.mem_start = 0;
107          menv.mem_end = 0;
108          menv.function_code = nullptr;
109          menv.asm_js = asm_js_;
110          // Decode functions.
111          for (uint32_t i = 0; i < functions_count; i++) {
112            if (failed()) break;
113            TRACE("DecodeFunction[%d] module+%d\n", i,
114                  static_cast<int>(pc_ - start_));
115
116            module->functions->push_back(
117                {nullptr, 0, 0, 0, 0, 0, 0, false, false});
118            WasmFunction* function = &module->functions->back();
119            DecodeFunctionInModule(module, function, false);
120          }
121          if (ok() && verify_functions) {
122            for (uint32_t i = 0; i < functions_count; i++) {
123              if (failed()) break;
124              WasmFunction* function = &module->functions->at(i);
125              if (!function->external) {
126                VerifyFunctionBody(i, &menv, function);
127                if (result_.failed())
128                  error(result_.error_pc, result_.error_msg.get());
129              }
130            }
131          }
132          break;
133        }
134        case kDeclGlobals: {
135          int length;
136          uint32_t globals_count = u32v(&length, "globals count");
137          module->globals->reserve(SafeReserve(globals_count));
138          // Decode globals.
139          for (uint32_t i = 0; i < globals_count; i++) {
140            if (failed()) break;
141            TRACE("DecodeGlobal[%d] module+%d\n", i,
142                  static_cast<int>(pc_ - start_));
143            module->globals->push_back({0, MachineType::Int32(), 0, false});
144            WasmGlobal* global = &module->globals->back();
145            DecodeGlobalInModule(global);
146          }
147          break;
148        }
149        case kDeclDataSegments: {
150          int length;
151          uint32_t data_segments_count = u32v(&length, "data segments count");
152          module->data_segments->reserve(SafeReserve(data_segments_count));
153          // Decode data segments.
154          for (uint32_t i = 0; i < data_segments_count; i++) {
155            if (failed()) break;
156            TRACE("DecodeDataSegment[%d] module+%d\n", i,
157                  static_cast<int>(pc_ - start_));
158            module->data_segments->push_back({0, 0, 0});
159            WasmDataSegment* segment = &module->data_segments->back();
160            DecodeDataSegmentInModule(segment);
161          }
162          break;
163        }
164        case kDeclFunctionTable: {
165          // An indirect function table requires functions first.
166          CheckForPreviousSection(sections, kDeclFunctions, true);
167          int length;
168          uint32_t function_table_count = u32v(&length, "function table count");
169          module->function_table->reserve(SafeReserve(function_table_count));
170          // Decode function table.
171          for (uint32_t i = 0; i < function_table_count; i++) {
172            if (failed()) break;
173            TRACE("DecodeFunctionTable[%d] module+%d\n", i,
174                  static_cast<int>(pc_ - start_));
175            uint16_t index = u16();
176            if (index >= module->functions->size()) {
177              error(pc_ - 2, "invalid function index");
178              break;
179            }
180            module->function_table->push_back(index);
181          }
182          break;
183        }
184        case kDeclWLL: {
185          // Reserved for experimentation by the Web Low-level Language project
186          // which is augmenting the binary encoding with source code meta
187          // information. This section does not affect the semantics of the code
188          // and can be ignored by the runtime. https://github.com/JSStats/wll
189          int length = 0;
190          uint32_t section_size = u32v(&length, "section size");
191          if (pc_ + section_size > limit_ || pc_ + section_size < pc_) {
192            error(pc_ - length, "invalid section size");
193            break;
194          }
195          pc_ += section_size;
196          break;
197        }
198        default:
199          error(pc_ - 1, nullptr, "unrecognized section 0x%02x", section);
200          break;
201      }
202    }
203
204    return toResult(module);
205  }
206
207  uint32_t SafeReserve(uint32_t count) {
208    // Avoid OOM by only reserving up to a certain size.
209    const uint32_t kMaxReserve = 20000;
210    return count < kMaxReserve ? count : kMaxReserve;
211  }
212
213  void CheckForPreviousSection(bool* sections, WasmSectionDeclCode section,
214                               bool present) {
215    if (section >= kMaxModuleSectionCode) return;
216    if (sections[section] == present) return;
217    const char* name = "";
218    switch (section) {
219      case kDeclMemory:
220        name = "memory";
221        break;
222      case kDeclSignatures:
223        name = "signatures";
224        break;
225      case kDeclFunctions:
226        name = "function declaration";
227        break;
228      case kDeclGlobals:
229        name = "global variable";
230        break;
231      case kDeclDataSegments:
232        name = "data segment";
233        break;
234      case kDeclFunctionTable:
235        name = "function table";
236        break;
237      default:
238        name = "";
239        break;
240    }
241    if (present) {
242      error(pc_ - 1, nullptr, "required %s section missing", name);
243    } else {
244      error(pc_ - 1, nullptr, "%s section already present", name);
245    }
246  }
247
248  // Decodes a single anonymous function starting at {start_}.
249  FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
250                                      WasmFunction* function) {
251    pc_ = start_;
252    function->sig = sig();                       // read signature
253    function->name_offset = 0;                   // ---- name
254    function->code_start_offset = off(pc_ + 8);  // ---- code start
255    function->code_end_offset = off(limit_);     // ---- code end
256    function->local_int32_count = u16();         // read u16
257    function->local_int64_count = u16();         // read u16
258    function->local_float32_count = u16();       // read u16
259    function->local_float64_count = u16();       // read u16
260    function->exported = false;                  // ---- exported
261    function->external = false;                  // ---- external
262
263    if (ok()) VerifyFunctionBody(0, module_env, function);
264
265    FunctionResult result;
266    result.CopyFrom(result_);  // Copy error code and location.
267    result.val = function;
268    return result;
269  }
270
271  // Decodes a single function signature at {start}.
272  FunctionSig* DecodeFunctionSignature(const byte* start) {
273    pc_ = start;
274    FunctionSig* result = sig();
275    return ok() ? result : nullptr;
276  }
277
278 private:
279  Zone* module_zone;
280  ModuleResult result_;
281  bool asm_js_;
282
283  uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
284
285  // Decodes a single global entry inside a module starting at {pc_}.
286  void DecodeGlobalInModule(WasmGlobal* global) {
287    global->name_offset = string("global name");
288    global->type = mem_type();
289    global->offset = 0;
290    global->exported = u8("exported") != 0;
291  }
292
293  // Decodes a single function entry inside a module starting at {pc_}.
294  void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
295                              bool verify_body = true) {
296    byte decl_bits = u8("function decl");
297
298    const byte* sigpos = pc_;
299    function->sig_index = u16("signature index");
300
301    if (function->sig_index >= module->signatures->size()) {
302      return error(sigpos, "invalid signature index");
303    } else {
304      function->sig = module->signatures->at(function->sig_index);
305    }
306
307    TRACE("  +%d  <function attributes:%s%s%s%s%s>\n",
308          static_cast<int>(pc_ - start_),
309          decl_bits & kDeclFunctionName ? " name" : "",
310          decl_bits & kDeclFunctionImport ? " imported" : "",
311          decl_bits & kDeclFunctionLocals ? " locals" : "",
312          decl_bits & kDeclFunctionExport ? " exported" : "",
313          (decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
314
315    if (decl_bits & kDeclFunctionName) {
316      function->name_offset = string("function name");
317    }
318
319    function->exported = decl_bits & kDeclFunctionExport;
320
321    // Imported functions have no locals or body.
322    if (decl_bits & kDeclFunctionImport) {
323      function->external = true;
324      return;
325    }
326
327    if (decl_bits & kDeclFunctionLocals) {
328      function->local_int32_count = u16("int32 count");
329      function->local_int64_count = u16("int64 count");
330      function->local_float32_count = u16("float32 count");
331      function->local_float64_count = u16("float64 count");
332    }
333
334    uint16_t size = u16("body size");
335    if (ok()) {
336      if ((pc_ + size) > limit_) {
337        return error(pc_, limit_,
338                     "expected %d bytes for function body, fell off end", size);
339      }
340      function->code_start_offset = static_cast<uint32_t>(pc_ - start_);
341      function->code_end_offset = function->code_start_offset + size;
342      TRACE("  +%d  %-20s: (%d bytes)\n", static_cast<int>(pc_ - start_),
343            "function body", size);
344      pc_ += size;
345    }
346  }
347
348  // Decodes a single data segment entry inside a module starting at {pc_}.
349  void DecodeDataSegmentInModule(WasmDataSegment* segment) {
350    segment->dest_addr =
351        u32("destination");  // TODO(titzer): check it's within the memory size.
352    segment->source_offset = offset("source offset");
353    segment->source_size =
354        u32("source size");  // TODO(titzer): check the size is reasonable.
355    segment->init = u8("init");
356  }
357
358  // Verifies the body (code) of a given function.
359  void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
360                          WasmFunction* function) {
361    if (FLAG_trace_wasm_decode_time) {
362      // TODO(titzer): clean me up a bit.
363      OFStream os(stdout);
364      os << "Verifying WASM function:";
365      if (function->name_offset > 0) {
366        os << menv->module->GetName(function->name_offset);
367      }
368      os << std::endl;
369    }
370    FunctionEnv fenv;
371    fenv.module = menv;
372    fenv.sig = function->sig;
373    fenv.local_int32_count = function->local_int32_count;
374    fenv.local_int64_count = function->local_int64_count;
375    fenv.local_float32_count = function->local_float32_count;
376    fenv.local_float64_count = function->local_float64_count;
377    fenv.SumLocals();
378
379    TreeResult result =
380        VerifyWasmCode(&fenv, start_, start_ + function->code_start_offset,
381                       start_ + function->code_end_offset);
382    if (result.failed()) {
383      // Wrap the error message from the function decoder.
384      std::ostringstream str;
385      str << "in function #" << func_num << ": ";
386      // TODO(titzer): add function name for the user?
387      str << result;
388      std::string strval = str.str();
389      const char* raw = strval.c_str();
390      size_t len = strlen(raw);
391      char* buffer = new char[len];
392      strncpy(buffer, raw, len);
393      buffer[len - 1] = 0;
394
395      // Copy error code and location.
396      result_.CopyFrom(result);
397      result_.error_msg.Reset(buffer);
398    }
399  }
400
401  // Reads a single 32-bit unsigned integer interpreted as an offset, checking
402  // the offset is within bounds and advances.
403  uint32_t offset(const char* name = nullptr) {
404    uint32_t offset = u32(name ? name : "offset");
405    if (offset > static_cast<uint32_t>(limit_ - start_)) {
406      error(pc_ - sizeof(uint32_t), "offset out of bounds of module");
407    }
408    return offset;
409  }
410
411  // Reads a single 32-bit unsigned integer interpreted as an offset into the
412  // data and validating the string there and advances.
413  uint32_t string(const char* name = nullptr) {
414    return offset(name ? name : "string");  // TODO(titzer): validate string
415  }
416
417  // Reads a single 8-bit integer, interpreting it as a local type.
418  LocalType local_type() {
419    byte val = u8("local type");
420    LocalTypeCode t = static_cast<LocalTypeCode>(val);
421    switch (t) {
422      case kLocalVoid:
423        return kAstStmt;
424      case kLocalI32:
425        return kAstI32;
426      case kLocalI64:
427        return kAstI64;
428      case kLocalF32:
429        return kAstF32;
430      case kLocalF64:
431        return kAstF64;
432      default:
433        error(pc_ - 1, "invalid local type");
434        return kAstStmt;
435    }
436  }
437
438  // Reads a single 8-bit integer, interpreting it as a memory type.
439  MachineType mem_type() {
440    byte val = u8("memory type");
441    MemTypeCode t = static_cast<MemTypeCode>(val);
442    switch (t) {
443      case kMemI8:
444        return MachineType::Int8();
445      case kMemU8:
446        return MachineType::Uint8();
447      case kMemI16:
448        return MachineType::Int16();
449      case kMemU16:
450        return MachineType::Uint16();
451      case kMemI32:
452        return MachineType::Int32();
453      case kMemU32:
454        return MachineType::Uint32();
455      case kMemI64:
456        return MachineType::Int64();
457      case kMemU64:
458        return MachineType::Uint64();
459      case kMemF32:
460        return MachineType::Float32();
461      case kMemF64:
462        return MachineType::Float64();
463      default:
464        error(pc_ - 1, "invalid memory type");
465        return MachineType::None();
466    }
467  }
468
469  // Parses an inline function signature.
470  FunctionSig* sig() {
471    byte count = u8("param count");
472    LocalType ret = local_type();
473    FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
474    if (ret != kAstStmt) builder.AddReturn(ret);
475
476    for (int i = 0; i < count; i++) {
477      LocalType param = local_type();
478      if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
479      builder.AddParam(param);
480    }
481    return builder.Build();
482  }
483};
484
485
486// Helpers for nice error messages.
487class ModuleError : public ModuleResult {
488 public:
489  explicit ModuleError(const char* msg) {
490    error_code = kError;
491    size_t len = strlen(msg) + 1;
492    char* result = new char[len];
493    strncpy(result, msg, len);
494    result[len - 1] = 0;
495    error_msg.Reset(result);
496  }
497};
498
499
500// Helpers for nice error messages.
501class FunctionError : public FunctionResult {
502 public:
503  explicit FunctionError(const char* msg) {
504    error_code = kError;
505    size_t len = strlen(msg) + 1;
506    char* result = new char[len];
507    strncpy(result, msg, len);
508    result[len - 1] = 0;
509    error_msg.Reset(result);
510  }
511};
512
513
514ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
515                              const byte* module_start, const byte* module_end,
516                              bool verify_functions, bool asm_js) {
517  size_t size = module_end - module_start;
518  if (module_start > module_end) return ModuleError("start > end");
519  if (size >= kMaxModuleSize) return ModuleError("size > maximum module size");
520  WasmModule* module = new WasmModule();
521  ModuleDecoder decoder(zone, module_start, module_end, asm_js);
522  return decoder.DecodeModule(module, verify_functions);
523}
524
525
526FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
527                                           const byte* end) {
528  ModuleDecoder decoder(zone, start, end, false);
529  return decoder.DecodeFunctionSignature(start);
530}
531
532
533FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
534                                  ModuleEnv* module_env,
535                                  const byte* function_start,
536                                  const byte* function_end) {
537  size_t size = function_end - function_start;
538  if (function_start > function_end) return FunctionError("start > end");
539  if (size > kMaxFunctionSize)
540    return FunctionError("size > maximum function size");
541  WasmFunction* function = new WasmFunction();
542  ModuleDecoder decoder(zone, function_start, function_end, false);
543  return decoder.DecodeSingleFunction(module_env, function);
544}
545}  // namespace wasm
546}  // namespace internal
547}  // namespace v8
548