blob: 3e85a1b53cefd2e8ebbecf75cfa9a18e94b3f14e [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
Ben Murdochda12d292016-06-02 14:46:10 +01005#include "src/wasm/module-decoder.h"
6
7#include "src/base/functional.h"
8#include "src/base/platform/platform.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/macro-assembler.h"
10#include "src/objects.h"
11#include "src/v8.h"
12
13#include "src/wasm/decoder.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014
15namespace v8 {
16namespace internal {
17namespace wasm {
18
19#if DEBUG
20#define TRACE(...) \
21 do { \
22 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
23 } while (false)
24#else
25#define TRACE(...)
26#endif
27
28
29// The main logic for decoding the bytes of a module.
30class ModuleDecoder : public Decoder {
31 public:
32 ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
Ben Murdochda12d292016-06-02 14:46:10 +010033 ModuleOrigin origin)
34 : Decoder(module_start, module_end), module_zone(zone), origin_(origin) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 result_.start = start_;
36 if (limit_ < start_) {
37 error(start_, "end is less than start");
38 limit_ = start_;
39 }
40 }
41
42 virtual void onFirstError() {
43 pc_ = limit_; // On error, terminate section decoding loop.
44 }
45
Ben Murdochda12d292016-06-02 14:46:10 +010046 static void DumpModule(WasmModule* module, ModuleResult result) {
47 std::string path;
48 if (FLAG_dump_wasm_module_path) {
49 path = FLAG_dump_wasm_module_path;
50 if (path.size() &&
51 !base::OS::isDirectorySeparator(path[path.size() - 1])) {
52 path += base::OS::DirectorySeparator();
53 }
54 }
55 // File are named `HASH.{ok,failed}.wasm`.
56 size_t hash = base::hash_range(module->module_start, module->module_end);
57 char buf[32] = {'\0'};
58#if V8_OS_WIN && _MSC_VER < 1900
59#define snprintf sprintf_s
60#endif
61 snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash,
62 result.ok() ? "ok" : "failed");
63 std::string name(buf);
64 if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
65 fwrite(module->module_start, module->module_end - module->module_start, 1,
66 wasm_file);
67 fclose(wasm_file);
68 }
69 }
70
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 // Decodes an entire module.
72 ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
73 pc_ = start_;
74 module->module_start = start_;
75 module->module_end = limit_;
Ben Murdochda12d292016-06-02 14:46:10 +010076 module->min_mem_pages = 0;
77 module->max_mem_pages = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 module->mem_export = false;
79 module->mem_external = false;
Ben Murdochda12d292016-06-02 14:46:10 +010080 module->origin = origin_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081
Ben Murdochda12d292016-06-02 14:46:10 +010082 bool sections[(size_t)WasmSection::Code::Max] = {false};
83
84 const byte* pos = pc_;
85 uint32_t magic_word = consume_u32("wasm magic");
86#define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
87 if (magic_word != kWasmMagic) {
88 error(pos, pos,
89 "expected magic word %02x %02x %02x %02x, "
90 "found %02x %02x %02x %02x",
91 BYTES(kWasmMagic), BYTES(magic_word));
92 goto done;
93 }
94
95 pos = pc_;
96 {
97 uint32_t magic_version = consume_u32("wasm version");
98 if (magic_version != kWasmVersion) {
99 error(pos, pos,
100 "expected version %02x %02x %02x %02x, "
101 "found %02x %02x %02x %02x",
102 BYTES(kWasmVersion), BYTES(magic_version));
103 goto done;
104 }
105 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106
107 // Decode the module sections.
108 while (pc_ < limit_) {
109 TRACE("DecodeSection\n");
Ben Murdochda12d292016-06-02 14:46:10 +0100110 pos = pc_;
111
112 int length;
113 uint32_t section_length = consume_u32v(&length, "section size");
114
115 int section_string_leb_length = 0;
116 uint32_t section_string_length = 0;
117 WasmSection::Code section = consume_section_name(
118 &section_string_leb_length, &section_string_length);
119 uint32_t string_and_leb_length =
120 section_string_leb_length + section_string_length;
121 if (string_and_leb_length > section_length) {
122 error(pos, pos,
123 "section string of size %u longer than total section bytes %u",
124 string_and_leb_length, section_length);
125 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 }
127
Ben Murdochda12d292016-06-02 14:46:10 +0100128 if (section == WasmSection::Code::Max) {
129 // Skip unknown section.
130 uint32_t skip = section_length - string_and_leb_length;
131 TRACE("skipping %u bytes from unknown section\n", skip);
132 consume_bytes(skip);
133 continue;
134 }
135
136 // Each section should appear at most once.
137 CheckForPreviousSection(sections, section, false);
138 sections[(size_t)section] = true;
139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 switch (section) {
Ben Murdochda12d292016-06-02 14:46:10 +0100141 case WasmSection::Code::End:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 // Terminate section decoding.
143 limit_ = pc_;
144 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100145 case WasmSection::Code::Memory:
146 int length;
147 module->min_mem_pages = consume_u32v(&length, "min memory");
148 module->max_mem_pages = consume_u32v(&length, "max memory");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 module->mem_export = consume_u8("export memory") != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100151 case WasmSection::Code::Signatures: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100153 uint32_t signatures_count = consume_u32v(&length, "signatures count");
Ben Murdochda12d292016-06-02 14:46:10 +0100154 module->signatures.reserve(SafeReserve(signatures_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 // Decode signatures.
156 for (uint32_t i = 0; i < signatures_count; i++) {
157 if (failed()) break;
158 TRACE("DecodeSignature[%d] module+%d\n", i,
159 static_cast<int>(pc_ - start_));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100160 FunctionSig* s = consume_sig(); // read function sig.
Ben Murdochda12d292016-06-02 14:46:10 +0100161 module->signatures.push_back(s);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 }
163 break;
164 }
Ben Murdochda12d292016-06-02 14:46:10 +0100165 case WasmSection::Code::FunctionSignatures: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 // Functions require a signature table first.
Ben Murdochda12d292016-06-02 14:46:10 +0100167 CheckForPreviousSection(sections, WasmSection::Code::Signatures,
168 true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100170 uint32_t functions_count = consume_u32v(&length, "functions count");
Ben Murdochda12d292016-06-02 14:46:10 +0100171 module->functions.reserve(SafeReserve(functions_count));
172 for (uint32_t i = 0; i < functions_count; i++) {
173 module->functions.push_back(
174 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
175 WasmFunction* function = &module->functions.back();
176 function->sig_index = consume_sig_index(module, &function->sig);
177 }
178 break;
179 }
180 case WasmSection::Code::FunctionBodies: {
181 // Function bodies should follow signatures.
182 CheckForPreviousSection(sections,
183 WasmSection::Code::FunctionSignatures, true);
184 int length;
185 const byte* pos = pc_;
186 uint32_t functions_count = consume_u32v(&length, "functions count");
187 if (functions_count != module->functions.size()) {
188 error(pos, pos, "function body count %u mismatch (%u expected)",
189 functions_count,
190 static_cast<uint32_t>(module->functions.size()));
191 break;
192 }
193 for (uint32_t i = 0; i < functions_count; i++) {
194 WasmFunction* function = &module->functions[i];
195 int length;
196 uint32_t size = consume_u32v(&length, "body size");
197 function->code_start_offset = pc_offset();
198 function->code_end_offset = pc_offset() + size;
199
200 TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body",
201 size);
202 pc_ += size;
203 if (pc_ > limit_) {
204 error(pc_, "function body extends beyond end of file");
205 }
206 }
207 break;
208 }
209 case WasmSection::Code::Functions: {
210 // Functions require a signature table first.
211 CheckForPreviousSection(sections, WasmSection::Code::Signatures,
212 true);
213 int length;
214 uint32_t functions_count = consume_u32v(&length, "functions count");
215 module->functions.reserve(SafeReserve(functions_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 // Set up module environment for verification.
217 ModuleEnv menv;
218 menv.module = module;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100219 menv.instance = nullptr;
Ben Murdochda12d292016-06-02 14:46:10 +0100220 menv.origin = origin_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 // Decode functions.
222 for (uint32_t i = 0; i < functions_count; i++) {
223 if (failed()) break;
224 TRACE("DecodeFunction[%d] module+%d\n", i,
225 static_cast<int>(pc_ - start_));
226
Ben Murdochda12d292016-06-02 14:46:10 +0100227 module->functions.push_back(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228 {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
Ben Murdochda12d292016-06-02 14:46:10 +0100229 WasmFunction* function = &module->functions.back();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 DecodeFunctionInModule(module, function, false);
231 }
232 if (ok() && verify_functions) {
233 for (uint32_t i = 0; i < functions_count; i++) {
234 if (failed()) break;
Ben Murdochda12d292016-06-02 14:46:10 +0100235 WasmFunction* function = &module->functions[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 if (!function->external) {
237 VerifyFunctionBody(i, &menv, function);
238 if (result_.failed())
239 error(result_.error_pc, result_.error_msg.get());
240 }
241 }
242 }
243 break;
244 }
Ben Murdochda12d292016-06-02 14:46:10 +0100245 case WasmSection::Code::Names: {
246 // Names correspond to functions.
247 CheckForPreviousSection(sections,
248 WasmSection::Code::FunctionSignatures, true);
249 int length;
250 const byte* pos = pc_;
251 uint32_t functions_count = consume_u32v(&length, "functions count");
252 if (functions_count != module->functions.size()) {
253 error(pos, pos, "function name count %u mismatch (%u expected)",
254 functions_count,
255 static_cast<uint32_t>(module->functions.size()));
256 break;
257 }
258
259 for (uint32_t i = 0; i < functions_count; i++) {
260 WasmFunction* function = &module->functions[i];
261 function->name_offset =
262 consume_string(&function->name_length, "function name");
263
264 uint32_t local_names_count =
265 consume_u32v(&length, "local names count");
266 for (uint32_t j = 0; j < local_names_count; j++) {
267 uint32_t unused = 0;
268 uint32_t offset = consume_string(&unused, "local name");
269 USE(unused);
270 USE(offset);
271 }
272 }
273 break;
274 }
275 case WasmSection::Code::Globals: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100277 uint32_t globals_count = consume_u32v(&length, "globals count");
Ben Murdochda12d292016-06-02 14:46:10 +0100278 module->globals.reserve(SafeReserve(globals_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 // Decode globals.
280 for (uint32_t i = 0; i < globals_count; i++) {
281 if (failed()) break;
282 TRACE("DecodeGlobal[%d] module+%d\n", i,
283 static_cast<int>(pc_ - start_));
Ben Murdochda12d292016-06-02 14:46:10 +0100284 module->globals.push_back({0, 0, MachineType::Int32(), 0, false});
285 WasmGlobal* global = &module->globals.back();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 DecodeGlobalInModule(global);
287 }
288 break;
289 }
Ben Murdochda12d292016-06-02 14:46:10 +0100290 case WasmSection::Code::DataSegments: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100292 uint32_t data_segments_count =
293 consume_u32v(&length, "data segments count");
Ben Murdochda12d292016-06-02 14:46:10 +0100294 module->data_segments.reserve(SafeReserve(data_segments_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 // Decode data segments.
296 for (uint32_t i = 0; i < data_segments_count; i++) {
297 if (failed()) break;
298 TRACE("DecodeDataSegment[%d] module+%d\n", i,
299 static_cast<int>(pc_ - start_));
Ben Murdochda12d292016-06-02 14:46:10 +0100300 module->data_segments.push_back({0, 0, 0});
301 WasmDataSegment* segment = &module->data_segments.back();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100302 DecodeDataSegmentInModule(module, segment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 }
304 break;
305 }
Ben Murdochda12d292016-06-02 14:46:10 +0100306 case WasmSection::Code::FunctionTable: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 // An indirect function table requires functions first.
Ben Murdochda12d292016-06-02 14:46:10 +0100308 CheckForFunctions(module, section);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 int length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100310 uint32_t function_table_count =
311 consume_u32v(&length, "function table count");
Ben Murdochda12d292016-06-02 14:46:10 +0100312 module->function_table.reserve(SafeReserve(function_table_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 // Decode function table.
314 for (uint32_t i = 0; i < function_table_count; i++) {
315 if (failed()) break;
316 TRACE("DecodeFunctionTable[%d] module+%d\n", i,
317 static_cast<int>(pc_ - start_));
Ben Murdochda12d292016-06-02 14:46:10 +0100318 uint16_t index = consume_u32v(&length);
319 if (index >= module->functions.size()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 error(pc_ - 2, "invalid function index");
321 break;
322 }
Ben Murdochda12d292016-06-02 14:46:10 +0100323 module->function_table.push_back(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 }
325 break;
326 }
Ben Murdochda12d292016-06-02 14:46:10 +0100327 case WasmSection::Code::StartFunction: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100328 // Declares a start function for a module.
Ben Murdochda12d292016-06-02 14:46:10 +0100329 CheckForFunctions(module, section);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100330 if (module->start_function_index >= 0) {
331 error("start function already declared");
332 break;
333 }
Ben Murdochda12d292016-06-02 14:46:10 +0100334 WasmFunction* func;
335 const byte* pos = pc_;
336 module->start_function_index = consume_func_index(module, &func);
337 if (func && func->sig->parameter_count() > 0) {
338 error(pos, "invalid start function: non-zero parameter count");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100339 break;
340 }
341 break;
342 }
Ben Murdochda12d292016-06-02 14:46:10 +0100343 case WasmSection::Code::ImportTable: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344 // Declares an import table.
Ben Murdochda12d292016-06-02 14:46:10 +0100345 CheckForPreviousSection(sections, WasmSection::Code::Signatures,
346 true);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100347 int length;
348 uint32_t import_table_count =
349 consume_u32v(&length, "import table count");
Ben Murdochda12d292016-06-02 14:46:10 +0100350 module->import_table.reserve(SafeReserve(import_table_count));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351 // Decode import table.
352 for (uint32_t i = 0; i < import_table_count; i++) {
353 if (failed()) break;
354 TRACE("DecodeImportTable[%d] module+%d\n", i,
355 static_cast<int>(pc_ - start_));
356
Ben Murdochda12d292016-06-02 14:46:10 +0100357 module->import_table.push_back({nullptr, 0, 0});
358 WasmImport* import = &module->import_table.back();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100359
Ben Murdochda12d292016-06-02 14:46:10 +0100360 import->sig_index = consume_sig_index(module, &import->sig);
361 const byte* pos = pc_;
362 import->module_name_offset = consume_string(
363 &import->module_name_length, "import module name");
364 if (import->module_name_length == 0) {
365 error(pos, "import module name cannot be NULL");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366 }
Ben Murdochda12d292016-06-02 14:46:10 +0100367 import->function_name_offset = consume_string(
368 &import->function_name_length, "import function name");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100369 }
370 break;
371 }
Ben Murdochda12d292016-06-02 14:46:10 +0100372 case WasmSection::Code::ExportTable: {
373 // Declares an export table.
374 CheckForFunctions(module, section);
375 int length;
376 uint32_t export_table_count =
377 consume_u32v(&length, "export table count");
378 module->export_table.reserve(SafeReserve(export_table_count));
379 // Decode export table.
380 for (uint32_t i = 0; i < export_table_count; i++) {
381 if (failed()) break;
382 TRACE("DecodeExportTable[%d] module+%d\n", i,
383 static_cast<int>(pc_ - start_));
384
385 module->export_table.push_back({0, 0});
386 WasmExport* exp = &module->export_table.back();
387
388 WasmFunction* func;
389 exp->func_index = consume_func_index(module, &func);
390 exp->name_offset = consume_string(&exp->name_length, "export name");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 break;
393 }
Ben Murdochda12d292016-06-02 14:46:10 +0100394 case WasmSection::Code::Max:
395 UNREACHABLE(); // Already skipped unknown sections.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 }
397 }
398
Ben Murdochda12d292016-06-02 14:46:10 +0100399 done:
400 ModuleResult result = toResult(module);
401 if (FLAG_dump_wasm_module) {
402 DumpModule(module, result);
403 }
404 return result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405 }
406
407 uint32_t SafeReserve(uint32_t count) {
408 // Avoid OOM by only reserving up to a certain size.
409 const uint32_t kMaxReserve = 20000;
410 return count < kMaxReserve ? count : kMaxReserve;
411 }
412
Ben Murdochda12d292016-06-02 14:46:10 +0100413 void CheckForFunctions(WasmModule* module, WasmSection::Code section) {
414 if (module->functions.size() == 0) {
415 error(pc_ - 1, nullptr, "functions must appear before section %s",
416 WasmSection::getName(section));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 }
Ben Murdochda12d292016-06-02 14:46:10 +0100418 }
419
420 void CheckForPreviousSection(bool* sections, WasmSection::Code section,
421 bool present) {
422 if (section >= WasmSection::Code::Max) return;
423 if (sections[(size_t)section] == present) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 if (present) {
Ben Murdochda12d292016-06-02 14:46:10 +0100425 error(pc_ - 1, nullptr, "required %s section missing",
426 WasmSection::getName(section));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100428 error(pc_ - 1, nullptr, "%s section already present",
429 WasmSection::getName(section));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 }
431 }
432
433 // Decodes a single anonymous function starting at {start_}.
434 FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
435 WasmFunction* function) {
436 pc_ = start_;
Ben Murdochda12d292016-06-02 14:46:10 +0100437 function->sig = consume_sig(); // read signature
438 function->name_offset = 0; // ---- name
439 function->name_length = 0; // ---- name length
440 function->code_start_offset = off(pc_); // ---- code start
441 function->code_end_offset = off(limit_); // ---- code end
442 function->exported = false; // ---- exported
443 function->external = false; // ---- external
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444
445 if (ok()) VerifyFunctionBody(0, module_env, function);
446
447 FunctionResult result;
448 result.CopyFrom(result_); // Copy error code and location.
449 result.val = function;
450 return result;
451 }
452
453 // Decodes a single function signature at {start}.
454 FunctionSig* DecodeFunctionSignature(const byte* start) {
455 pc_ = start;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100456 FunctionSig* result = consume_sig();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 return ok() ? result : nullptr;
458 }
459
460 private:
461 Zone* module_zone;
462 ModuleResult result_;
Ben Murdochda12d292016-06-02 14:46:10 +0100463 ModuleOrigin origin_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464
465 uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
466
467 // Decodes a single global entry inside a module starting at {pc_}.
468 void DecodeGlobalInModule(WasmGlobal* global) {
Ben Murdochda12d292016-06-02 14:46:10 +0100469 global->name_offset = consume_string(&global->name_length, "global name");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470 global->type = mem_type();
471 global->offset = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100472 global->exported = consume_u8("exported") != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 }
474
475 // Decodes a single function entry inside a module starting at {pc_}.
Ben Murdochda12d292016-06-02 14:46:10 +0100476 // TODO(titzer): legacy function body; remove
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
478 bool verify_body = true) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100479 byte decl_bits = consume_u8("function decl");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480
481 const byte* sigpos = pc_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100482 function->sig_index = consume_u16("signature index");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483
Ben Murdochda12d292016-06-02 14:46:10 +0100484 if (function->sig_index >= module->signatures.size()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 return error(sigpos, "invalid signature index");
486 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100487 function->sig = module->signatures[function->sig_index];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 }
489
490 TRACE(" +%d <function attributes:%s%s%s%s%s>\n",
491 static_cast<int>(pc_ - start_),
492 decl_bits & kDeclFunctionName ? " name" : "",
493 decl_bits & kDeclFunctionImport ? " imported" : "",
494 decl_bits & kDeclFunctionLocals ? " locals" : "",
495 decl_bits & kDeclFunctionExport ? " exported" : "",
496 (decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
497
498 if (decl_bits & kDeclFunctionName) {
Ben Murdochda12d292016-06-02 14:46:10 +0100499 function->name_offset =
500 consume_string(&function->name_length, "function name");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000501 }
502
503 function->exported = decl_bits & kDeclFunctionExport;
504
505 // Imported functions have no locals or body.
506 if (decl_bits & kDeclFunctionImport) {
507 function->external = true;
508 return;
509 }
510
511 if (decl_bits & kDeclFunctionLocals) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100512 function->local_i32_count = consume_u16("i32 count");
513 function->local_i64_count = consume_u16("i64 count");
514 function->local_f32_count = consume_u16("f32 count");
515 function->local_f64_count = consume_u16("f64 count");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 }
517
Ben Murdoch097c5b22016-05-18 11:27:45 +0100518 uint16_t size = consume_u16("body size");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 if (ok()) {
520 if ((pc_ + size) > limit_) {
521 return error(pc_, limit_,
522 "expected %d bytes for function body, fell off end", size);
523 }
524 function->code_start_offset = static_cast<uint32_t>(pc_ - start_);
525 function->code_end_offset = function->code_start_offset + size;
526 TRACE(" +%d %-20s: (%d bytes)\n", static_cast<int>(pc_ - start_),
527 "function body", size);
528 pc_ += size;
529 }
530 }
531
Ben Murdoch097c5b22016-05-18 11:27:45 +0100532 bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
533 if (offset > limit) return false;
534 if ((offset + size) < offset) return false; // overflow
535 return (offset + size) <= limit;
536 }
537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 // Decodes a single data segment entry inside a module starting at {pc_}.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100539 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
Ben Murdochda12d292016-06-02 14:46:10 +0100540 const byte* start = pc_;
541 int length;
542 segment->dest_addr = consume_u32v(&length, "destination");
543 segment->source_size = consume_u32v(&length, "source size");
544 segment->source_offset = static_cast<uint32_t>(pc_ - start_);
545 segment->init = true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100546
547 // Validate the data is in the module.
548 uint32_t module_limit = static_cast<uint32_t>(limit_ - start_);
549 if (!IsWithinLimit(module_limit, segment->source_offset,
550 segment->source_size)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100551 error(start, "segment out of bounds of module");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100552 }
553
554 // Validate that the segment will fit into the (minimum) memory.
555 uint32_t memory_limit =
Ben Murdochda12d292016-06-02 14:46:10 +0100556 WasmModule::kPageSize * (module ? module->min_mem_pages
557 : WasmModule::kMaxMemPages);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100558 if (!IsWithinLimit(memory_limit, segment->dest_addr,
559 segment->source_size)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100560 error(start, "segment out of bounds of memory");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100561 }
Ben Murdochda12d292016-06-02 14:46:10 +0100562
563 consume_bytes(segment->source_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 }
565
566 // Verifies the body (code) of a given function.
567 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
568 WasmFunction* function) {
569 if (FLAG_trace_wasm_decode_time) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 OFStream os(stdout);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100571 os << "Verifying WASM function " << WasmFunctionName(function, menv)
572 << std::endl;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 os << std::endl;
574 }
Ben Murdochda12d292016-06-02 14:46:10 +0100575 FunctionBody body = {menv, function->sig, start_,
576 start_ + function->code_start_offset,
577 start_ + function->code_end_offset};
578 TreeResult result = VerifyWasmCode(module_zone->allocator(), body);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 if (result.failed()) {
580 // Wrap the error message from the function decoder.
581 std::ostringstream str;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100582 str << "in function " << WasmFunctionName(function, menv) << ": ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 str << result;
584 std::string strval = str.str();
585 const char* raw = strval.c_str();
586 size_t len = strlen(raw);
587 char* buffer = new char[len];
588 strncpy(buffer, raw, len);
589 buffer[len - 1] = 0;
590
591 // Copy error code and location.
592 result_.CopyFrom(result);
593 result_.error_msg.Reset(buffer);
594 }
595 }
596
597 // Reads a single 32-bit unsigned integer interpreted as an offset, checking
598 // the offset is within bounds and advances.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100599 uint32_t consume_offset(const char* name = nullptr) {
600 uint32_t offset = consume_u32(name ? name : "offset");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 if (offset > static_cast<uint32_t>(limit_ - start_)) {
602 error(pc_ - sizeof(uint32_t), "offset out of bounds of module");
603 }
604 return offset;
605 }
606
Ben Murdochda12d292016-06-02 14:46:10 +0100607 // Reads a length-prefixed string, checking that it is within bounds. Returns
608 // the offset of the string, and the length as an out parameter.
609 uint32_t consume_string(uint32_t* length, const char* name = nullptr) {
610 int varint_length;
611 *length = consume_u32v(&varint_length, "string length");
612 uint32_t offset = pc_offset();
613 TRACE(" +%u %-20s: (%u bytes)\n", offset, "string", *length);
614 consume_bytes(*length);
615 return offset;
616 }
617
618 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
619 const byte* pos = pc_;
620 int length;
621 uint32_t sig_index = consume_u32v(&length, "signature index");
622 if (sig_index >= module->signatures.size()) {
623 error(pos, pos, "signature index %u out of bounds (%d signatures)",
624 sig_index, static_cast<int>(module->signatures.size()));
625 *sig = nullptr;
626 return 0;
627 }
628 *sig = module->signatures[sig_index];
629 return sig_index;
630 }
631
632 uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
633 const byte* pos = pc_;
634 int length;
635 uint32_t func_index = consume_u32v(&length, "function index");
636 if (func_index >= module->functions.size()) {
637 error(pos, pos, "function index %u out of bounds (%d functions)",
638 func_index, static_cast<int>(module->functions.size()));
639 *func = nullptr;
640 return 0;
641 }
642 *func = &module->functions[func_index];
643 return func_index;
644 }
645
646 // Reads a section name.
647 WasmSection::Code consume_section_name(int* string_leb_length,
648 uint32_t* string_length) {
649 *string_length = consume_u32v(string_leb_length, "name length");
650 const byte* start = pc_;
651 consume_bytes(*string_length);
652 if (failed()) {
653 TRACE("Section name of length %u couldn't be read\n", *string_length);
654 return WasmSection::Code::Max;
655 }
656 // TODO(jfb) Linear search, it may be better to do a common-prefix search.
657 for (WasmSection::Code i = WasmSection::begin(); i != WasmSection::end();
658 i = WasmSection::next(i)) {
659 if (WasmSection::getNameLength(i) == *string_length &&
660 0 == memcmp(WasmSection::getName(i), start, *string_length)) {
661 return i;
662 }
663 }
664 TRACE("Unknown section: '");
665 for (uint32_t i = 0; i != *string_length; ++i) TRACE("%c", *(start + i));
666 TRACE("'\n");
667 return WasmSection::Code::Max;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 }
669
670 // Reads a single 8-bit integer, interpreting it as a local type.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100671 LocalType consume_local_type() {
672 byte val = consume_u8("local type");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 LocalTypeCode t = static_cast<LocalTypeCode>(val);
674 switch (t) {
675 case kLocalVoid:
676 return kAstStmt;
677 case kLocalI32:
678 return kAstI32;
679 case kLocalI64:
680 return kAstI64;
681 case kLocalF32:
682 return kAstF32;
683 case kLocalF64:
684 return kAstF64;
685 default:
686 error(pc_ - 1, "invalid local type");
687 return kAstStmt;
688 }
689 }
690
691 // Reads a single 8-bit integer, interpreting it as a memory type.
692 MachineType mem_type() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100693 byte val = consume_u8("memory type");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000694 MemTypeCode t = static_cast<MemTypeCode>(val);
695 switch (t) {
696 case kMemI8:
697 return MachineType::Int8();
698 case kMemU8:
699 return MachineType::Uint8();
700 case kMemI16:
701 return MachineType::Int16();
702 case kMemU16:
703 return MachineType::Uint16();
704 case kMemI32:
705 return MachineType::Int32();
706 case kMemU32:
707 return MachineType::Uint32();
708 case kMemI64:
709 return MachineType::Int64();
710 case kMemU64:
711 return MachineType::Uint64();
712 case kMemF32:
713 return MachineType::Float32();
714 case kMemF64:
715 return MachineType::Float64();
716 default:
717 error(pc_ - 1, "invalid memory type");
718 return MachineType::None();
719 }
720 }
721
722 // Parses an inline function signature.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100723 FunctionSig* consume_sig() {
Ben Murdochda12d292016-06-02 14:46:10 +0100724 int length;
725 byte count = consume_u32v(&length, "param count");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100726 LocalType ret = consume_local_type();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
728 if (ret != kAstStmt) builder.AddReturn(ret);
729
730 for (int i = 0; i < count; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100731 LocalType param = consume_local_type();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732 if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
733 builder.AddParam(param);
734 }
735 return builder.Build();
736 }
737};
738
739
740// Helpers for nice error messages.
741class ModuleError : public ModuleResult {
742 public:
743 explicit ModuleError(const char* msg) {
744 error_code = kError;
745 size_t len = strlen(msg) + 1;
746 char* result = new char[len];
747 strncpy(result, msg, len);
748 result[len - 1] = 0;
749 error_msg.Reset(result);
750 }
751};
752
753
754// Helpers for nice error messages.
755class FunctionError : public FunctionResult {
756 public:
757 explicit FunctionError(const char* msg) {
758 error_code = kError;
759 size_t len = strlen(msg) + 1;
760 char* result = new char[len];
761 strncpy(result, msg, len);
762 result[len - 1] = 0;
763 error_msg.Reset(result);
764 }
765};
766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
768 const byte* module_start, const byte* module_end,
Ben Murdochda12d292016-06-02 14:46:10 +0100769 bool verify_functions, ModuleOrigin origin) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 size_t size = module_end - module_start;
771 if (module_start > module_end) return ModuleError("start > end");
772 if (size >= kMaxModuleSize) return ModuleError("size > maximum module size");
773 WasmModule* module = new WasmModule();
Ben Murdochda12d292016-06-02 14:46:10 +0100774 ModuleDecoder decoder(zone, module_start, module_end, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 return decoder.DecodeModule(module, verify_functions);
776}
777
778
779FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
780 const byte* end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100781 ModuleDecoder decoder(zone, start, end, kWasmOrigin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782 return decoder.DecodeFunctionSignature(start);
783}
784
785
786FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
787 ModuleEnv* module_env,
788 const byte* function_start,
789 const byte* function_end) {
790 size_t size = function_end - function_start;
791 if (function_start > function_end) return FunctionError("start > end");
792 if (size > kMaxFunctionSize)
793 return FunctionError("size > maximum function size");
794 WasmFunction* function = new WasmFunction();
Ben Murdochda12d292016-06-02 14:46:10 +0100795 ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 return decoder.DecodeSingleFunction(module_env, function);
797}
798} // namespace wasm
799} // namespace internal
800} // namespace v8