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