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 :
7 : #include "src/base/functional.h"
8 : #include "src/base/platform/platform.h"
9 : #include "src/base/template-utils.h"
10 : #include "src/counters.h"
11 : #include "src/flags.h"
12 : #include "src/objects-inl.h"
13 : #include "src/ostreams.h"
14 : #include "src/v8.h"
15 : #include "src/wasm/decoder.h"
16 : #include "src/wasm/function-body-decoder-impl.h"
17 : #include "src/wasm/wasm-engine.h"
18 : #include "src/wasm/wasm-limits.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 : namespace wasm {
23 :
24 : #define TRACE(...) \
25 : do { \
26 : if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
27 : } while (false)
28 :
29 : namespace {
30 :
31 : constexpr char kNameString[] = "name";
32 : constexpr char kSourceMappingURLString[] = "sourceMappingURL";
33 :
34 : template <size_t N>
35 : constexpr size_t num_chars(const char (&)[N]) {
36 : return N - 1; // remove null character at end.
37 : }
38 :
39 : const char* ExternalKindName(ImportExportKindCode kind) {
40 738 : switch (kind) {
41 : case kExternalFunction:
42 : return "function";
43 : case kExternalTable:
44 : return "table";
45 : case kExternalMemory:
46 : return "memory";
47 : case kExternalGlobal:
48 : return "global";
49 : case kExternalException:
50 : return "exception";
51 : }
52 : return "unknown";
53 : }
54 :
55 : } // namespace
56 :
57 32 : const char* SectionName(SectionCode code) {
58 32 : switch (code) {
59 : case kUnknownSectionCode:
60 : return "Unknown";
61 : case kTypeSectionCode:
62 0 : return "Type";
63 : case kImportSectionCode:
64 0 : return "Import";
65 : case kFunctionSectionCode:
66 0 : return "Function";
67 : case kTableSectionCode:
68 0 : return "Table";
69 : case kMemorySectionCode:
70 0 : return "Memory";
71 : case kGlobalSectionCode:
72 2 : return "Global";
73 : case kExportSectionCode:
74 2 : return "Export";
75 : case kStartSectionCode:
76 9 : return "Start";
77 : case kCodeSectionCode:
78 1 : return "Code";
79 : case kElementSectionCode:
80 2 : return "Element";
81 : case kDataSectionCode:
82 0 : return "Data";
83 : case kExceptionSectionCode:
84 12 : return "Exception";
85 : case kDataCountSectionCode:
86 4 : return "DataCount";
87 : case kNameSectionCode:
88 0 : return kNameString;
89 : case kSourceMappingURLSectionCode:
90 0 : return kSourceMappingURLString;
91 : default:
92 0 : return "<unknown>";
93 : }
94 : }
95 :
96 : namespace {
97 :
98 16915 : bool validate_utf8(Decoder* decoder, WireBytesRef string) {
99 : return unibrow::Utf8::ValidateEncoding(
100 : decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
101 33830 : string.length());
102 : }
103 :
104 446462 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
105 446462 : switch (expr.kind) {
106 : case WasmInitExpr::kNone:
107 : return kWasmStmt;
108 : case WasmInitExpr::kGlobalIndex:
109 307 : return expr.val.global_index < module->globals.size()
110 : ? module->globals[expr.val.global_index].type
111 614 : : kWasmStmt;
112 : case WasmInitExpr::kI32Const:
113 : return kWasmI32;
114 : case WasmInitExpr::kI64Const:
115 : return kWasmI64;
116 : case WasmInitExpr::kF32Const:
117 : return kWasmF32;
118 : case WasmInitExpr::kF64Const:
119 : return kWasmF64;
120 : case WasmInitExpr::kAnyRefConst:
121 : return kWasmAnyRef;
122 : default:
123 0 : UNREACHABLE();
124 : }
125 : }
126 :
127 : // Reads a length-prefixed string, checking that it is within bounds. Returns
128 : // the offset of the string, and the length as an out parameter.
129 978127 : WireBytesRef consume_string(Decoder& decoder, bool validate_utf8,
130 : const char* name) {
131 : uint32_t length = decoder.consume_u32v("string length");
132 : uint32_t offset = decoder.pc_offset();
133 : const byte* string_start = decoder.pc();
134 : // Consume bytes before validation to guarantee that the string is not oob.
135 978135 : if (length > 0) {
136 965784 : decoder.consume_bytes(length, name);
137 1912679 : if (decoder.ok() && validate_utf8 &&
138 946890 : !unibrow::Utf8::ValidateEncoding(string_start, length)) {
139 9722 : decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
140 : }
141 : }
142 978166 : return {offset, decoder.failed() ? 0 : length};
143 : }
144 :
145 : // An iterator over the sections in a wasm binary module.
146 : // Automatically skips all unknown sections.
147 : class WasmSectionIterator {
148 : public:
149 139775 : explicit WasmSectionIterator(Decoder& decoder)
150 : : decoder_(decoder),
151 : section_code_(kUnknownSectionCode),
152 : section_start_(decoder.pc()),
153 586379 : section_end_(decoder.pc()) {
154 446604 : next();
155 : }
156 :
157 1923313 : inline bool more() const { return decoder_.ok() && decoder_.more(); }
158 :
159 : inline SectionCode section_code() const { return section_code_; }
160 :
161 : inline const byte* section_start() const { return section_start_; }
162 :
163 : inline uint32_t section_length() const {
164 549 : return static_cast<uint32_t>(section_end_ - section_start_);
165 : }
166 :
167 1435631 : inline Vector<const uint8_t> payload() const {
168 1435631 : return {payload_start_, payload_length()};
169 : }
170 :
171 : inline const byte* payload_start() const { return payload_start_; }
172 :
173 : inline uint32_t payload_length() const {
174 2868708 : return static_cast<uint32_t>(section_end_ - payload_start_);
175 : }
176 :
177 : inline const byte* section_end() const { return section_end_; }
178 :
179 : // Advances to the next section, checking that decoding the current section
180 : // stopped at {section_end_}.
181 1475046 : void advance(bool move_to_section_end = false) {
182 4423464 : if (move_to_section_end && decoder_.pc() < section_end_) {
183 : decoder_.consume_bytes(
184 2946676 : static_cast<uint32_t>(section_end_ - decoder_.pc()));
185 : }
186 2950160 : if (decoder_.pc() != section_end_) {
187 549 : const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
188 : decoder_.errorf(decoder_.pc(),
189 : "section was %s than expected size "
190 : "(%u bytes expected, %zu decoded)",
191 : msg, section_length(),
192 1098 : static_cast<size_t>(decoder_.pc() - section_start_));
193 : }
194 1475080 : next();
195 1475107 : }
196 :
197 : private:
198 : Decoder& decoder_;
199 : SectionCode section_code_;
200 : const byte* section_start_;
201 : const byte* payload_start_;
202 : const byte* section_end_;
203 :
204 : // Reads the section code/name at the current position and sets up
205 : // the embedder fields.
206 1921672 : void next() {
207 3834058 : if (!decoder_.more()) {
208 309786 : section_code_ = kUnknownSectionCode;
209 2231486 : return;
210 : }
211 1611886 : section_start_ = decoder_.pc();
212 : uint8_t section_code = decoder_.consume_u8("section code");
213 : // Read and check the section size.
214 1611907 : uint32_t section_length = decoder_.consume_u32v("section length");
215 :
216 3223814 : payload_start_ = decoder_.pc();
217 1611907 : if (decoder_.checkAvailable(section_length)) {
218 : // Get the limit of the section within the module.
219 1486939 : section_end_ = payload_start_ + section_length;
220 : } else {
221 : // The section would extend beyond the end of the module.
222 124968 : section_end_ = payload_start_;
223 : }
224 :
225 1611907 : if (section_code == kUnknownSectionCode) {
226 : // Check for the known "name" or "sourceMappingURL" section.
227 : section_code =
228 37468 : ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
229 : // As a side effect, the above function will forward the decoder to after
230 : // the identifier string.
231 74906 : payload_start_ = decoder_.pc();
232 1574439 : } else if (!IsValidSectionCode(section_code)) {
233 : decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
234 248436 : section_code);
235 : section_code = kUnknownSectionCode;
236 : }
237 1611914 : section_code_ = decoder_.failed() ? kUnknownSectionCode
238 1611914 : : static_cast<SectionCode>(section_code);
239 :
240 1746583 : if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
241 : // skip to the end of the unknown section.
242 8278 : uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
243 4139 : decoder_.consume_bytes(remaining, "section payload");
244 : }
245 : }
246 : };
247 :
248 : } // namespace
249 :
250 : // The main logic for decoding the bytes of a module.
251 632459 : class ModuleDecoderImpl : public Decoder {
252 : public:
253 : explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
254 : : Decoder(nullptr, nullptr),
255 : enabled_features_(enabled),
256 778 : origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
257 :
258 315647 : ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start,
259 : const byte* module_end, ModuleOrigin origin)
260 : : Decoder(module_start, module_end),
261 : enabled_features_(enabled),
262 631294 : origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
263 315647 : if (end_ < start_) {
264 0 : error(start_, "end is less than start");
265 0 : end_ = start_;
266 : }
267 315647 : }
268 :
269 17387 : void onFirstError() override {
270 17387 : pc_ = end_; // On error, terminate section decoding loop.
271 17387 : }
272 :
273 : void DumpModule(const Vector<const byte> module_bytes) {
274 : std::string path;
275 : if (FLAG_dump_wasm_module_path) {
276 : path = FLAG_dump_wasm_module_path;
277 : if (path.size() &&
278 : !base::OS::isDirectorySeparator(path[path.size() - 1])) {
279 : path += base::OS::DirectorySeparator();
280 : }
281 : }
282 : // File are named `HASH.{ok,failed}.wasm`.
283 : size_t hash = base::hash_range(module_bytes.start(), module_bytes.end());
284 : EmbeddedVector<char, 32> buf;
285 : SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed");
286 : std::string name(buf.start());
287 : if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
288 : if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) !=
289 : 1) {
290 : OFStream os(stderr);
291 : os << "Error while dumping wasm file" << std::endl;
292 : }
293 : fclose(wasm_file);
294 : }
295 : }
296 :
297 315748 : void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
298 315748 : CHECK_NULL(module_);
299 : SetCounters(counters);
300 : module_.reset(
301 1578756 : new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
302 315752 : module_->initial_pages = 0;
303 315752 : module_->maximum_pages = 0;
304 315752 : module_->mem_export = false;
305 315752 : module_->origin = origin_;
306 315752 : }
307 :
308 315744 : void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
309 631491 : if (failed()) return;
310 315744 : Reset(bytes, offset);
311 :
312 315729 : const byte* pos = pc_;
313 : uint32_t magic_word = consume_u32("wasm magic");
314 : #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
315 315741 : if (magic_word != kWasmMagic) {
316 : errorf(pos,
317 : "expected magic word %02x %02x %02x %02x, "
318 : "found %02x %02x %02x %02x",
319 8112 : BYTES(kWasmMagic), BYTES(magic_word));
320 : }
321 :
322 315741 : pos = pc_;
323 : {
324 : uint32_t magic_version = consume_u32("wasm version");
325 315747 : if (magic_version != kWasmVersion) {
326 : errorf(pos,
327 : "expected version %02x %02x %02x %02x, "
328 : "found %02x %02x %02x %02x",
329 8549 : BYTES(kWasmVersion), BYTES(magic_version));
330 : }
331 : }
332 : #undef BYTES
333 : }
334 :
335 474 : bool CheckSectionOrder(SectionCode section_code,
336 : SectionCode prev_section_code,
337 : SectionCode next_section_code) {
338 474 : if (next_ordered_section_ > next_section_code) {
339 : errorf(pc(), "The %s section must appear before the %s section",
340 3 : SectionName(section_code), SectionName(next_section_code));
341 3 : return false;
342 : }
343 471 : if (next_ordered_section_ <= prev_section_code) {
344 469 : next_ordered_section_ = prev_section_code + 1;
345 : }
346 : return true;
347 : }
348 :
349 475 : bool CheckUnorderedSection(SectionCode section_code) {
350 475 : if (has_seen_unordered_section(section_code)) {
351 : errorf(pc(), "Multiple %s sections not allowed",
352 1 : SectionName(section_code));
353 1 : return false;
354 : }
355 : set_seen_unordered_section(section_code);
356 474 : return true;
357 : }
358 :
359 1433226 : void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
360 : uint32_t offset, bool verify_functions = true) {
361 2866419 : if (failed()) return;
362 1433241 : Reset(bytes, offset);
363 : TRACE("Section: %s\n", SectionName(section_code));
364 : TRACE("Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()),
365 : static_cast<const void*>(bytes.end()));
366 :
367 : // Check if the section is out-of-order.
368 1433233 : if (section_code < next_ordered_section_ &&
369 : section_code < kFirstUnorderedSection) {
370 26 : errorf(pc(), "unexpected section: %s", SectionName(section_code));
371 13 : return;
372 : }
373 :
374 1433220 : switch (section_code) {
375 : case kUnknownSectionCode:
376 : break;
377 : case kDataCountSectionCode:
378 66 : if (!CheckUnorderedSection(section_code)) return;
379 65 : if (!CheckSectionOrder(section_code, kElementSectionCode,
380 65 : kCodeSectionCode))
381 : return;
382 : break;
383 : case kExceptionSectionCode:
384 409 : if (!CheckUnorderedSection(section_code)) return;
385 409 : if (!CheckSectionOrder(section_code, kGlobalSectionCode,
386 409 : kExportSectionCode))
387 : return;
388 : break;
389 : case kSourceMappingURLSectionCode:
390 : // sourceMappingURL is a custom section and currently can occur anywhere
391 : // in the module. In case of multiple sourceMappingURL sections, all
392 : // except the first occurrence are ignored.
393 : case kNameSectionCode:
394 : // TODO(titzer): report out of place name section as a warning.
395 : // Be lenient with placement of name section. All except first
396 : // occurrence are ignored.
397 : break;
398 : default:
399 1407962 : next_ordered_section_ = section_code + 1;
400 1407962 : break;
401 : }
402 :
403 1433171 : switch (section_code) {
404 : case kUnknownSectionCode:
405 : break;
406 : case kTypeSectionCode:
407 288533 : DecodeTypeSection();
408 288547 : break;
409 : case kImportSectionCode:
410 260477 : DecodeImportSection();
411 260480 : break;
412 : case kFunctionSectionCode:
413 286504 : DecodeFunctionSection();
414 286497 : break;
415 : case kTableSectionCode:
416 2539 : DecodeTableSection();
417 2539 : break;
418 : case kMemorySectionCode:
419 11385 : DecodeMemorySection();
420 11385 : break;
421 : case kGlobalSectionCode:
422 2830 : DecodeGlobalSection();
423 2830 : break;
424 : case kExportSectionCode:
425 262704 : DecodeExportSection();
426 262697 : break;
427 : case kStartSectionCode:
428 3328 : DecodeStartSection();
429 3328 : break;
430 : case kCodeSectionCode:
431 285792 : DecodeCodeSection(verify_functions);
432 285791 : break;
433 : case kElementSectionCode:
434 2159 : DecodeElementSection();
435 2159 : break;
436 : case kDataSectionCode:
437 1669 : DecodeDataSection();
438 1669 : break;
439 : case kNameSectionCode:
440 24761 : DecodeNameSection();
441 24756 : break;
442 : case kSourceMappingURLSectionCode:
443 9 : DecodeSourceMappingURLSection();
444 9 : break;
445 : case kDataCountSectionCode:
446 64 : if (enabled_features_.bulk_memory) {
447 : DecodeDataCountSection();
448 : } else {
449 4 : errorf(pc(), "unexpected section: %s", SectionName(section_code));
450 : }
451 : break;
452 : case kExceptionSectionCode:
453 407 : if (enabled_features_.eh) {
454 397 : DecodeExceptionSection();
455 : } else {
456 20 : errorf(pc(), "unexpected section: %s", SectionName(section_code));
457 : }
458 : break;
459 : default:
460 0 : errorf(pc(), "unexpected section: %s", SectionName(section_code));
461 0 : return;
462 : }
463 :
464 1433168 : if (pc() != bytes.end()) {
465 148 : const char* msg = pc() < bytes.end() ? "shorter" : "longer";
466 : errorf(pc(),
467 : "section was %s than expected size "
468 : "(%zu bytes expected, %zu decoded)",
469 148 : msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
470 : }
471 : }
472 :
473 288532 : void DecodeTypeSection() {
474 288532 : uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
475 3103054 : module_->signatures.reserve(signatures_count);
476 1840144 : for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
477 : TRACE("DecodeSignature[%d] module+%d\n", i,
478 : static_cast<int>(pc_ - start_));
479 631515 : FunctionSig* s = consume_sig(module_->signature_zone.get());
480 631515 : module_->signatures.push_back(s);
481 1262931 : uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
482 631505 : module_->signature_ids.push_back(id);
483 : }
484 : module_->signature_map.Freeze();
485 288557 : }
486 :
487 260477 : void DecodeImportSection() {
488 : uint32_t import_table_count =
489 260477 : consume_count("imports count", kV8MaxWasmImports);
490 1843013 : module_->import_table.reserve(import_table_count);
491 1051040 : for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
492 : TRACE("DecodeImportTable[%d] module+%d\n", i,
493 : static_cast<int>(pc_ - start_));
494 :
495 : module_->import_table.push_back({
496 : {0, 0}, // module_name
497 : {0, 0}, // field_name
498 : kExternalFunction, // kind
499 : 0 // index
500 795074 : });
501 265018 : WasmImport* import = &module_->import_table.back();
502 265018 : const byte* pos = pc_;
503 265018 : import->module_name = consume_string(*this, true, "module name");
504 265032 : import->field_name = consume_string(*this, true, "field name");
505 : import->kind =
506 265011 : static_cast<ImportExportKindCode>(consume_u8("import kind"));
507 265011 : switch (import->kind) {
508 : case kExternalFunction: {
509 : // ===== Imported function =======================================
510 510894 : import->index = static_cast<uint32_t>(module_->functions.size());
511 255447 : module_->num_imported_functions++;
512 : module_->functions.push_back({nullptr, // sig
513 : import->index, // func_index
514 : 0, // sig_index
515 : {0, 0}, // code
516 : true, // imported
517 1021788 : false}); // exported
518 : WasmFunction* function = &module_->functions.back();
519 : function->sig_index =
520 255447 : consume_sig_index(module_.get(), &function->sig);
521 255447 : break;
522 : }
523 : case kExternalTable: {
524 : // ===== Imported table ==========================================
525 1762 : if (!AddTable(module_.get())) break;
526 3488 : import->index = static_cast<uint32_t>(module_->tables.size());
527 1744 : module_->tables.emplace_back();
528 : WasmTable* table = &module_->tables.back();
529 1744 : table->imported = true;
530 1744 : ValueType type = consume_reference_type();
531 1744 : if (!enabled_features_.anyref) {
532 1738 : if (type != kWasmAnyFunc) {
533 0 : error(pc_ - 1, "invalid table type");
534 0 : break;
535 : }
536 : }
537 1744 : table->type = type;
538 1744 : uint8_t flags = validate_table_flags("element count");
539 : consume_resizable_limits(
540 : "element count", "elements", FLAG_wasm_max_table_size,
541 : &table->initial_size, &table->has_maximum_size,
542 1744 : FLAG_wasm_max_table_size, &table->maximum_size, flags);
543 1744 : break;
544 : }
545 : case kExternalMemory: {
546 : // ===== Imported memory =========================================
547 5355 : if (!AddMemory(module_.get())) break;
548 5329 : uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
549 : consume_resizable_limits(
550 : "memory", "pages", kSpecMaxWasmMemoryPages,
551 : &module_->initial_pages, &module_->has_maximum_pages,
552 10654 : kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
553 5341 : break;
554 : }
555 : case kExternalGlobal: {
556 : // ===== Imported global =========================================
557 4672 : import->index = static_cast<uint32_t>(module_->globals.size());
558 : module_->globals.push_back(
559 9344 : {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
560 : WasmGlobal* global = &module_->globals.back();
561 2336 : global->type = consume_value_type();
562 2336 : global->mutability = consume_mutability();
563 2336 : if (global->mutability) {
564 327 : module_->num_imported_mutable_globals++;
565 : }
566 : break;
567 : }
568 : case kExternalException: {
569 : // ===== Imported exception ======================================
570 119 : if (!enabled_features_.eh) {
571 1 : errorf(pos, "unknown import kind 0x%02x", import->kind);
572 1 : break;
573 : }
574 236 : import->index = static_cast<uint32_t>(module_->exceptions.size());
575 118 : WasmExceptionSig* exception_sig = nullptr;
576 118 : consume_exception_attribute(); // Attribute ignored for now.
577 118 : consume_exception_sig_index(module_.get(), &exception_sig);
578 118 : module_->exceptions.emplace_back(exception_sig);
579 118 : break;
580 : }
581 : default:
582 0 : errorf(pos, "unknown import kind 0x%02x", import->kind);
583 0 : break;
584 : }
585 : }
586 260492 : }
587 :
588 572971 : void DecodeFunctionSection() {
589 : uint32_t functions_count =
590 286477 : consume_count("functions count", kV8MaxWasmFunctions);
591 : auto counter =
592 572988 : SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
593 286494 : counter->AddSample(static_cast<int>(functions_count));
594 : DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
595 : uint32_t total_function_count =
596 1435190 : module_->num_imported_functions + functions_count;
597 286500 : module_->functions.reserve(total_function_count);
598 286500 : module_->num_declared_functions = functions_count;
599 717552 : for (uint32_t i = 0; i < functions_count; ++i) {
600 862192 : uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
601 : module_->functions.push_back({nullptr, // sig
602 : func_index, // func_index
603 : 0, // sig_index
604 : {0, 0}, // code
605 : false, // imported
606 1293286 : false}); // exported
607 : WasmFunction* function = &module_->functions.back();
608 431094 : function->sig_index = consume_sig_index(module_.get(), &function->sig);
609 717600 : if (!ok()) return;
610 : }
611 : DCHECK_EQ(module_->functions.size(), total_function_count);
612 : }
613 :
614 2539 : void DecodeTableSection() {
615 : // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
616 : // implementation of AnyRef landed.
617 2539 : uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
618 2539 : uint32_t table_count = consume_count("table count", max_count);
619 :
620 10060 : for (uint32_t i = 0; ok() && i < table_count; i++) {
621 5000 : if (!AddTable(module_.get())) break;
622 2491 : module_->tables.emplace_back();
623 : WasmTable* table = &module_->tables.back();
624 2491 : table->type = consume_reference_type();
625 2491 : uint8_t flags = validate_table_flags("table elements");
626 : consume_resizable_limits(
627 : "table elements", "elements", FLAG_wasm_max_table_size,
628 : &table->initial_size, &table->has_maximum_size,
629 2491 : FLAG_wasm_max_table_size, &table->maximum_size, flags);
630 : }
631 2539 : }
632 :
633 11385 : void DecodeMemorySection() {
634 11385 : uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
635 :
636 45338 : for (uint32_t i = 0; ok() && i < memory_count; i++) {
637 33942 : if (!AddMemory(module_.get())) break;
638 11284 : uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
639 : consume_resizable_limits(
640 : "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
641 : &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
642 22568 : &module_->maximum_pages, flags);
643 : }
644 11385 : }
645 :
646 2830 : void DecodeGlobalSection() {
647 2830 : uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
648 891246 : uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
649 2830 : module_->globals.reserve(imported_globals + globals_count);
650 888866 : for (uint32_t i = 0; ok() && i < globals_count; ++i) {
651 : TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
652 : // Add an uninitialized global and pass a pointer to it.
653 : module_->globals.push_back(
654 1766412 : {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
655 441603 : WasmGlobal* global = &module_->globals.back();
656 441603 : DecodeGlobalInModule(module_.get(), i + imported_globals, global);
657 : }
658 5210 : if (ok()) CalculateGlobalOffsets(module_.get());
659 2830 : }
660 :
661 262699 : void DecodeExportSection() {
662 : uint32_t export_table_count =
663 262699 : consume_count("exports count", kV8MaxWasmExports);
664 2102774 : module_->export_table.reserve(export_table_count);
665 1312496 : for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
666 : TRACE("DecodeExportTable[%d] module+%d\n", i,
667 : static_cast<int>(pc_ - start_));
668 :
669 : module_->export_table.push_back({
670 : {0, 0}, // name
671 : kExternalFunction, // kind
672 : 0 // index
673 1180617 : });
674 393531 : WasmExport* exp = &module_->export_table.back();
675 :
676 394269 : exp->name = consume_string(*this, true, "field name");
677 :
678 : const byte* pos = pc();
679 393522 : exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
680 393522 : switch (exp->kind) {
681 : case kExternalFunction: {
682 389574 : WasmFunction* func = nullptr;
683 389578 : exp->index = consume_func_index(module_.get(), &func);
684 389578 : module_->num_exported_functions++;
685 389578 : if (func) func->exported = true;
686 : break;
687 : }
688 : case kExternalTable: {
689 747 : WasmTable* table = nullptr;
690 747 : exp->index = consume_table_index(module_.get(), &table);
691 747 : if (table) table->exported = true;
692 : break;
693 : }
694 : case kExternalMemory: {
695 : uint32_t index = consume_u32v("memory index");
696 : // TODO(titzer): This should become more regular
697 : // once we support multiple memories.
698 1902 : if (!module_->has_memory || index != 0) {
699 27 : error("invalid memory index != 0");
700 : }
701 1902 : module_->mem_export = true;
702 1902 : break;
703 : }
704 : case kExternalGlobal: {
705 1136 : WasmGlobal* global = nullptr;
706 1136 : exp->index = consume_global_index(module_.get(), &global);
707 1136 : if (global) {
708 1118 : global->exported = true;
709 : }
710 : break;
711 : }
712 : case kExternalException: {
713 163 : if (!enabled_features_.eh) {
714 0 : errorf(pos, "invalid export kind 0x%02x", exp->kind);
715 0 : break;
716 : }
717 163 : WasmException* exception = nullptr;
718 163 : exp->index = consume_exception_index(module_.get(), &exception);
719 163 : break;
720 : }
721 : default:
722 0 : errorf(pos, "invalid export kind 0x%02x", exp->kind);
723 0 : break;
724 : }
725 : }
726 : // Check for duplicate exports (except for asm.js).
727 781895 : if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
728 8391 : std::vector<WasmExport> sorted_exports(module_->export_table);
729 :
730 706004 : auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
731 : // Return true if a < b.
732 1771270 : if (a.name.length() != b.name.length()) {
733 173371 : return a.name.length() < b.name.length();
734 : }
735 1597899 : const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
736 532633 : const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
737 532633 : return memcmp(left, right, a.name.length()) < 0;
738 8391 : };
739 8391 : std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
740 :
741 : auto it = sorted_exports.begin();
742 : WasmExport* last = &*it++;
743 145062 : for (auto end = sorted_exports.end(); it != end; last = &*it++) {
744 : DCHECK(!cmp_less(*it, *last)); // Vector must be sorted.
745 128649 : if (!cmp_less(*last, *it)) {
746 738 : const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
747 369 : TruncatedUserString<> name(pc, it->name.length());
748 : errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
749 : name.length(), name.start(), ExternalKindName(last->kind),
750 1107 : last->index, ExternalKindName(it->kind), it->index);
751 : break;
752 : }
753 : }
754 : }
755 262705 : }
756 :
757 3328 : void DecodeStartSection() {
758 : WasmFunction* func;
759 3328 : const byte* pos = pc_;
760 6656 : module_->start_function_index = consume_func_index(module_.get(), &func);
761 9948 : if (func &&
762 6539 : (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
763 72 : error(pos, "invalid start function: non-zero parameter or return count");
764 : }
765 3328 : }
766 :
767 2159 : void DecodeElementSection() {
768 : uint32_t element_count =
769 2159 : consume_count("element count", FLAG_wasm_max_table_size);
770 :
771 20824 : if (element_count > 0 && module_->tables.size() == 0) {
772 55 : error(pc_, "The element section requires a table");
773 : }
774 7327 : for (uint32_t i = 0; ok() && i < element_count; ++i) {
775 : const byte* pos = pc();
776 :
777 : bool is_active;
778 : uint32_t table_index;
779 : WasmInitExpr offset;
780 2731 : consume_segment_header("table index", &is_active, &table_index, &offset);
781 5035 : if (failed()) return;
782 :
783 2586 : if (is_active) {
784 7662 : if (table_index >= module_->tables.size()) {
785 0 : errorf(pos, "out of bounds table index %u", table_index);
786 0 : break;
787 : }
788 2554 : if (module_->tables[table_index].type != kWasmAnyFunc) {
789 : errorf(pos,
790 : "Invalid element segment. Table %u is not of type AnyFunc",
791 2 : table_index);
792 2 : break;
793 : }
794 : }
795 :
796 : uint32_t num_elem =
797 2584 : consume_count("number of elements", kV8MaxWasmTableEntries);
798 2584 : if (is_active) {
799 2552 : module_->elem_segments.emplace_back(table_index, offset);
800 : } else {
801 32 : module_->elem_segments.emplace_back();
802 : }
803 :
804 : WasmElemSegment* init = &module_->elem_segments.back();
805 11371 : for (uint32_t j = 0; j < num_elem; j++) {
806 8806 : WasmFunction* func = nullptr;
807 8806 : uint32_t index = consume_func_index(module_.get(), &func);
808 : DCHECK_IMPLIES(ok(), func != nullptr);
809 8806 : if (!ok()) break;
810 : DCHECK_EQ(index, func->func_index);
811 8787 : init->entries.push_back(index);
812 : }
813 : }
814 : }
815 :
816 285771 : void DecodeCodeSection(bool verify_functions) {
817 429779 : uint32_t pos = pc_offset();
818 285771 : uint32_t functions_count = consume_u32v("functions count");
819 285785 : CheckFunctionsCount(functions_count, pos);
820 1431102 : for (uint32_t i = 0; ok() && i < functions_count; ++i) {
821 : const byte* pos = pc();
822 : uint32_t size = consume_u32v("body size");
823 429777 : if (size > kV8MaxWasmFunctionSize) {
824 : errorf(pos, "size %u > maximum function size %zu", size,
825 3 : kV8MaxWasmFunctionSize);
826 285786 : return;
827 : }
828 : uint32_t offset = pc_offset();
829 429774 : consume_bytes(size, "function body");
830 429776 : if (failed()) break;
831 429768 : DecodeFunctionBody(i, size, offset, verify_functions);
832 : }
833 : }
834 :
835 286026 : bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
836 286115 : if (functions_count != module_->num_declared_functions) {
837 89 : Reset(nullptr, nullptr, offset);
838 : errorf(nullptr, "function body count %u mismatch (%u expected)",
839 89 : functions_count, module_->num_declared_functions);
840 89 : return false;
841 : }
842 : return true;
843 : }
844 :
845 430263 : void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
846 : bool verify_functions) {
847 : WasmFunction* function =
848 581996 : &module_->functions[index + module_->num_imported_functions];
849 430263 : function->code = {offset, length};
850 430263 : if (verify_functions) {
851 151733 : ModuleWireBytes bytes(start_, end_);
852 : VerifyFunctionBody(module_->signature_zone->allocator(),
853 : index + module_->num_imported_functions, bytes,
854 303466 : module_.get(), function);
855 : }
856 430263 : }
857 :
858 296581 : bool CheckDataSegmentsCount(uint32_t data_segments_count) {
859 296695 : if (has_seen_unordered_section(kDataCountSectionCode) &&
860 117 : data_segments_count != module_->num_declared_data_segments) {
861 : errorf(pc(), "data segments count %u mismatch (%u expected)",
862 3 : data_segments_count, module_->num_declared_data_segments);
863 3 : return false;
864 : }
865 : return true;
866 : }
867 :
868 1669 : void DecodeDataSection() {
869 : uint32_t data_segments_count =
870 1669 : consume_count("data segments count", kV8MaxWasmDataSegments);
871 3338 : if (!CheckDataSegmentsCount(data_segments_count)) return;
872 :
873 7738 : module_->data_segments.reserve(data_segments_count);
874 7268 : for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
875 2135 : const byte* pos = pc();
876 2135 : if (!module_->has_memory) {
877 73 : error("cannot load data without memory");
878 73 : break;
879 : }
880 : TRACE("DecodeDataSegment[%d] module+%d\n", i,
881 : static_cast<int>(pc_ - start_));
882 :
883 : bool is_active;
884 : uint32_t memory_index;
885 : WasmInitExpr dest_addr;
886 : consume_segment_header("memory index", &is_active, &memory_index,
887 2062 : &dest_addr);
888 2062 : if (failed()) break;
889 :
890 1968 : if (is_active && memory_index != 0) {
891 0 : errorf(pos, "illegal memory index %u != 0", memory_index);
892 0 : break;
893 : }
894 :
895 1968 : uint32_t source_length = consume_u32v("source size");
896 : uint32_t source_offset = pc_offset();
897 :
898 1968 : if (is_active) {
899 1904 : module_->data_segments.emplace_back(dest_addr);
900 : } else {
901 64 : module_->data_segments.emplace_back();
902 : }
903 :
904 : WasmDataSegment* segment = &module_->data_segments.back();
905 :
906 1968 : consume_bytes(source_length, "segment data");
907 1968 : if (failed()) break;
908 :
909 1967 : segment->source = {source_offset, source_length};
910 : }
911 : }
912 :
913 24739 : void DecodeNameSection() {
914 : // TODO(titzer): find a way to report name errors as warnings.
915 : // ignore all but the first occurrence of name section.
916 24739 : if (!has_seen_unordered_section(kNameSectionCode)) {
917 : set_seen_unordered_section(kNameSectionCode);
918 : // Use an inner decoder so that errors don't fail the outer decoder.
919 24753 : Decoder inner(start_, pc_, end_, buffer_offset_);
920 : // Decode all name subsections.
921 : // Be lenient with their order.
922 49613 : while (inner.ok() && inner.more()) {
923 : uint8_t name_type = inner.consume_u8("name type");
924 24877 : if (name_type & 0x80) inner.error("name type if not varuint7");
925 :
926 : uint32_t name_payload_len = inner.consume_u32v("name payload length");
927 24880 : if (!inner.checkAvailable(name_payload_len)) break;
928 :
929 : // Decode module name, ignore the rest.
930 : // Function and local names will be decoded when needed.
931 24861 : if (name_type == NameSectionKindCode::kModule) {
932 149 : WireBytesRef name = consume_string(inner, false, "module name");
933 206 : if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
934 : } else {
935 24712 : inner.consume_bytes(name_payload_len, "name subsection payload");
936 : }
937 : }
938 : }
939 : // Skip the whole names section in the outer decoder.
940 24741 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
941 24762 : }
942 :
943 17 : void DecodeSourceMappingURLSection() {
944 9 : Decoder inner(start_, pc_, end_, buffer_offset_);
945 9 : WireBytesRef url = wasm::consume_string(inner, true, "module name");
946 17 : if (inner.ok() &&
947 : !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
948 : const byte* url_start =
949 14 : inner.start() + inner.GetBufferRelativeOffset(url.offset());
950 7 : module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
951 14 : url.length());
952 : set_seen_unordered_section(kSourceMappingURLSectionCode);
953 : }
954 9 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
955 9 : }
956 :
957 : void DecodeDataCountSection() {
958 62 : module_->num_declared_data_segments =
959 62 : consume_count("data segments count", kV8MaxWasmDataSegments);
960 : }
961 :
962 397 : void DecodeExceptionSection() {
963 : uint32_t exception_count =
964 397 : consume_count("exception count", kV8MaxWasmExceptions);
965 1708 : for (uint32_t i = 0; ok() && i < exception_count; ++i) {
966 : TRACE("DecodeException[%d] module+%d\n", i,
967 : static_cast<int>(pc_ - start_));
968 457 : WasmExceptionSig* exception_sig = nullptr;
969 457 : consume_exception_attribute(); // Attribute ignored for now.
970 457 : consume_exception_sig_index(module_.get(), &exception_sig);
971 457 : module_->exceptions.emplace_back(exception_sig);
972 : }
973 397 : }
974 :
975 294914 : bool CheckMismatchedCounts() {
976 : // The declared vs. defined function count is normally checked when
977 : // decoding the code section, but we have to check it here too in case the
978 : // code section is absent.
979 294914 : if (module_->num_declared_functions != 0) {
980 : DCHECK_LT(module_->num_imported_functions, module_->functions.size());
981 : // We know that the code section has been decoded if the first
982 : // non-imported function has its code set.
983 571476 : if (!module_->functions[module_->num_imported_functions].code.is_set()) {
984 : errorf(pc(), "function count is %u, but code section is absent",
985 25 : module_->num_declared_functions);
986 25 : return false;
987 : }
988 : }
989 : // Perform a similar check for the DataCount and Data sections, where data
990 : // segments are declared but the Data section is absent.
991 294911 : if (!CheckDataSegmentsCount(
992 589778 : static_cast<uint32_t>(module_->data_segments.size()))) {
993 : return false;
994 : }
995 294910 : return true;
996 : }
997 :
998 312098 : ModuleResult FinishDecoding(bool verify_functions = true) {
999 312098 : if (ok() && CheckMismatchedCounts()) {
1000 294910 : CalculateGlobalOffsets(module_.get());
1001 : }
1002 624224 : ModuleResult result = toResult(std::move(module_));
1003 584716 : if (verify_functions && result.ok() && intermediate_error_.has_error()) {
1004 : // Copy error message and location.
1005 6823 : return ModuleResult{std::move(intermediate_error_)};
1006 : }
1007 312111 : return result;
1008 : }
1009 :
1010 : // Decodes an entire module.
1011 315357 : ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
1012 : bool verify_functions = true) {
1013 315357 : StartDecoding(counters, allocator);
1014 : uint32_t offset = 0;
1015 315363 : Vector<const byte> orig_bytes(start(), end() - start());
1016 315363 : DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
1017 315360 : if (failed()) {
1018 17062 : return FinishDecoding(verify_functions);
1019 : }
1020 : // Size of the module header.
1021 : offset += 8;
1022 306829 : Decoder decoder(start_ + offset, end_, offset);
1023 :
1024 : WasmSectionIterator section_iter(decoder);
1025 :
1026 3471263 : while (ok() && section_iter.more()) {
1027 : // Shift the offset by the section header length
1028 1433121 : offset += section_iter.payload_start() - section_iter.section_start();
1029 1433121 : if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
1030 : DecodeSection(section_iter.section_code(), section_iter.payload(),
1031 2864760 : offset, verify_functions);
1032 : }
1033 : // Shift the offset by the remaining section payload
1034 2866154 : offset += section_iter.payload_length();
1035 1433077 : section_iter.advance(true);
1036 : }
1037 :
1038 : if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
1039 :
1040 306831 : if (decoder.failed()) {
1041 10371 : return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
1042 : }
1043 :
1044 606747 : return FinishDecoding(verify_functions);
1045 : }
1046 :
1047 : // Decodes a single anonymous function starting at {start_}.
1048 2 : FunctionResult DecodeSingleFunction(Zone* zone,
1049 : const ModuleWireBytes& wire_bytes,
1050 : const WasmModule* module,
1051 1 : std::unique_ptr<WasmFunction> function) {
1052 1 : pc_ = start_;
1053 1 : function->sig = consume_sig(zone);
1054 2 : function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
1055 :
1056 1 : if (ok())
1057 : VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
1058 1 : function.get());
1059 :
1060 1 : if (intermediate_error_.has_error()) {
1061 0 : return FunctionResult{std::move(intermediate_error_)};
1062 : }
1063 :
1064 1 : return FunctionResult(std::move(function));
1065 : }
1066 :
1067 : // Decodes a single function signature at {start}.
1068 : FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
1069 262 : pc_ = start;
1070 262 : FunctionSig* result = consume_sig(zone);
1071 262 : return ok() ? result : nullptr;
1072 : }
1073 :
1074 : WasmInitExpr DecodeInitExpr(const byte* start) {
1075 22 : pc_ = start;
1076 22 : return consume_init_expr(nullptr, kWasmStmt);
1077 : }
1078 :
1079 : const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
1080 :
1081 : Counters* GetCounters() const {
1082 : DCHECK_NOT_NULL(counters_);
1083 : return counters_;
1084 : }
1085 :
1086 : void SetCounters(Counters* counters) {
1087 : DCHECK_NULL(counters_);
1088 315749 : counters_ = counters;
1089 : }
1090 :
1091 : private:
1092 : const WasmFeatures enabled_features_;
1093 : std::shared_ptr<WasmModule> module_;
1094 : Counters* counters_ = nullptr;
1095 : // The type section is the first section in a module.
1096 : uint8_t next_ordered_section_ = kFirstSectionInModule;
1097 : // We store next_ordered_section_ as uint8_t instead of SectionCode so that we
1098 : // can increment it. This static_assert should make sure that SectionCode does
1099 : // not get bigger than uint8_t accidentially.
1100 : static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
1101 : sizeof(SectionCode),
1102 : "type mismatch");
1103 : uint32_t seen_unordered_sections_ = 0;
1104 : static_assert(kBitsPerByte *
1105 : sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
1106 : kLastKnownModuleSection,
1107 : "not enough bits");
1108 : WasmError intermediate_error_;
1109 : ModuleOrigin origin_;
1110 :
1111 : bool has_seen_unordered_section(SectionCode section_code) {
1112 321803 : return seen_unordered_sections_ & (1 << section_code);
1113 : }
1114 :
1115 : void set_seen_unordered_section(SectionCode section_code) {
1116 25234 : seen_unordered_sections_ |= 1 << section_code;
1117 : }
1118 :
1119 : uint32_t off(const byte* ptr) {
1120 1 : return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
1121 : }
1122 :
1123 4271 : bool AddTable(WasmModule* module) {
1124 4271 : if (enabled_features_.anyref) return true;
1125 8502 : if (module->tables.size() > 0) {
1126 36 : error("At most one table is supported");
1127 36 : return false;
1128 : } else {
1129 : return true;
1130 : }
1131 : }
1132 :
1133 : bool AddMemory(WasmModule* module) {
1134 16676 : if (module->has_memory) {
1135 72 : error("At most one memory is supported");
1136 : return false;
1137 : } else {
1138 16604 : module->has_memory = true;
1139 : return true;
1140 : }
1141 : }
1142 :
1143 : // Decodes a single global entry inside a module starting at {pc_}.
1144 441603 : void DecodeGlobalInModule(WasmModule* module, uint32_t index,
1145 : WasmGlobal* global) {
1146 441603 : global->type = consume_value_type();
1147 441603 : global->mutability = consume_mutability();
1148 441603 : const byte* pos = pc();
1149 441603 : global->init = consume_init_expr(module, kWasmStmt);
1150 441603 : if (global->init.kind == WasmInitExpr::kGlobalIndex) {
1151 73 : uint32_t other_index = global->init.val.global_index;
1152 73 : if (other_index >= index) {
1153 : errorf(pos,
1154 : "invalid global index in init expression, "
1155 : "index %u, other_index %u",
1156 0 : index, other_index);
1157 146 : } else if (module->globals[other_index].type != global->type) {
1158 : errorf(pos,
1159 : "type mismatch in global initialization "
1160 : "(from global #%u), expected %s, got %s",
1161 : other_index, ValueTypes::TypeName(global->type),
1162 0 : ValueTypes::TypeName(module->globals[other_index].type));
1163 : }
1164 : } else {
1165 441530 : if (global->type != TypeOf(module, global->init)) {
1166 : errorf(pos, "type error in global initialization, expected %s, got %s",
1167 : ValueTypes::TypeName(global->type),
1168 432 : ValueTypes::TypeName(TypeOf(module, global->init)));
1169 : }
1170 : }
1171 441603 : }
1172 :
1173 : // Decodes a single data segment entry inside a module starting at {pc_}.
1174 :
1175 : // Calculate individual global offsets and total size of globals table.
1176 297268 : void CalculateGlobalOffsets(WasmModule* module) {
1177 : uint32_t untagged_offset = 0;
1178 : uint32_t tagged_offset = 0;
1179 : uint32_t num_imported_mutable_globals = 0;
1180 1479687 : for (WasmGlobal& global : module->globals) {
1181 885151 : if (global.mutability && global.imported) {
1182 352 : global.index = num_imported_mutable_globals++;
1183 884799 : } else if (global.type == ValueType::kWasmAnyRef) {
1184 312 : global.offset = tagged_offset;
1185 : // All entries in the tagged_globals_buffer have size 1.
1186 312 : tagged_offset++;
1187 : } else {
1188 : byte size =
1189 884487 : ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
1190 884487 : untagged_offset = (untagged_offset + size - 1) & ~(size - 1); // align
1191 884487 : global.offset = untagged_offset;
1192 884487 : untagged_offset += size;
1193 : }
1194 : }
1195 297268 : module->untagged_globals_buffer_size = untagged_offset;
1196 297268 : module->tagged_globals_buffer_size = tagged_offset;
1197 297268 : }
1198 :
1199 : // Verifies the body (code) of a given function.
1200 151734 : void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
1201 : const ModuleWireBytes& wire_bytes,
1202 151734 : const WasmModule* module, WasmFunction* function) {
1203 : WasmFunctionName func_name(function,
1204 151734 : wire_bytes.GetNameOrNull(function, module));
1205 : if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
1206 : StdoutStream os;
1207 : os << "Verifying wasm function " << func_name << std::endl;
1208 : }
1209 : FunctionBody body = {
1210 : function->sig, function->code.offset(),
1211 : start_ + GetBufferRelativeOffset(function->code.offset()),
1212 606936 : start_ + GetBufferRelativeOffset(function->code.end_offset())};
1213 :
1214 : DecodeResult result;
1215 : {
1216 303468 : auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
1217 : wasm_decode, function_time);
1218 :
1219 : TimedHistogramScope wasm_decode_function_time_scope(time_counter);
1220 151734 : WasmFeatures unused_detected_features;
1221 303468 : result = VerifyWasmCode(allocator, enabled_features_, module,
1222 : &unused_detected_features, body);
1223 : }
1224 :
1225 : // If the decode failed and this is the first error, set error code and
1226 : // location.
1227 158593 : if (result.failed() && intermediate_error_.empty()) {
1228 : // Wrap the error message from the function decoder.
1229 6859 : std::ostringstream error_msg;
1230 6859 : error_msg << "in function " << func_name << ": "
1231 : << result.error().message();
1232 20577 : intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
1233 : }
1234 151734 : }
1235 :
1236 687115 : uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
1237 687115 : const byte* pos = pc_;
1238 687115 : uint32_t sig_index = consume_u32v("signature index");
1239 1374238 : if (sig_index >= module->signatures.size()) {
1240 : errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
1241 6457 : static_cast<int>(module->signatures.size()));
1242 6457 : *sig = nullptr;
1243 6457 : return 0;
1244 : }
1245 680662 : *sig = module->signatures[sig_index];
1246 680662 : return sig_index;
1247 : }
1248 :
1249 575 : uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
1250 575 : const byte* pos = pc_;
1251 575 : uint32_t sig_index = consume_sig_index(module, sig);
1252 575 : if (*sig && (*sig)->return_count() != 0) {
1253 2 : errorf(pos, "exception signature %u has non-void return", sig_index);
1254 2 : *sig = nullptr;
1255 2 : return 0;
1256 : }
1257 : return sig_index;
1258 : }
1259 :
1260 2385111 : uint32_t consume_count(const char* name, size_t maximum) {
1261 2385111 : const byte* p = pc_;
1262 2385111 : uint32_t count = consume_u32v(name);
1263 2385160 : if (count > maximum) {
1264 132 : errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
1265 132 : return static_cast<uint32_t>(maximum);
1266 : }
1267 : return count;
1268 : }
1269 :
1270 : uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
1271 401708 : return consume_index("function index", module->functions, func);
1272 : }
1273 :
1274 : uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
1275 1136 : return consume_index("global index", module->globals, global);
1276 : }
1277 :
1278 : uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
1279 747 : return consume_index("table index", module->tables, table);
1280 : }
1281 :
1282 : uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
1283 163 : return consume_index("exception index", module->exceptions, except);
1284 : }
1285 :
1286 : template <typename T>
1287 807506 : uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
1288 403753 : const byte* pos = pc_;
1289 403753 : uint32_t index = consume_u32v(name);
1290 807506 : if (index >= vector.size()) {
1291 120 : errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
1292 : static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
1293 120 : *ptr = nullptr;
1294 120 : return 0;
1295 : }
1296 403633 : *ptr = &vector[index];
1297 403633 : return index;
1298 : }
1299 :
1300 4235 : uint8_t validate_table_flags(const char* name) {
1301 8470 : uint8_t flags = consume_u8("resizable limits flags");
1302 : const byte* pos = pc();
1303 4235 : if (flags & 0xFE) {
1304 9 : errorf(pos - 1, "invalid %s limits flags", name);
1305 : }
1306 4235 : return flags;
1307 : }
1308 :
1309 16602 : uint8_t validate_memory_flags(bool* has_shared_memory) {
1310 33213 : uint8_t flags = consume_u8("resizable limits flags");
1311 : const byte* pos = pc();
1312 16611 : *has_shared_memory = false;
1313 16611 : if (enabled_features_.threads) {
1314 1461 : if (flags & 0xFC) {
1315 0 : errorf(pos - 1, "invalid memory limits flags");
1316 1461 : } else if (flags == 3) {
1317 : DCHECK_NOT_NULL(has_shared_memory);
1318 1369 : *has_shared_memory = true;
1319 92 : } else if (flags == 2) {
1320 : errorf(pos - 1,
1321 : "memory limits flags should have maximum defined if shared is "
1322 9 : "true");
1323 : }
1324 : } else {
1325 15150 : if (flags & 0xFE) {
1326 18 : errorf(pos - 1, "invalid memory limits flags");
1327 : }
1328 : }
1329 16611 : return flags;
1330 : }
1331 :
1332 20837 : void consume_resizable_limits(const char* name, const char* units,
1333 : uint32_t max_initial, uint32_t* initial,
1334 : bool* has_max, uint32_t max_maximum,
1335 : uint32_t* maximum, uint8_t flags) {
1336 27081 : const byte* pos = pc();
1337 41689 : *initial = consume_u32v("initial size");
1338 20852 : *has_max = false;
1339 20852 : if (*initial > max_initial) {
1340 : errorf(pos,
1341 : "initial %s size (%u %s) is larger than implementation limit (%u)",
1342 54 : name, *initial, units, max_initial);
1343 : }
1344 20860 : if (flags & 1) {
1345 6244 : *has_max = true;
1346 : pos = pc();
1347 6245 : *maximum = consume_u32v("maximum size");
1348 6245 : if (*maximum > max_maximum) {
1349 : errorf(
1350 : pos,
1351 : "maximum %s size (%u %s) is larger than implementation limit (%u)",
1352 55 : name, *maximum, units, max_maximum);
1353 : }
1354 6245 : if (*maximum < *initial) {
1355 : errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
1356 18 : name, *maximum, units, *initial, units);
1357 : }
1358 : } else {
1359 14616 : *has_max = false;
1360 14616 : *maximum = max_initial;
1361 : }
1362 20861 : }
1363 :
1364 1078092 : bool expect_u8(const char* name, uint8_t expected) {
1365 1078092 : const byte* pos = pc();
1366 1078092 : uint8_t value = consume_u8(name);
1367 1078094 : if (value != expected) {
1368 748 : errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
1369 748 : return false;
1370 : }
1371 : return true;
1372 : }
1373 :
1374 446320 : WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
1375 892313 : const byte* pos = pc();
1376 446320 : uint8_t opcode = consume_u8("opcode");
1377 : WasmInitExpr expr;
1378 : uint32_t len = 0;
1379 446320 : switch (opcode) {
1380 : case kExprGetGlobal: {
1381 418 : GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
1382 836 : if (module->globals.size() <= imm.index) {
1383 18 : error("global index is out of bounds");
1384 18 : expr.kind = WasmInitExpr::kNone;
1385 18 : expr.val.i32_const = 0;
1386 18 : break;
1387 : }
1388 : WasmGlobal* global = &module->globals[imm.index];
1389 400 : if (global->mutability || !global->imported) {
1390 : error(
1391 : "only immutable imported globals can be used in initializer "
1392 20 : "expressions");
1393 20 : expr.kind = WasmInitExpr::kNone;
1394 20 : expr.val.i32_const = 0;
1395 20 : break;
1396 : }
1397 380 : expr.kind = WasmInitExpr::kGlobalIndex;
1398 380 : expr.val.global_index = imm.index;
1399 380 : len = imm.length;
1400 380 : break;
1401 : }
1402 : case kExprI32Const: {
1403 : ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
1404 8455 : expr.kind = WasmInitExpr::kI32Const;
1405 8455 : expr.val.i32_const = imm.value;
1406 8455 : len = imm.length;
1407 : break;
1408 : }
1409 : case kExprF32Const: {
1410 436080 : ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
1411 436080 : expr.kind = WasmInitExpr::kF32Const;
1412 436080 : expr.val.f32_const = imm.value;
1413 436080 : len = imm.length;
1414 : break;
1415 : }
1416 : case kExprI64Const: {
1417 : ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
1418 355 : expr.kind = WasmInitExpr::kI64Const;
1419 355 : expr.val.i64_const = imm.value;
1420 355 : len = imm.length;
1421 : break;
1422 : }
1423 : case kExprF64Const: {
1424 685 : ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
1425 685 : expr.kind = WasmInitExpr::kF64Const;
1426 685 : expr.val.f64_const = imm.value;
1427 685 : len = imm.length;
1428 : break;
1429 : }
1430 : case kExprRefNull: {
1431 128 : if (enabled_features_.anyref) {
1432 128 : expr.kind = WasmInitExpr::kAnyRefConst;
1433 : len = 0;
1434 128 : break;
1435 : }
1436 : V8_FALLTHROUGH;
1437 : }
1438 : default: {
1439 199 : error("invalid opcode in initialization expression");
1440 199 : expr.kind = WasmInitExpr::kNone;
1441 199 : expr.val.i32_const = 0;
1442 : }
1443 : }
1444 446320 : consume_bytes(len, "init code");
1445 446320 : if (!expect_u8("end opcode", kExprEnd)) {
1446 619 : expr.kind = WasmInitExpr::kNone;
1447 : }
1448 446320 : if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
1449 : errorf(pos, "type error in init expression, expected %s, got %s",
1450 : ValueTypes::TypeName(expected),
1451 237 : ValueTypes::TypeName(TypeOf(module, expr)));
1452 : }
1453 446320 : return expr;
1454 : }
1455 :
1456 : // Read a mutability flag
1457 443939 : bool consume_mutability() {
1458 443939 : byte val = consume_u8("mutability");
1459 443939 : if (val > 1) error(pc_ - 1, "invalid mutability");
1460 443939 : return val != 0;
1461 : }
1462 :
1463 : // Reads a single 8-bit integer, interpreting it as a local type.
1464 1428839 : ValueType consume_value_type() {
1465 1428839 : byte val = consume_u8("value type");
1466 : ValueTypeCode t = static_cast<ValueTypeCode>(val);
1467 1428853 : switch (t) {
1468 : case kLocalI32:
1469 : return kWasmI32;
1470 : case kLocalI64:
1471 38086 : return kWasmI64;
1472 : case kLocalF32:
1473 740494 : return kWasmF32;
1474 : case kLocalF64:
1475 312258 : return kWasmF64;
1476 : default:
1477 930 : if (origin_ == kWasmOrigin) {
1478 930 : switch (t) {
1479 : case kLocalS128:
1480 36 : if (enabled_features_.simd) return kWasmS128;
1481 : break;
1482 : case kLocalAnyFunc:
1483 80 : if (enabled_features_.anyref) return kWasmAnyFunc;
1484 : break;
1485 : case kLocalAnyRef:
1486 785 : if (enabled_features_.anyref) return kWasmAnyRef;
1487 : break;
1488 : default:
1489 : break;
1490 : }
1491 : }
1492 53 : error(pc_ - 1, "invalid local type");
1493 53 : return kWasmStmt;
1494 : }
1495 : }
1496 :
1497 : // Reads a single 8-bit integer, interpreting it as a reference type.
1498 4235 : ValueType consume_reference_type() {
1499 4235 : byte val = consume_u8("reference type");
1500 : ValueTypeCode t = static_cast<ValueTypeCode>(val);
1501 4235 : switch (t) {
1502 : case kLocalAnyFunc:
1503 : return kWasmAnyFunc;
1504 : case kLocalAnyRef:
1505 3 : if (!enabled_features_.anyref) {
1506 : error(pc_ - 1,
1507 0 : "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
1508 : }
1509 : return kWasmAnyRef;
1510 : default:
1511 : break;
1512 : }
1513 2 : error(pc_ - 1, "invalid reference type");
1514 2 : return kWasmStmt;
1515 : }
1516 :
1517 631773 : FunctionSig* consume_sig(Zone* zone) {
1518 631773 : if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
1519 : // parse parameter types
1520 : uint32_t param_count =
1521 631644 : consume_count("param count", kV8MaxWasmFunctionParams);
1522 631641 : if (failed()) return nullptr;
1523 : std::vector<ValueType> params;
1524 2521396 : for (uint32_t i = 0; ok() && i < param_count; ++i) {
1525 629050 : ValueType param = consume_value_type();
1526 629059 : params.push_back(param);
1527 : }
1528 : std::vector<ValueType> returns;
1529 : // parse return types
1530 : const size_t max_return_count = enabled_features_.mv
1531 : ? kV8MaxWasmFunctionMultiReturns
1532 631648 : : kV8MaxWasmFunctionReturns;
1533 631648 : uint32_t return_count = consume_count("return count", max_return_count);
1534 631649 : if (failed()) return nullptr;
1535 1343267 : for (uint32_t i = 0; ok() && i < return_count; ++i) {
1536 355853 : ValueType ret = consume_value_type();
1537 355858 : returns.push_back(ret);
1538 : }
1539 :
1540 631552 : if (failed()) return nullptr;
1541 :
1542 : // FunctionSig stores the return types first.
1543 631538 : ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
1544 : uint32_t b = 0;
1545 987387 : for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
1546 1258040 : for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
1547 :
1548 1263074 : return new (zone) FunctionSig(return_count, param_count, buffer);
1549 : }
1550 :
1551 : // Consume the attribute field of an exception.
1552 575 : uint32_t consume_exception_attribute() {
1553 575 : const byte* pos = pc_;
1554 575 : uint32_t attribute = consume_u32v("exception attribute");
1555 575 : if (attribute != kExceptionAttribute) {
1556 1 : errorf(pos, "exception attribute %u not supported", attribute);
1557 1 : return 0;
1558 : }
1559 : return attribute;
1560 : }
1561 :
1562 4793 : void consume_segment_header(const char* name, bool* is_active,
1563 : uint32_t* index, WasmInitExpr* offset) {
1564 4793 : const byte* pos = pc();
1565 : // In the MVP, this is a table or memory index field that must be 0, but
1566 : // we've repurposed it as a flags field in the bulk memory proposal.
1567 : uint32_t flags;
1568 4793 : if (enabled_features_.bulk_memory) {
1569 176 : flags = consume_u32v("flags");
1570 176 : if (failed()) return;
1571 : } else {
1572 4617 : flags = consume_u32v(name);
1573 4617 : if (failed()) return;
1574 :
1575 4617 : if (flags != 0) {
1576 2 : errorf(pos, "illegal %s %u != 0", name, flags);
1577 2 : return;
1578 : }
1579 : }
1580 :
1581 : bool read_index;
1582 : bool read_offset;
1583 4791 : if (flags == SegmentFlags::kActiveNoIndex) {
1584 4686 : *is_active = true;
1585 : read_index = false;
1586 : read_offset = true;
1587 105 : } else if (flags == SegmentFlags::kPassive) {
1588 96 : *is_active = false;
1589 : read_index = false;
1590 : read_offset = false;
1591 9 : } else if (flags == SegmentFlags::kActiveWithIndex) {
1592 9 : *is_active = true;
1593 : read_index = true;
1594 : read_offset = true;
1595 : } else {
1596 0 : errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
1597 0 : return;
1598 : }
1599 :
1600 4791 : if (read_index) {
1601 18 : *index = consume_u32v(name);
1602 : } else {
1603 4782 : *index = 0;
1604 : }
1605 :
1606 4791 : if (read_offset) {
1607 4695 : *offset = consume_init_expr(module_.get(), kWasmI32);
1608 : }
1609 : }
1610 : };
1611 :
1612 315340 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
1613 : const byte* module_start, const byte* module_end,
1614 : bool verify_functions, ModuleOrigin origin,
1615 : Counters* counters,
1616 : AccountingAllocator* allocator) {
1617 : auto counter =
1618 315340 : SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
1619 : TimedHistogramScope wasm_decode_module_time_scope(counter);
1620 315358 : size_t size = module_end - module_start;
1621 315358 : CHECK_LE(module_start, module_end);
1622 315358 : if (size >= kV8MaxWasmModuleSize) {
1623 : return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
1624 0 : kV8MaxWasmModuleSize, size}};
1625 : }
1626 : // TODO(bradnelson): Improve histogram handling of size_t.
1627 : auto size_counter =
1628 315358 : SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
1629 315358 : size_counter->AddSample(static_cast<int>(size));
1630 : // Signatures are stored in zone memory, which have the same lifetime
1631 : // as the {module}.
1632 630723 : ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
1633 : ModuleResult result =
1634 946086 : decoder.DecodeModule(counters, allocator, verify_functions);
1635 : // TODO(bradnelson): Improve histogram handling of size_t.
1636 : // TODO(titzer): this isn't accurate, since it doesn't count the data
1637 : // allocated on the C++ heap.
1638 : // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
1639 315360 : if (result.ok()) {
1640 287928 : auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
1641 : module_peak_memory_bytes);
1642 : peak_counter->AddSample(
1643 575856 : static_cast<int>(result.value()->signature_zone->allocation_size()));
1644 : }
1645 : return result;
1646 : }
1647 :
1648 424 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
1649 424 : : enabled_features_(enabled) {}
1650 :
1651 : ModuleDecoder::~ModuleDecoder() = default;
1652 :
1653 732 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
1654 732 : return impl_->shared_module();
1655 : }
1656 :
1657 389 : void ModuleDecoder::StartDecoding(Counters* counters,
1658 : AccountingAllocator* allocator,
1659 : ModuleOrigin origin) {
1660 : DCHECK_NULL(impl_);
1661 389 : impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
1662 389 : impl_->StartDecoding(counters, allocator);
1663 389 : }
1664 :
1665 389 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
1666 : uint32_t offset) {
1667 778 : impl_->DecodeModuleHeader(bytes, offset);
1668 389 : }
1669 :
1670 860 : void ModuleDecoder::DecodeSection(SectionCode section_code,
1671 : Vector<const uint8_t> bytes, uint32_t offset,
1672 : bool verify_functions) {
1673 1720 : impl_->DecodeSection(section_code, bytes, offset, verify_functions);
1674 860 : }
1675 :
1676 503 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
1677 : uint32_t offset, bool verify_functions) {
1678 1006 : impl_->DecodeFunctionBody(index, length, offset, verify_functions);
1679 503 : }
1680 :
1681 243 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
1682 : uint32_t offset) {
1683 243 : return impl_->CheckFunctionsCount(functions_count, offset);
1684 : }
1685 :
1686 214 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
1687 642 : return impl_->FinishDecoding(verify_functions);
1688 : }
1689 :
1690 126038 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
1691 : const byte* end) {
1692 37514 : WireBytesRef string = consume_string(decoder, true, "section name");
1693 67417 : if (decoder.failed() || decoder.pc() > end) {
1694 : return kUnknownSectionCode;
1695 : }
1696 : const byte* section_name_start =
1697 58634 : decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
1698 :
1699 : TRACE(" +%d section name : \"%.*s\"\n",
1700 : static_cast<int>(section_name_start - decoder.start()),
1701 : string.length() < 20 ? string.length() : 20, section_name_start);
1702 :
1703 57373 : if (string.length() == num_chars(kNameString) &&
1704 : strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
1705 28056 : num_chars(kNameString)) == 0) {
1706 : return kNameSectionCode;
1707 1478 : } else if (string.length() == num_chars(kSourceMappingURLString) &&
1708 : strncmp(reinterpret_cast<const char*>(section_name_start),
1709 : kSourceMappingURLString,
1710 163 : num_chars(kSourceMappingURLString)) == 0) {
1711 : return kSourceMappingURLSectionCode;
1712 : }
1713 1296 : return kUnknownSectionCode;
1714 : }
1715 :
1716 2498 : bool ModuleDecoder::ok() { return impl_->ok(); }
1717 :
1718 262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
1719 : Zone* zone, const byte* start,
1720 : const byte* end) {
1721 262 : ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1722 262 : return decoder.DecodeFunctionSignature(zone, start);
1723 : }
1724 :
1725 22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
1726 : const byte* start, const byte* end) {
1727 22 : AccountingAllocator allocator;
1728 44 : ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1729 22 : return decoder.DecodeInitExpr(start);
1730 : }
1731 :
1732 1 : FunctionResult DecodeWasmFunctionForTesting(
1733 : const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
1734 : const WasmModule* module, const byte* function_start,
1735 : const byte* function_end, Counters* counters) {
1736 1 : size_t size = function_end - function_start;
1737 1 : CHECK_LE(function_start, function_end);
1738 1 : auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
1739 : function_size_bytes);
1740 : // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
1741 1 : size_histogram->AddSample(static_cast<int>(size));
1742 1 : if (size > kV8MaxWasmFunctionSize) {
1743 : return FunctionResult{WasmError{0,
1744 : "size > maximum function size (%zu): %zu",
1745 0 : kV8MaxWasmFunctionSize, size}};
1746 : }
1747 1 : ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
1748 : decoder.SetCounters(counters);
1749 : return decoder.DecodeSingleFunction(zone, wire_bytes, module,
1750 3 : base::make_unique<WasmFunction>());
1751 : }
1752 :
1753 159 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
1754 : const byte* tables_end) {
1755 : AsmJsOffsets table;
1756 :
1757 : Decoder decoder(tables_start, tables_end);
1758 : uint32_t functions_count = decoder.consume_u32v("functions count");
1759 : // Reserve space for the entries, taking care of invalid input.
1760 159 : if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
1761 159 : table.reserve(functions_count);
1762 : }
1763 :
1764 756 : for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1765 : uint32_t size = decoder.consume_u32v("table size");
1766 378 : if (size == 0) {
1767 159 : table.emplace_back();
1768 159 : continue;
1769 : }
1770 219 : if (!decoder.checkAvailable(size)) {
1771 0 : decoder.error("illegal asm function offset table size");
1772 : }
1773 219 : const byte* table_end = decoder.pc() + size;
1774 : uint32_t locals_size = decoder.consume_u32v("locals size");
1775 219 : int function_start_position = decoder.consume_u32v("function start pos");
1776 219 : int last_byte_offset = locals_size;
1777 : int last_asm_position = function_start_position;
1778 : std::vector<AsmJsOffsetEntry> func_asm_offsets;
1779 219 : func_asm_offsets.reserve(size / 4); // conservative estimation
1780 : // Add an entry for the stack check, associated with position 0.
1781 : func_asm_offsets.push_back(
1782 438 : {0, function_start_position, function_start_position});
1783 729 : while (decoder.ok() && decoder.pc() < table_end) {
1784 291 : last_byte_offset += decoder.consume_u32v("byte offset delta");
1785 : int call_position =
1786 291 : last_asm_position + decoder.consume_i32v("call position delta");
1787 : int to_number_position =
1788 291 : call_position + decoder.consume_i32v("to_number position delta");
1789 : last_asm_position = to_number_position;
1790 : func_asm_offsets.push_back(
1791 582 : {last_byte_offset, call_position, to_number_position});
1792 : }
1793 219 : if (decoder.pc() != table_end) {
1794 0 : decoder.error("broken asm offset table");
1795 : }
1796 : table.push_back(std::move(func_asm_offsets));
1797 : }
1798 159 : if (decoder.more()) decoder.error("unexpected additional bytes");
1799 :
1800 477 : return decoder.toResult(std::move(table));
1801 : }
1802 :
1803 56 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
1804 : const byte* end) {
1805 : Decoder decoder(start, end);
1806 56 : decoder.consume_bytes(4, "wasm magic");
1807 56 : decoder.consume_bytes(4, "wasm version");
1808 :
1809 : std::vector<CustomSectionOffset> result;
1810 :
1811 207 : while (decoder.more()) {
1812 : byte section_code = decoder.consume_u8("section code");
1813 : uint32_t section_length = decoder.consume_u32v("section length");
1814 : uint32_t section_start = decoder.pc_offset();
1815 160 : if (section_code != 0) {
1816 : // Skip known sections.
1817 2 : decoder.consume_bytes(section_length, "section bytes");
1818 2 : continue;
1819 : }
1820 : uint32_t name_length = decoder.consume_u32v("name length");
1821 : uint32_t name_offset = decoder.pc_offset();
1822 158 : decoder.consume_bytes(name_length, "section name");
1823 : uint32_t payload_offset = decoder.pc_offset();
1824 158 : if (section_length < (payload_offset - section_start)) {
1825 9 : decoder.error("invalid section length");
1826 9 : break;
1827 : }
1828 149 : uint32_t payload_length = section_length - (payload_offset - section_start);
1829 149 : decoder.consume_bytes(payload_length);
1830 149 : if (decoder.failed()) break;
1831 : result.push_back({{section_start, section_length},
1832 : {name_offset, name_length},
1833 149 : {payload_offset, payload_length}});
1834 : }
1835 :
1836 56 : return result;
1837 : }
1838 :
1839 : namespace {
1840 :
1841 139775 : bool FindNameSection(Decoder& decoder) {
1842 : static constexpr int kModuleHeaderSize = 8;
1843 139775 : decoder.consume_bytes(kModuleHeaderSize, "module header");
1844 :
1845 : WasmSectionIterator section_iter(decoder);
1846 :
1847 279205 : while (decoder.ok() && section_iter.more() &&
1848 45227 : section_iter.section_code() != kNameSectionCode) {
1849 41976 : section_iter.advance(true);
1850 : }
1851 279550 : if (!section_iter.more()) return false;
1852 :
1853 : // Reset the decoder to not read beyond the name section end.
1854 : decoder.Reset(section_iter.payload(), decoder.pc_offset());
1855 3251 : return true;
1856 : }
1857 :
1858 : } // namespace
1859 :
1860 139750 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
1861 : std::unordered_map<uint32_t, WireBytesRef>* names) {
1862 : DCHECK_NOT_NULL(names);
1863 : DCHECK(names->empty());
1864 :
1865 : Decoder decoder(module_start, module_end);
1866 279500 : if (!FindNameSection(decoder)) return;
1867 :
1868 6467 : while (decoder.ok() && decoder.more()) {
1869 : uint8_t name_type = decoder.consume_u8("name type");
1870 3241 : if (name_type & 0x80) break; // no varuint7
1871 :
1872 : uint32_t name_payload_len = decoder.consume_u32v("name payload length");
1873 3241 : if (!decoder.checkAvailable(name_payload_len)) break;
1874 :
1875 3241 : if (name_type != NameSectionKindCode::kFunction) {
1876 25 : decoder.consume_bytes(name_payload_len, "name subsection payload");
1877 25 : continue;
1878 : }
1879 : uint32_t functions_count = decoder.consume_u32v("functions count");
1880 :
1881 40148 : for (; decoder.ok() && functions_count > 0; --functions_count) {
1882 : uint32_t function_index = decoder.consume_u32v("function index");
1883 16858 : WireBytesRef name = consume_string(decoder, false, "function name");
1884 :
1885 : // Be lenient with errors in the name section: Ignore non-UTF8 names. You
1886 : // can even assign to the same function multiple times (last valid one
1887 : // wins).
1888 33716 : if (decoder.ok() && validate_utf8(&decoder, name)) {
1889 33698 : names->insert(std::make_pair(function_index, name));
1890 : }
1891 : }
1892 : }
1893 : }
1894 :
1895 25 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
1896 : LocalNames* result) {
1897 : DCHECK_NOT_NULL(result);
1898 : DCHECK(result->names.empty());
1899 :
1900 : Decoder decoder(module_start, module_end);
1901 50 : if (!FindNameSection(decoder)) return;
1902 :
1903 55 : while (decoder.ok() && decoder.more()) {
1904 : uint8_t name_type = decoder.consume_u8("name type");
1905 30 : if (name_type & 0x80) break; // no varuint7
1906 :
1907 : uint32_t name_payload_len = decoder.consume_u32v("name payload length");
1908 30 : if (!decoder.checkAvailable(name_payload_len)) break;
1909 :
1910 30 : if (name_type != NameSectionKindCode::kLocal) {
1911 25 : decoder.consume_bytes(name_payload_len, "name subsection payload");
1912 25 : continue;
1913 : }
1914 :
1915 : uint32_t local_names_count = decoder.consume_u32v("local names count");
1916 10 : for (uint32_t i = 0; i < local_names_count; ++i) {
1917 : uint32_t func_index = decoder.consume_u32v("function index");
1918 5 : if (func_index > kMaxInt) continue;
1919 5 : result->names.emplace_back(static_cast<int>(func_index));
1920 : LocalNamesPerFunction& func_names = result->names.back();
1921 : result->max_function_index =
1922 10 : std::max(result->max_function_index, func_names.function_index);
1923 : uint32_t num_names = decoder.consume_u32v("namings count");
1924 20 : for (uint32_t k = 0; k < num_names; ++k) {
1925 : uint32_t local_index = decoder.consume_u32v("local index");
1926 15 : WireBytesRef name = consume_string(decoder, true, "local name");
1927 15 : if (!decoder.ok()) break;
1928 15 : if (local_index > kMaxInt) continue;
1929 : func_names.max_local_index =
1930 30 : std::max(func_names.max_local_index, static_cast<int>(local_index));
1931 15 : func_names.names.emplace_back(static_cast<int>(local_index), name);
1932 : }
1933 : }
1934 : }
1935 : }
1936 :
1937 : #undef TRACE
1938 :
1939 : } // namespace wasm
1940 : } // namespace internal
1941 183867 : } // namespace v8
|