blob: 62b000da2bfd8b3d5df0b2c612a027ffe0a64946 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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>();
Ben Murdoch097c5b22016-05-18 11:27:45 +010057 module->import_table = new std::vector<WasmImport>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058
59 bool sections[kMaxModuleSectionCode];
60 memset(sections, 0, sizeof(sections));
61
62 // Decode the module sections.
63 while (pc_ < limit_) {
64 TRACE("DecodeSection\n");
65 WasmSectionDeclCode section =
Ben Murdoch097c5b22016-05-18 11:27:45 +010066 static_cast<WasmSectionDeclCode>(consume_u8("section"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 // Each section should appear at most once.
68 if (section < kMaxModuleSectionCode) {
69 CheckForPreviousSection(sections, section, false);
70 sections[section] = true;
71 }
72
73 switch (section) {
74 case kDeclEnd:
75 // Terminate section decoding.
76 limit_ = pc_;
77 break;
78 case kDeclMemory:
Ben Murdoch097c5b22016-05-18 11:27:45 +010079 module->min_mem_size_log2 = consume_u8("min memory");
80 module->max_mem_size_log2 = consume_u8("max memory");
81 module->mem_export = consume_u8("export memory") != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 break;
83 case kDeclSignatures: {
84 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010085 uint32_t signatures_count = consume_u32v(&length, "signatures count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 module->signatures->reserve(SafeReserve(signatures_count));
87 // Decode signatures.
88 for (uint32_t i = 0; i < signatures_count; i++) {
89 if (failed()) break;
90 TRACE("DecodeSignature[%d] module+%d\n", i,
91 static_cast<int>(pc_ - start_));
Ben Murdoch097c5b22016-05-18 11:27:45 +010092 FunctionSig* s = consume_sig(); // read function sig.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 module->signatures->push_back(s);
94 }
95 break;
96 }
97 case kDeclFunctions: {
98 // Functions require a signature table first.
99 CheckForPreviousSection(sections, kDeclSignatures, true);
100 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100101 uint32_t functions_count = consume_u32v(&length, "functions count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 module->functions->reserve(SafeReserve(functions_count));
103 // Set up module environment for verification.
104 ModuleEnv menv;
105 menv.module = module;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100106 menv.instance = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 menv.asm_js = asm_js_;
108 // Decode functions.
109 for (uint32_t i = 0; i < functions_count; i++) {
110 if (failed()) break;
111 TRACE("DecodeFunction[%d] module+%d\n", i,
112 static_cast<int>(pc_ - start_));
113
114 module->functions->push_back(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100115 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 WasmFunction* function = &module->functions->back();
117 DecodeFunctionInModule(module, function, false);
118 }
119 if (ok() && verify_functions) {
120 for (uint32_t i = 0; i < functions_count; i++) {
121 if (failed()) break;
122 WasmFunction* function = &module->functions->at(i);
123 if (!function->external) {
124 VerifyFunctionBody(i, &menv, function);
125 if (result_.failed())
126 error(result_.error_pc, result_.error_msg.get());
127 }
128 }
129 }
130 break;
131 }
132 case kDeclGlobals: {
133 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100134 uint32_t globals_count = consume_u32v(&length, "globals count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 module->globals->reserve(SafeReserve(globals_count));
136 // Decode globals.
137 for (uint32_t i = 0; i < globals_count; i++) {
138 if (failed()) break;
139 TRACE("DecodeGlobal[%d] module+%d\n", i,
140 static_cast<int>(pc_ - start_));
141 module->globals->push_back({0, MachineType::Int32(), 0, false});
142 WasmGlobal* global = &module->globals->back();
143 DecodeGlobalInModule(global);
144 }
145 break;
146 }
147 case kDeclDataSegments: {
148 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 uint32_t data_segments_count =
150 consume_u32v(&length, "data segments count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 module->data_segments->reserve(SafeReserve(data_segments_count));
152 // Decode data segments.
153 for (uint32_t i = 0; i < data_segments_count; i++) {
154 if (failed()) break;
155 TRACE("DecodeDataSegment[%d] module+%d\n", i,
156 static_cast<int>(pc_ - start_));
157 module->data_segments->push_back({0, 0, 0});
158 WasmDataSegment* segment = &module->data_segments->back();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100159 DecodeDataSegmentInModule(module, segment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 }
161 break;
162 }
163 case kDeclFunctionTable: {
164 // An indirect function table requires functions first.
165 CheckForPreviousSection(sections, kDeclFunctions, true);
166 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100167 uint32_t function_table_count =
168 consume_u32v(&length, "function table count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 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_));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100175 uint16_t index = consume_u16();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 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 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100184 case kDeclStartFunction: {
185 // Declares a start function for a module.
186 CheckForPreviousSection(sections, kDeclFunctions, true);
187 if (module->start_function_index >= 0) {
188 error("start function already declared");
189 break;
190 }
191 int length;
192 const byte* before = pc_;
193 uint32_t index = consume_u32v(&length, "start function index");
194 if (index >= module->functions->size()) {
195 error(before, "invalid start function index");
196 break;
197 }
198 module->start_function_index = static_cast<int>(index);
199 FunctionSig* sig =
200 module->signatures->at(module->functions->at(index).sig_index);
201 if (sig->parameter_count() > 0) {
202 error(before, "invalid start function: non-zero parameter count");
203 break;
204 }
205 break;
206 }
207 case kDeclImportTable: {
208 // Declares an import table.
209 CheckForPreviousSection(sections, kDeclSignatures, true);
210 int length;
211 uint32_t import_table_count =
212 consume_u32v(&length, "import table count");
213 module->import_table->reserve(SafeReserve(import_table_count));
214 // Decode import table.
215 for (uint32_t i = 0; i < import_table_count; i++) {
216 if (failed()) break;
217 TRACE("DecodeImportTable[%d] module+%d\n", i,
218 static_cast<int>(pc_ - start_));
219
220 module->import_table->push_back({nullptr, 0, 0});
221 WasmImport* import = &module->import_table->back();
222
223 const byte* sigpos = pc_;
224 import->sig_index = consume_u16("signature index");
225
226 if (import->sig_index >= module->signatures->size()) {
227 error(sigpos, "invalid signature index");
228 } else {
229 import->sig = module->signatures->at(import->sig_index);
230 }
231 import->module_name_offset = consume_string("import module name");
232 import->function_name_offset =
233 consume_string("import function name");
234 }
235 break;
236 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 case kDeclWLL: {
238 // Reserved for experimentation by the Web Low-level Language project
239 // which is augmenting the binary encoding with source code meta
240 // information. This section does not affect the semantics of the code
241 // and can be ignored by the runtime. https://github.com/JSStats/wll
242 int length = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100243 uint32_t section_size = consume_u32v(&length, "section size");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 if (pc_ + section_size > limit_ || pc_ + section_size < pc_) {
245 error(pc_ - length, "invalid section size");
246 break;
247 }
248 pc_ += section_size;
249 break;
250 }
251 default:
252 error(pc_ - 1, nullptr, "unrecognized section 0x%02x", section);
253 break;
254 }
255 }
256
257 return toResult(module);
258 }
259
260 uint32_t SafeReserve(uint32_t count) {
261 // Avoid OOM by only reserving up to a certain size.
262 const uint32_t kMaxReserve = 20000;
263 return count < kMaxReserve ? count : kMaxReserve;
264 }
265
266 void CheckForPreviousSection(bool* sections, WasmSectionDeclCode section,
267 bool present) {
268 if (section >= kMaxModuleSectionCode) return;
269 if (sections[section] == present) return;
270 const char* name = "";
271 switch (section) {
272 case kDeclMemory:
273 name = "memory";
274 break;
275 case kDeclSignatures:
276 name = "signatures";
277 break;
278 case kDeclFunctions:
279 name = "function declaration";
280 break;
281 case kDeclGlobals:
282 name = "global variable";
283 break;
284 case kDeclDataSegments:
285 name = "data segment";
286 break;
287 case kDeclFunctionTable:
288 name = "function table";
289 break;
290 default:
291 name = "";
292 break;
293 }
294 if (present) {
295 error(pc_ - 1, nullptr, "required %s section missing", name);
296 } else {
297 error(pc_ - 1, nullptr, "%s section already present", name);
298 }
299 }
300
301 // Decodes a single anonymous function starting at {start_}.
302 FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
303 WasmFunction* function) {
304 pc_ = start_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 function->sig = consume_sig(); // read signature
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 function->name_offset = 0; // ---- name
307 function->code_start_offset = off(pc_ + 8); // ---- code start
308 function->code_end_offset = off(limit_); // ---- code end
Ben Murdoch097c5b22016-05-18 11:27:45 +0100309 function->local_i32_count = consume_u16(); // read u16
310 function->local_i64_count = consume_u16(); // read u16
311 function->local_f32_count = consume_u16(); // read u16
312 function->local_f64_count = consume_u16(); // read u16
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 function->exported = false; // ---- exported
314 function->external = false; // ---- external
315
316 if (ok()) VerifyFunctionBody(0, module_env, function);
317
318 FunctionResult result;
319 result.CopyFrom(result_); // Copy error code and location.
320 result.val = function;
321 return result;
322 }
323
324 // Decodes a single function signature at {start}.
325 FunctionSig* DecodeFunctionSignature(const byte* start) {
326 pc_ = start;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100327 FunctionSig* result = consume_sig();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 return ok() ? result : nullptr;
329 }
330
331 private:
332 Zone* module_zone;
333 ModuleResult result_;
334 bool asm_js_;
335
336 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
337
338 // Decodes a single global entry inside a module starting at {pc_}.
339 void DecodeGlobalInModule(WasmGlobal* global) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340 global->name_offset = consume_string("global name");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 global->type = mem_type();
342 global->offset = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100343 global->exported = consume_u8("exported") != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 }
345
346 // Decodes a single function entry inside a module starting at {pc_}.
347 void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
348 bool verify_body = true) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100349 byte decl_bits = consume_u8("function decl");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350
351 const byte* sigpos = pc_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100352 function->sig_index = consume_u16("signature index");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353
354 if (function->sig_index >= module->signatures->size()) {
355 return error(sigpos, "invalid signature index");
356 } else {
357 function->sig = module->signatures->at(function->sig_index);
358 }
359
360 TRACE(" +%d <function attributes:%s%s%s%s%s>\n",
361 static_cast<int>(pc_ - start_),
362 decl_bits & kDeclFunctionName ? " name" : "",
363 decl_bits & kDeclFunctionImport ? " imported" : "",
364 decl_bits & kDeclFunctionLocals ? " locals" : "",
365 decl_bits & kDeclFunctionExport ? " exported" : "",
366 (decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
367
368 if (decl_bits & kDeclFunctionName) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100369 function->name_offset = consume_string("function name");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370 }
371
372 function->exported = decl_bits & kDeclFunctionExport;
373
374 // Imported functions have no locals or body.
375 if (decl_bits & kDeclFunctionImport) {
376 function->external = true;
377 return;
378 }
379
380 if (decl_bits & kDeclFunctionLocals) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100381 function->local_i32_count = consume_u16("i32 count");
382 function->local_i64_count = consume_u16("i64 count");
383 function->local_f32_count = consume_u16("f32 count");
384 function->local_f64_count = consume_u16("f64 count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 }
386
Ben Murdoch097c5b22016-05-18 11:27:45 +0100387 uint16_t size = consume_u16("body size");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 if (ok()) {
389 if ((pc_ + size) > limit_) {
390 return error(pc_, limit_,
391 "expected %d bytes for function body, fell off end", size);
392 }
393 function->code_start_offset = static_cast<uint32_t>(pc_ - start_);
394 function->code_end_offset = function->code_start_offset + size;
395 TRACE(" +%d %-20s: (%d bytes)\n", static_cast<int>(pc_ - start_),
396 "function body", size);
397 pc_ += size;
398 }
399 }
400
Ben Murdoch097c5b22016-05-18 11:27:45 +0100401 bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
402 if (offset > limit) return false;
403 if ((offset + size) < offset) return false; // overflow
404 return (offset + size) <= limit;
405 }
406
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 // Decodes a single data segment entry inside a module starting at {pc_}.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100408 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
409 segment->dest_addr = consume_u32("destination");
410 segment->source_offset = consume_offset("source offset");
411 segment->source_size = consume_u32("source size");
412 segment->init = consume_u8("init");
413
414 // Validate the data is in the module.
415 uint32_t module_limit = static_cast<uint32_t>(limit_ - start_);
416 if (!IsWithinLimit(module_limit, segment->source_offset,
417 segment->source_size)) {
418 error(pc_ - sizeof(uint32_t), "segment out of bounds of module");
419 }
420
421 // Validate that the segment will fit into the (minimum) memory.
422 uint32_t memory_limit =
423 1 << (module ? module->min_mem_size_log2 : WasmModule::kMaxMemSize);
424 if (!IsWithinLimit(memory_limit, segment->dest_addr,
425 segment->source_size)) {
426 error(pc_ - sizeof(uint32_t), "segment out of bounds of memory");
427 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428 }
429
430 // Verifies the body (code) of a given function.
431 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
432 WasmFunction* function) {
433 if (FLAG_trace_wasm_decode_time) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 OFStream os(stdout);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100435 os << "Verifying WASM function " << WasmFunctionName(function, menv)
436 << std::endl;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437 os << std::endl;
438 }
439 FunctionEnv fenv;
440 fenv.module = menv;
441 fenv.sig = function->sig;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100442 fenv.local_i32_count = function->local_i32_count;
443 fenv.local_i64_count = function->local_i64_count;
444 fenv.local_f32_count = function->local_f32_count;
445 fenv.local_f64_count = function->local_f64_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 fenv.SumLocals();
447
448 TreeResult result =
449 VerifyWasmCode(&fenv, start_, start_ + function->code_start_offset,
450 start_ + function->code_end_offset);
451 if (result.failed()) {
452 // Wrap the error message from the function decoder.
453 std::ostringstream str;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100454 str << "in function " << WasmFunctionName(function, menv) << ": ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 str << result;
456 std::string strval = str.str();
457 const char* raw = strval.c_str();
458 size_t len = strlen(raw);
459 char* buffer = new char[len];
460 strncpy(buffer, raw, len);
461 buffer[len - 1] = 0;
462
463 // Copy error code and location.
464 result_.CopyFrom(result);
465 result_.error_msg.Reset(buffer);
466 }
467 }
468
469 // Reads a single 32-bit unsigned integer interpreted as an offset, checking
470 // the offset is within bounds and advances.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100471 uint32_t consume_offset(const char* name = nullptr) {
472 uint32_t offset = consume_u32(name ? name : "offset");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 if (offset > static_cast<uint32_t>(limit_ - start_)) {
474 error(pc_ - sizeof(uint32_t), "offset out of bounds of module");
475 }
476 return offset;
477 }
478
479 // Reads a single 32-bit unsigned integer interpreted as an offset into the
480 // data and validating the string there and advances.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100481 uint32_t consume_string(const char* name = nullptr) {
482 // TODO(titzer): validate string
483 return consume_offset(name ? name : "string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 }
485
486 // Reads a single 8-bit integer, interpreting it as a local type.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100487 LocalType consume_local_type() {
488 byte val = consume_u8("local type");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 LocalTypeCode t = static_cast<LocalTypeCode>(val);
490 switch (t) {
491 case kLocalVoid:
492 return kAstStmt;
493 case kLocalI32:
494 return kAstI32;
495 case kLocalI64:
496 return kAstI64;
497 case kLocalF32:
498 return kAstF32;
499 case kLocalF64:
500 return kAstF64;
501 default:
502 error(pc_ - 1, "invalid local type");
503 return kAstStmt;
504 }
505 }
506
507 // Reads a single 8-bit integer, interpreting it as a memory type.
508 MachineType mem_type() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100509 byte val = consume_u8("memory type");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 MemTypeCode t = static_cast<MemTypeCode>(val);
511 switch (t) {
512 case kMemI8:
513 return MachineType::Int8();
514 case kMemU8:
515 return MachineType::Uint8();
516 case kMemI16:
517 return MachineType::Int16();
518 case kMemU16:
519 return MachineType::Uint16();
520 case kMemI32:
521 return MachineType::Int32();
522 case kMemU32:
523 return MachineType::Uint32();
524 case kMemI64:
525 return MachineType::Int64();
526 case kMemU64:
527 return MachineType::Uint64();
528 case kMemF32:
529 return MachineType::Float32();
530 case kMemF64:
531 return MachineType::Float64();
532 default:
533 error(pc_ - 1, "invalid memory type");
534 return MachineType::None();
535 }
536 }
537
538 // Parses an inline function signature.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100539 FunctionSig* consume_sig() {
540 byte count = consume_u8("param count");
541 LocalType ret = consume_local_type();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
543 if (ret != kAstStmt) builder.AddReturn(ret);
544
545 for (int i = 0; i < count; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100546 LocalType param = consume_local_type();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000547 if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
548 builder.AddParam(param);
549 }
550 return builder.Build();
551 }
552};
553
554
555// Helpers for nice error messages.
556class ModuleError : public ModuleResult {
557 public:
558 explicit ModuleError(const char* msg) {
559 error_code = kError;
560 size_t len = strlen(msg) + 1;
561 char* result = new char[len];
562 strncpy(result, msg, len);
563 result[len - 1] = 0;
564 error_msg.Reset(result);
565 }
566};
567
568
569// Helpers for nice error messages.
570class FunctionError : public FunctionResult {
571 public:
572 explicit FunctionError(const char* msg) {
573 error_code = kError;
574 size_t len = strlen(msg) + 1;
575 char* result = new char[len];
576 strncpy(result, msg, len);
577 result[len - 1] = 0;
578 error_msg.Reset(result);
579 }
580};
581
582
583ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
584 const byte* module_start, const byte* module_end,
585 bool verify_functions, bool asm_js) {
586 size_t size = module_end - module_start;
587 if (module_start > module_end) return ModuleError("start > end");
588 if (size >= kMaxModuleSize) return ModuleError("size > maximum module size");
589 WasmModule* module = new WasmModule();
590 ModuleDecoder decoder(zone, module_start, module_end, asm_js);
591 return decoder.DecodeModule(module, verify_functions);
592}
593
594
595FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
596 const byte* end) {
597 ModuleDecoder decoder(zone, start, end, false);
598 return decoder.DecodeFunctionSignature(start);
599}
600
601
602FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
603 ModuleEnv* module_env,
604 const byte* function_start,
605 const byte* function_end) {
606 size_t size = function_end - function_start;
607 if (function_start > function_end) return FunctionError("start > end");
608 if (size > kMaxFunctionSize)
609 return FunctionError("size > maximum function size");
610 WasmFunction* function = new WasmFunction();
611 ModuleDecoder decoder(zone, function_start, function_end, false);
612 return decoder.DecodeSingleFunction(module_env, function);
613}
614} // namespace wasm
615} // namespace internal
616} // namespace v8