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 : constexpr char kCompilationHintsString[] = "compilationHints";
34 :
35 : template <size_t N>
36 : constexpr size_t num_chars(const char (&)[N]) {
37 : return N - 1; // remove null character at end.
38 : }
39 :
40 : const char* ExternalKindName(ImportExportKindCode kind) {
41 656 : switch (kind) {
42 : case kExternalFunction:
43 : return "function";
44 : case kExternalTable:
45 : return "table";
46 : case kExternalMemory:
47 : return "memory";
48 : case kExternalGlobal:
49 : return "global";
50 : case kExternalException:
51 : return "exception";
52 : }
53 : return "unknown";
54 : }
55 :
56 : } // namespace
57 :
58 31 : const char* SectionName(SectionCode code) {
59 31 : switch (code) {
60 : case kUnknownSectionCode:
61 : return "Unknown";
62 : case kTypeSectionCode:
63 0 : return "Type";
64 : case kImportSectionCode:
65 0 : return "Import";
66 : case kFunctionSectionCode:
67 0 : return "Function";
68 : case kTableSectionCode:
69 0 : return "Table";
70 : case kMemorySectionCode:
71 0 : return "Memory";
72 : case kGlobalSectionCode:
73 2 : return "Global";
74 : case kExportSectionCode:
75 2 : return "Export";
76 : case kStartSectionCode:
77 8 : return "Start";
78 : case kCodeSectionCode:
79 1 : return "Code";
80 : case kElementSectionCode:
81 2 : return "Element";
82 : case kDataSectionCode:
83 0 : return "Data";
84 : case kExceptionSectionCode:
85 12 : return "Exception";
86 : case kDataCountSectionCode:
87 4 : return "DataCount";
88 : case kNameSectionCode:
89 0 : return kNameString;
90 : case kSourceMappingURLSectionCode:
91 0 : return kSourceMappingURLString;
92 : case kCompilationHintsSectionCode:
93 0 : return kCompilationHintsString;
94 : default:
95 0 : return "<unknown>";
96 : }
97 : }
98 :
99 : namespace {
100 :
101 : bool validate_utf8(Decoder* decoder, WireBytesRef string) {
102 30236 : return unibrow::Utf8::ValidateEncoding(
103 : decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
104 15118 : string.length());
105 : }
106 :
107 445984 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
108 445984 : switch (expr.kind) {
109 : case WasmInitExpr::kNone:
110 : return kWasmStmt;
111 : case WasmInitExpr::kGlobalIndex:
112 297 : return expr.val.global_index < module->globals.size()
113 : ? module->globals[expr.val.global_index].type
114 594 : : kWasmStmt;
115 : case WasmInitExpr::kI32Const:
116 : return kWasmI32;
117 : case WasmInitExpr::kI64Const:
118 : return kWasmI64;
119 : case WasmInitExpr::kF32Const:
120 : return kWasmF32;
121 : case WasmInitExpr::kF64Const:
122 : return kWasmF64;
123 : case WasmInitExpr::kRefNullConst:
124 : return kWasmNullRef;
125 : default:
126 0 : UNREACHABLE();
127 : }
128 : }
129 :
130 : // Reads a length-prefixed string, checking that it is within bounds. Returns
131 : // the offset of the string, and the length as an out parameter.
132 876100 : WireBytesRef consume_string(Decoder& decoder, bool validate_utf8,
133 : const char* name) {
134 : uint32_t length = decoder.consume_u32v("string length");
135 : uint32_t offset = decoder.pc_offset();
136 : const byte* string_start = decoder.pc();
137 : // Consume bytes before validation to guarantee that the string is not oob.
138 876104 : if (length > 0) {
139 865064 : decoder.consume_bytes(length, name);
140 1712636 : if (decoder.ok() && validate_utf8 &&
141 847574 : !unibrow::Utf8::ValidateEncoding(string_start, length)) {
142 8642 : decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
143 : }
144 : }
145 876101 : return {offset, decoder.failed() ? 0 : length};
146 : }
147 :
148 : // An iterator over the sections in a wasm binary module.
149 : // Automatically skips all unknown sections.
150 : class WasmSectionIterator {
151 : public:
152 : explicit WasmSectionIterator(Decoder& decoder)
153 : : decoder_(decoder),
154 : section_code_(kUnknownSectionCode),
155 : section_start_(decoder.pc()),
156 404609 : section_end_(decoder.pc()) {
157 404609 : next();
158 : }
159 :
160 1743515 : inline bool more() const { return decoder_.ok() && decoder_.more(); }
161 :
162 : inline SectionCode section_code() const { return section_code_; }
163 :
164 : inline const byte* section_start() const { return section_start_; }
165 :
166 : inline uint32_t section_length() const {
167 472 : return static_cast<uint32_t>(section_end_ - section_start_);
168 : }
169 :
170 : inline Vector<const uint8_t> payload() const {
171 1297803 : return {payload_start_, payload_length()};
172 : }
173 :
174 : inline const byte* payload_start() const { return payload_start_; }
175 :
176 : inline uint32_t payload_length() const {
177 2587464 : return static_cast<uint32_t>(section_end_ - payload_start_);
178 : }
179 :
180 : inline const byte* section_end() const { return section_end_; }
181 :
182 : // Advances to the next section, checking that decoding the current section
183 : // stopped at {section_end_}.
184 1335787 : void advance(bool move_to_section_end = false) {
185 1335787 : if (move_to_section_end && decoder_.pc() < section_end_) {
186 1334175 : decoder_.consume_bytes(
187 2668350 : static_cast<uint32_t>(section_end_ - decoder_.pc()));
188 : }
189 1335786 : if (decoder_.pc() != section_end_) {
190 472 : const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
191 472 : decoder_.errorf(decoder_.pc(),
192 : "section was %s than expected size "
193 : "(%u bytes expected, %zu decoded)",
194 : msg, section_length(),
195 944 : static_cast<size_t>(decoder_.pc() - section_start_));
196 : }
197 1335786 : next();
198 1335794 : }
199 :
200 : private:
201 : Decoder& decoder_;
202 : SectionCode section_code_;
203 : const byte* section_start_;
204 : const byte* payload_start_;
205 : const byte* section_end_;
206 :
207 : // Reads the section code/name at the current position and sets up
208 : // the embedder fields.
209 1740388 : void next() {
210 1740388 : if (!decoder_.more()) {
211 281441 : section_code_ = kUnknownSectionCode;
212 281441 : return;
213 : }
214 1458947 : section_start_ = decoder_.pc();
215 : uint8_t section_code = decoder_.consume_u8("section code");
216 : // Read and check the section size.
217 1458945 : uint32_t section_length = decoder_.consume_u32v("section length");
218 :
219 1458954 : payload_start_ = decoder_.pc();
220 1458959 : if (decoder_.checkAvailable(section_length)) {
221 : // Get the limit of the section within the module.
222 1347171 : section_end_ = payload_start_ + section_length;
223 : } else {
224 : // The section would extend beyond the end of the module.
225 111788 : section_end_ = payload_start_;
226 : }
227 :
228 1458959 : if (section_code == kUnknownSectionCode) {
229 : // Check for the known "name", "sourceMappingURL", or "compilationHints"
230 : // section.
231 : section_code =
232 35902 : ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
233 : // As a side effect, the above function will forward the decoder to after
234 : // the identifier string.
235 35895 : payload_start_ = decoder_.pc();
236 1423057 : } else if (!IsValidSectionCode(section_code)) {
237 110904 : decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
238 110904 : section_code);
239 : section_code = kUnknownSectionCode;
240 : }
241 1458955 : section_code_ = decoder_.failed() ? kUnknownSectionCode
242 1458955 : : static_cast<SectionCode>(section_code);
243 :
244 1458955 : if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
245 : // skip to the end of the unknown section.
246 3840 : uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
247 3840 : decoder_.consume_bytes(remaining, "section payload");
248 : }
249 : }
250 : };
251 :
252 : } // namespace
253 :
254 : // The main logic for decoding the bytes of a module.
255 571731 : class ModuleDecoderImpl : public Decoder {
256 : public:
257 : explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
258 : : Decoder(nullptr, nullptr),
259 : enabled_features_(enabled),
260 1224 : origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
261 :
262 285256 : ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start,
263 : const byte* module_end, ModuleOrigin origin)
264 : : Decoder(module_start, module_end),
265 : enabled_features_(enabled),
266 855768 : origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
267 285256 : if (end_ < start_) {
268 0 : error(start_, "end is less than start");
269 0 : end_ = start_;
270 : }
271 285256 : }
272 :
273 15569 : void onFirstError() override {
274 15569 : pc_ = end_; // On error, terminate section decoding loop.
275 15569 : }
276 :
277 : void DumpModule(const Vector<const byte> module_bytes) {
278 : std::string path;
279 : if (FLAG_dump_wasm_module_path) {
280 : path = FLAG_dump_wasm_module_path;
281 : if (path.size() &&
282 : !base::OS::isDirectorySeparator(path[path.size() - 1])) {
283 : path += base::OS::DirectorySeparator();
284 : }
285 : }
286 : // File are named `HASH.{ok,failed}.wasm`.
287 : size_t hash = base::hash_range(module_bytes.start(), module_bytes.end());
288 : EmbeddedVector<char, 32> buf;
289 : SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed");
290 : std::string name(buf.start());
291 : if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
292 : if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) !=
293 : 1) {
294 : OFStream os(stderr);
295 : os << "Error while dumping wasm file" << std::endl;
296 : }
297 : fclose(wasm_file);
298 : }
299 : }
300 :
301 285375 : void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
302 285375 : CHECK_NULL(module_);
303 : SetCounters(counters);
304 570756 : module_.reset(
305 856133 : new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
306 285379 : module_->initial_pages = 0;
307 285379 : module_->maximum_pages = 0;
308 285379 : module_->mem_export = false;
309 285379 : module_->origin = origin_;
310 285379 : }
311 :
312 285376 : void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
313 285376 : if (failed()) return;
314 285378 : Reset(bytes, offset);
315 :
316 285374 : const byte* pos = pc_;
317 : uint32_t magic_word = consume_u32("wasm magic");
318 : #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
319 285377 : if (magic_word != kWasmMagic) {
320 21729 : errorf(pos,
321 : "expected magic word %02x %02x %02x %02x, "
322 : "found %02x %02x %02x %02x",
323 21729 : BYTES(kWasmMagic), BYTES(magic_word));
324 : }
325 :
326 285377 : pos = pc_;
327 : {
328 : uint32_t magic_version = consume_u32("wasm version");
329 285378 : if (magic_version != kWasmVersion) {
330 22905 : errorf(pos,
331 : "expected version %02x %02x %02x %02x, "
332 : "found %02x %02x %02x %02x",
333 22905 : BYTES(kWasmVersion), BYTES(magic_version));
334 : }
335 : }
336 : #undef BYTES
337 : }
338 :
339 657 : bool CheckSectionOrder(SectionCode section_code,
340 : SectionCode prev_section_code,
341 : SectionCode next_section_code) {
342 657 : if (next_ordered_section_ > next_section_code) {
343 3 : errorf(pc(), "The %s section must appear before the %s section",
344 3 : SectionName(section_code), SectionName(next_section_code));
345 3 : return false;
346 : }
347 654 : if (next_ordered_section_ <= prev_section_code) {
348 636 : next_ordered_section_ = prev_section_code + 1;
349 : }
350 : return true;
351 : }
352 :
353 658 : bool CheckUnorderedSection(SectionCode section_code) {
354 658 : if (has_seen_unordered_section(section_code)) {
355 1 : errorf(pc(), "Multiple %s sections not allowed",
356 1 : SectionName(section_code));
357 1 : return false;
358 : }
359 : set_seen_unordered_section(section_code);
360 657 : return true;
361 : }
362 :
363 1292992 : void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
364 : uint32_t offset, bool verify_functions = true) {
365 1292992 : if (failed()) return;
366 1292996 : Reset(bytes, offset);
367 : TRACE("Section: %s\n", SectionName(section_code));
368 : TRACE("Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()),
369 : static_cast<const void*>(bytes.end()));
370 :
371 : // Check if the section is out-of-order.
372 1293002 : if (section_code < next_ordered_section_ &&
373 : section_code < kFirstUnorderedSection) {
374 12 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
375 12 : return;
376 : }
377 :
378 1292990 : switch (section_code) {
379 : case kUnknownSectionCode:
380 : break;
381 : case kDataCountSectionCode:
382 52 : if (!CheckUnorderedSection(section_code)) return;
383 51 : if (!CheckSectionOrder(section_code, kElementSectionCode,
384 : kCodeSectionCode))
385 : return;
386 : break;
387 : case kExceptionSectionCode:
388 606 : if (!CheckUnorderedSection(section_code)) return;
389 606 : if (!CheckSectionOrder(section_code, kGlobalSectionCode,
390 : kExportSectionCode))
391 : return;
392 : break;
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 : case kSourceMappingURLSectionCode:
398 : // sourceMappingURL is a custom section and currently can occur anywhere
399 : // in the module. In case of multiple sourceMappingURL sections, all
400 : // except the first occurrence are ignored.
401 : case kCompilationHintsSectionCode:
402 : // TODO(frgossen): report out of place compilation hints section as a
403 : // warning.
404 : // Be lenient with placement of compilation hints section. All except
405 : // first occurrence after function section and before code section are
406 : // ignored.
407 : break;
408 : default:
409 1268595 : next_ordered_section_ = section_code + 1;
410 1268595 : break;
411 : }
412 :
413 1292982 : switch (section_code) {
414 : case kUnknownSectionCode:
415 : break;
416 : case kTypeSectionCode:
417 261017 : DecodeTypeSection();
418 261020 : break;
419 : case kImportSectionCode:
420 232264 : DecodeImportSection();
421 232261 : break;
422 : case kFunctionSectionCode:
423 259180 : DecodeFunctionSection();
424 259176 : break;
425 : case kTableSectionCode:
426 2576 : DecodeTableSection();
427 2576 : break;
428 : case kMemorySectionCode:
429 10941 : DecodeMemorySection();
430 10941 : break;
431 : case kGlobalSectionCode:
432 2923 : DecodeGlobalSection();
433 2923 : break;
434 : case kExportSectionCode:
435 234871 : DecodeExportSection();
436 234870 : break;
437 : case kStartSectionCode:
438 2774 : DecodeStartSection();
439 2774 : break;
440 : case kCodeSectionCode:
441 258458 : DecodeCodeSection(verify_functions);
442 258457 : break;
443 : case kElementSectionCode:
444 2246 : DecodeElementSection();
445 2246 : break;
446 : case kDataSectionCode:
447 1346 : DecodeDataSection();
448 1346 : break;
449 : case kNameSectionCode:
450 23578 : DecodeNameSection();
451 23573 : break;
452 : case kSourceMappingURLSectionCode:
453 8 : DecodeSourceMappingURLSection();
454 8 : break;
455 : case kCompilationHintsSectionCode:
456 145 : if (enabled_features_.compilation_hints) {
457 137 : DecodeCompilationHintsSection();
458 : } else {
459 : // Ignore this section when feature was disabled. It is an optional
460 : // custom section anyways.
461 8 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
462 : }
463 : break;
464 : case kDataCountSectionCode:
465 50 : if (enabled_features_.bulk_memory) {
466 : DecodeDataCountSection();
467 : } else {
468 2 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
469 : }
470 : break;
471 : case kExceptionSectionCode:
472 604 : if (enabled_features_.eh) {
473 594 : DecodeExceptionSection();
474 : } else {
475 10 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
476 : }
477 : break;
478 : default:
479 0 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
480 0 : return;
481 : }
482 :
483 1292971 : if (pc() != bytes.end()) {
484 132 : const char* msg = pc() < bytes.end() ? "shorter" : "longer";
485 132 : errorf(pc(),
486 : "section was %s than expected size "
487 : "(%zu bytes expected, %zu decoded)",
488 264 : msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
489 : }
490 : }
491 :
492 261015 : void DecodeTypeSection() {
493 261015 : uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
494 261020 : module_->signatures.reserve(signatures_count);
495 1396356 : for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
496 : TRACE("DecodeSignature[%d] module+%d\n", i,
497 : static_cast<int>(pc_ - start_));
498 567667 : FunctionSig* s = consume_sig(module_->signature_zone.get());
499 567667 : module_->signatures.push_back(s);
500 567667 : uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
501 567666 : module_->signature_ids.push_back(id);
502 : }
503 : module_->signature_map.Freeze();
504 261022 : }
505 :
506 232258 : void DecodeImportSection() {
507 : uint32_t import_table_count =
508 232258 : consume_count("imports count", kV8MaxWasmImports);
509 232262 : module_->import_table.reserve(import_table_count);
510 705383 : for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
511 : TRACE("DecodeImportTable[%d] module+%d\n", i,
512 : static_cast<int>(pc_ - start_));
513 :
514 473124 : module_->import_table.push_back({
515 : {0, 0}, // module_name
516 : {0, 0}, // field_name
517 : kExternalFunction, // kind
518 : 0 // index
519 : });
520 : WasmImport* import = &module_->import_table.back();
521 236563 : const byte* pos = pc_;
522 236563 : import->module_name = consume_string(*this, true, "module name");
523 236559 : import->field_name = consume_string(*this, true, "field name");
524 : import->kind =
525 236558 : static_cast<ImportExportKindCode>(consume_u8("import kind"));
526 236558 : switch (import->kind) {
527 : case kExternalFunction: {
528 : // ===== Imported function ===========================================
529 227674 : import->index = static_cast<uint32_t>(module_->functions.size());
530 227674 : module_->num_imported_functions++;
531 910696 : module_->functions.push_back({nullptr, // sig
532 227674 : import->index, // func_index
533 : 0, // sig_index
534 : {0, 0}, // code
535 : true, // imported
536 : false}); // exported
537 : WasmFunction* function = &module_->functions.back();
538 : function->sig_index =
539 227674 : consume_sig_index(module_.get(), &function->sig);
540 227674 : break;
541 : }
542 : case kExternalTable: {
543 : // ===== Imported table ==============================================
544 1564 : if (!AddTable(module_.get())) break;
545 1551 : import->index = static_cast<uint32_t>(module_->tables.size());
546 1551 : module_->num_imported_tables++;
547 1551 : module_->tables.emplace_back();
548 : WasmTable* table = &module_->tables.back();
549 1551 : table->imported = true;
550 1551 : ValueType type = consume_reference_type();
551 1551 : if (!enabled_features_.anyref) {
552 1489 : if (type != kWasmAnyFunc) {
553 0 : error(pc_ - 1, "invalid table type");
554 0 : break;
555 : }
556 : }
557 1551 : table->type = type;
558 1551 : uint8_t flags = validate_table_flags("element count");
559 1551 : consume_resizable_limits(
560 : "element count", "elements", FLAG_wasm_max_table_size,
561 : &table->initial_size, &table->has_maximum_size,
562 1551 : FLAG_wasm_max_table_size, &table->maximum_size, flags);
563 1551 : break;
564 : }
565 : case kExternalMemory: {
566 : // ===== Imported memory =============================================
567 4879 : if (!AddMemory(module_.get())) break;
568 4855 : uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
569 4858 : consume_resizable_limits(
570 : "memory", "pages", kSpecMaxWasmMemoryPages,
571 : &module_->initial_pages, &module_->has_maximum_pages,
572 4858 : kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
573 4860 : break;
574 : }
575 : case kExternalGlobal: {
576 : // ===== Imported global =============================================
577 2332 : import->index = static_cast<uint32_t>(module_->globals.size());
578 6996 : module_->globals.push_back(
579 : {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
580 : WasmGlobal* global = &module_->globals.back();
581 2332 : global->type = consume_value_type();
582 2332 : global->mutability = consume_mutability();
583 2332 : if (global->mutability) {
584 419 : module_->num_imported_mutable_globals++;
585 : }
586 : break;
587 : }
588 : case kExternalException: {
589 : // ===== Imported exception ==========================================
590 106 : if (!enabled_features_.eh) {
591 1 : errorf(pos, "unknown import kind 0x%02x", import->kind);
592 1 : break;
593 : }
594 105 : import->index = static_cast<uint32_t>(module_->exceptions.size());
595 105 : WasmExceptionSig* exception_sig = nullptr;
596 105 : consume_exception_attribute(); // Attribute ignored for now.
597 105 : consume_exception_sig_index(module_.get(), &exception_sig);
598 105 : module_->exceptions.emplace_back(exception_sig);
599 105 : break;
600 : }
601 : default:
602 0 : errorf(pos, "unknown import kind 0x%02x", import->kind);
603 0 : break;
604 : }
605 : }
606 232262 : }
607 :
608 259173 : void DecodeFunctionSection() {
609 : uint32_t functions_count =
610 259173 : consume_count("functions count", kV8MaxWasmFunctions);
611 : auto counter =
612 259177 : SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
613 259177 : counter->AddSample(static_cast<int>(functions_count));
614 : DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
615 : uint32_t total_function_count =
616 259179 : module_->num_imported_functions + functions_count;
617 259179 : module_->functions.reserve(total_function_count);
618 259179 : module_->num_declared_functions = functions_count;
619 1036173 : for (uint32_t i = 0; i < functions_count; ++i) {
620 388540 : uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
621 1165620 : module_->functions.push_back({nullptr, // sig
622 : func_index, // func_index
623 : 0, // sig_index
624 : {0, 0}, // code
625 : false, // imported
626 : false}); // exported
627 : WasmFunction* function = &module_->functions.back();
628 388540 : function->sig_index = consume_sig_index(module_.get(), &function->sig);
629 388539 : if (!ok()) return;
630 : }
631 : DCHECK_EQ(module_->functions.size(), total_function_count);
632 : }
633 :
634 2576 : void DecodeTableSection() {
635 : // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
636 : // implementation of AnyRef landed.
637 2576 : uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
638 2576 : uint32_t table_count = consume_count("table count", max_count);
639 :
640 7756 : for (uint32_t i = 0; ok() && i < table_count; i++) {
641 2606 : if (!AddTable(module_.get())) break;
642 2590 : module_->tables.emplace_back();
643 : WasmTable* table = &module_->tables.back();
644 2590 : table->type = consume_reference_type();
645 2590 : uint8_t flags = validate_table_flags("table elements");
646 2590 : consume_resizable_limits(
647 : "table elements", "elements", FLAG_wasm_max_table_size,
648 : &table->initial_size, &table->has_maximum_size,
649 2590 : FLAG_wasm_max_table_size, &table->maximum_size, flags);
650 : }
651 2576 : }
652 :
653 10941 : void DecodeMemorySection() {
654 10941 : uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
655 :
656 32643 : for (uint32_t i = 0; ok() && i < memory_count; i++) {
657 10891 : if (!AddMemory(module_.get())) break;
658 10851 : uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
659 10851 : consume_resizable_limits(
660 : "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
661 : &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
662 10851 : &module_->maximum_pages, flags);
663 : }
664 10941 : }
665 :
666 2923 : void DecodeGlobalSection() {
667 2923 : uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
668 2923 : uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
669 2923 : module_->globals.reserve(imported_globals + globals_count);
670 885755 : for (uint32_t i = 0; ok() && i < globals_count; ++i) {
671 : TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
672 : // Add an uninitialized global and pass a pointer to it.
673 1324248 : module_->globals.push_back(
674 : {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
675 : WasmGlobal* global = &module_->globals.back();
676 441416 : DecodeGlobalInModule(module_.get(), i + imported_globals, global);
677 : }
678 2923 : if (ok()) CalculateGlobalOffsets(module_.get());
679 2923 : }
680 :
681 234866 : void DecodeExportSection() {
682 : uint32_t export_table_count =
683 234866 : consume_count("exports count", kV8MaxWasmExports);
684 234868 : module_->export_table.reserve(export_table_count);
685 938312 : for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
686 : TRACE("DecodeExportTable[%d] module+%d\n", i,
687 : static_cast<int>(pc_ - start_));
688 :
689 703449 : module_->export_table.push_back({
690 : {0, 0}, // name
691 : kExternalFunction, // kind
692 : 0 // index
693 : });
694 : WasmExport* exp = &module_->export_table.back();
695 :
696 351725 : exp->name = consume_string(*this, true, "field name");
697 :
698 : const byte* pos = pc();
699 351721 : exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
700 351721 : switch (exp->kind) {
701 : case kExternalFunction: {
702 347871 : WasmFunction* func = nullptr;
703 : exp->index =
704 347870 : consume_func_index(module_.get(), &func, "export function index");
705 347870 : module_->num_exported_functions++;
706 347870 : if (func) func->exported = true;
707 : break;
708 : }
709 : case kExternalTable: {
710 744 : WasmTable* table = nullptr;
711 744 : exp->index = consume_table_index(module_.get(), &table);
712 744 : if (table) table->exported = true;
713 : break;
714 : }
715 : case kExternalMemory: {
716 : uint32_t index = consume_u32v("memory index");
717 : // TODO(titzer): This should become more regular
718 : // once we support multiple memories.
719 1719 : if (!module_->has_memory || index != 0) {
720 24 : error("invalid memory index != 0");
721 : }
722 1719 : module_->mem_export = true;
723 1719 : break;
724 : }
725 : case kExternalGlobal: {
726 1242 : WasmGlobal* global = nullptr;
727 1242 : exp->index = consume_global_index(module_.get(), &global);
728 1242 : if (global) {
729 1226 : global->exported = true;
730 : }
731 : break;
732 : }
733 : case kExternalException: {
734 145 : if (!enabled_features_.eh) {
735 0 : errorf(pos, "invalid export kind 0x%02x", exp->kind);
736 0 : break;
737 : }
738 145 : WasmException* exception = nullptr;
739 145 : exp->index = consume_exception_index(module_.get(), &exception);
740 145 : break;
741 : }
742 : default:
743 0 : errorf(pos, "invalid export kind 0x%02x", exp->kind);
744 0 : break;
745 : }
746 : }
747 : // Check for duplicate exports (except for asm.js).
748 467154 : if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
749 7623 : std::vector<WasmExport> sorted_exports(module_->export_table);
750 :
751 1103102 : auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
752 : // Return true if a < b.
753 628375 : if (a.name.length() != b.name.length()) {
754 153648 : return a.name.length() < b.name.length();
755 : }
756 474727 : const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
757 474727 : const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
758 474727 : return memcmp(left, right, a.name.length()) < 0;
759 7623 : };
760 : std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
761 :
762 : auto it = sorted_exports.begin();
763 : WasmExport* last = &*it++;
764 237079 : for (auto end = sorted_exports.end(); it != end; last = &*it++) {
765 : DCHECK(!cmp_less(*it, *last)); // Vector must be sorted.
766 115056 : if (!cmp_less(*last, *it)) {
767 328 : const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
768 328 : TruncatedUserString<> name(pc, it->name.length());
769 984 : errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
770 328 : name.length(), name.start(), ExternalKindName(last->kind),
771 656 : last->index, ExternalKindName(it->kind), it->index);
772 : break;
773 : }
774 : }
775 : }
776 234868 : }
777 :
778 2774 : void DecodeStartSection() {
779 : WasmFunction* func;
780 2774 : const byte* pos = pc_;
781 : module_->start_function_index =
782 2774 : consume_func_index(module_.get(), &func, "start function index");
783 8282 : if (func &&
784 5428 : (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
785 64 : error(pos, "invalid start function: non-zero parameter or return count");
786 : }
787 2774 : }
788 :
789 2246 : void DecodeElementSection() {
790 : uint32_t element_count =
791 2246 : consume_count("element count", FLAG_wasm_max_table_size);
792 :
793 4472 : if (element_count > 0 && module_->tables.size() == 0) {
794 49 : error(pc_, "The element section requires a table");
795 : }
796 7588 : for (uint32_t i = 0; ok() && i < element_count; ++i) {
797 : const byte* pos = pc();
798 :
799 : bool is_active;
800 : uint32_t table_index;
801 : WasmInitExpr offset;
802 2803 : consume_segment_header("table index", &is_active, &table_index, &offset);
803 2932 : if (failed()) return;
804 :
805 2674 : if (is_active) {
806 5304 : if (table_index >= module_->tables.size()) {
807 0 : errorf(pos, "out of bounds table index %u", table_index);
808 0 : break;
809 : }
810 2652 : if (module_->tables[table_index].type != kWasmAnyFunc) {
811 2 : errorf(pos,
812 : "Invalid element segment. Table %u is not of type AnyFunc",
813 2 : table_index);
814 2 : break;
815 : }
816 : } else {
817 22 : ValueType type = consume_reference_type();
818 22 : if (type != kWasmAnyFunc) {
819 1 : error(pc_ - 1, "invalid element segment type");
820 1 : break;
821 : }
822 : }
823 :
824 : uint32_t num_elem =
825 2671 : consume_count("number of elements", max_table_init_entries());
826 2671 : if (is_active) {
827 2650 : module_->elem_segments.emplace_back(table_index, offset);
828 : } else {
829 21 : module_->elem_segments.emplace_back();
830 : }
831 :
832 : WasmElemSegment* init = &module_->elem_segments.back();
833 19505 : for (uint32_t j = 0; j < num_elem; j++) {
834 : uint32_t index = is_active ? consume_element_func_index()
835 8489 : : consume_passive_element();
836 8434 : if (failed()) break;
837 8417 : init->entries.push_back(index);
838 : }
839 : }
840 : }
841 :
842 258450 : void DecodeCodeSection(bool verify_functions) {
843 : uint32_t pos = pc_offset();
844 258450 : uint32_t functions_count = consume_u32v("functions count");
845 258453 : CheckFunctionsCount(functions_count, pos);
846 1032993 : for (uint32_t i = 0; ok() && i < functions_count; ++i) {
847 : const byte* pos = pc();
848 : uint32_t size = consume_u32v("body size");
849 387274 : if (size > kV8MaxWasmFunctionSize) {
850 : errorf(pos, "size %u > maximum function size %zu", size,
851 3 : kV8MaxWasmFunctionSize);
852 3 : return;
853 : }
854 : uint32_t offset = pc_offset();
855 387271 : consume_bytes(size, "function body");
856 387271 : if (failed()) break;
857 387271 : DecodeFunctionBody(i, size, offset, verify_functions);
858 : }
859 : }
860 :
861 258721 : bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
862 258721 : if (functions_count != module_->num_declared_functions) {
863 79 : Reset(nullptr, nullptr, offset);
864 79 : errorf(nullptr, "function body count %u mismatch (%u expected)",
865 79 : functions_count, module_->num_declared_functions);
866 79 : return false;
867 : }
868 : return true;
869 : }
870 :
871 387777 : void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
872 : bool verify_functions) {
873 : WasmFunction* function =
874 387777 : &module_->functions[index + module_->num_imported_functions];
875 387777 : function->code = {offset, length};
876 387777 : if (verify_functions) {
877 136550 : ModuleWireBytes bytes(start_, end_);
878 136550 : VerifyFunctionBody(module_->signature_zone->allocator(),
879 136550 : index + module_->num_imported_functions, bytes,
880 136550 : module_.get(), function);
881 : }
882 387777 : }
883 :
884 268086 : bool CheckDataSegmentsCount(uint32_t data_segments_count) {
885 268172 : if (has_seen_unordered_section(kDataCountSectionCode) &&
886 86 : data_segments_count != module_->num_declared_data_segments) {
887 3 : errorf(pc(), "data segments count %u mismatch (%u expected)",
888 3 : data_segments_count, module_->num_declared_data_segments);
889 3 : return false;
890 : }
891 : return true;
892 : }
893 :
894 1346 : void DecodeDataSection() {
895 : uint32_t data_segments_count =
896 1346 : consume_count("data segments count", kV8MaxWasmDataSegments);
897 1346 : if (!CheckDataSegmentsCount(data_segments_count)) return;
898 :
899 1344 : module_->data_segments.reserve(data_segments_count);
900 4566 : for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
901 : const byte* pos = pc();
902 1761 : if (!module_->has_memory) {
903 65 : error("cannot load data without memory");
904 65 : break;
905 : }
906 : TRACE("DecodeDataSegment[%d] module+%d\n", i,
907 : static_cast<int>(pc_ - start_));
908 :
909 : bool is_active;
910 : uint32_t memory_index;
911 : WasmInitExpr dest_addr;
912 : consume_segment_header("memory index", &is_active, &memory_index,
913 1696 : &dest_addr);
914 1696 : if (failed()) break;
915 :
916 1612 : if (is_active && memory_index != 0) {
917 0 : errorf(pos, "illegal memory index %u != 0", memory_index);
918 0 : break;
919 : }
920 :
921 1612 : uint32_t source_length = consume_u32v("source size");
922 : uint32_t source_offset = pc_offset();
923 :
924 1612 : if (is_active) {
925 1563 : module_->data_segments.emplace_back(dest_addr);
926 : } else {
927 49 : module_->data_segments.emplace_back();
928 : }
929 :
930 : WasmDataSegment* segment = &module_->data_segments.back();
931 :
932 1612 : consume_bytes(source_length, "segment data");
933 1612 : if (failed()) break;
934 :
935 1611 : segment->source = {source_offset, source_length};
936 : }
937 : }
938 :
939 23569 : void DecodeNameSection() {
940 : // TODO(titzer): find a way to report name errors as warnings.
941 : // Ignore all but the first occurrence of name section.
942 23569 : if (!has_seen_unordered_section(kNameSectionCode)) {
943 : set_seen_unordered_section(kNameSectionCode);
944 : // Use an inner decoder so that errors don't fail the outer decoder.
945 23563 : Decoder inner(start_, pc_, end_, buffer_offset_);
946 : // Decode all name subsections.
947 : // Be lenient with their order.
948 47220 : while (inner.ok() && inner.more()) {
949 : uint8_t name_type = inner.consume_u8("name type");
950 23679 : if (name_type & 0x80) inner.error("name type if not varuint7");
951 :
952 : uint32_t name_payload_len = inner.consume_u32v("name payload length");
953 23680 : if (!inner.checkAvailable(name_payload_len)) break;
954 :
955 : // Decode module name, ignore the rest.
956 : // Function and local names will be decoded when needed.
957 23656 : if (name_type == NameSectionKindCode::kModule) {
958 139 : WireBytesRef name = consume_string(inner, false, "module name");
959 196 : if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
960 : } else {
961 23517 : inner.consume_bytes(name_payload_len, "name subsection payload");
962 : }
963 : }
964 : }
965 : // Skip the whole names section in the outer decoder.
966 23572 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
967 23577 : }
968 :
969 8 : void DecodeSourceMappingURLSection() {
970 8 : Decoder inner(start_, pc_, end_, buffer_offset_);
971 8 : WireBytesRef url = wasm::consume_string(inner, true, "module name");
972 15 : if (inner.ok() &&
973 : !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
974 : const byte* url_start =
975 6 : inner.start() + inner.GetBufferRelativeOffset(url.offset());
976 : module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
977 6 : url.length());
978 : set_seen_unordered_section(kSourceMappingURLSectionCode);
979 : }
980 8 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
981 8 : }
982 :
983 137 : void DecodeCompilationHintsSection() {
984 : TRACE("DecodeCompilationHints module+%d\n", static_cast<int>(pc_ - start_));
985 :
986 : // TODO(frgossen): Find a way to report compilation hint errors as warnings.
987 : // All except first occurrence after function section and before code
988 : // section are ignored.
989 : const bool before_function_section =
990 137 : next_ordered_section_ <= kFunctionSectionCode;
991 137 : const bool after_code_section = next_ordered_section_ > kCodeSectionCode;
992 274 : if (before_function_section || after_code_section ||
993 : has_seen_unordered_section(kCompilationHintsSectionCode)) {
994 : return;
995 : }
996 : set_seen_unordered_section(kCompilationHintsSectionCode);
997 :
998 : // TODO(frgossen) Propagate errors to outer decoder in experimental phase.
999 : // We should use an inner decoder later and propagate its errors as
1000 : // warnings.
1001 137 : Decoder& decoder = *this;
1002 : // Decoder decoder(start_, pc_, end_, buffer_offset_);
1003 :
1004 : // Ensure exactly one compilation hint per function.
1005 : uint32_t hint_count = decoder.consume_u32v("compilation hint count");
1006 137 : if (hint_count != module_->num_declared_functions) {
1007 : decoder.errorf(decoder.pc(), "Expected %u compilation hints (%u found)",
1008 0 : module_->num_declared_functions, hint_count);
1009 : }
1010 :
1011 : // Decode sequence of compilation hints.
1012 137 : if (decoder.ok()) {
1013 137 : module_->compilation_hints.reserve(hint_count);
1014 137 : module_->num_lazy_compilation_hints = 0;
1015 : }
1016 527 : for (uint32_t i = 0; decoder.ok() && i < hint_count; i++) {
1017 : TRACE("DecodeCompilationHints[%d] module+%d\n", i,
1018 : static_cast<int>(pc_ - start_));
1019 :
1020 : // Compilation hints are encoded in one byte each.
1021 : // +-------+----------+---------------+------------------+
1022 : // | 2 bit | 2 bit | 2 bit | 2 bit |
1023 : // | ... | Top tier | Baseline tier | Lazy compilation |
1024 : // +-------+----------+---------------+------------------+
1025 : uint8_t hint_byte = decoder.consume_u8("compilation hint");
1026 195 : if (!decoder.ok()) break;
1027 :
1028 : // Decode compilation hint.
1029 : WasmCompilationHint hint;
1030 : hint.strategy =
1031 195 : static_cast<WasmCompilationHintStrategy>(hint_byte & 0x03);
1032 : hint.baseline_tier =
1033 195 : static_cast<WasmCompilationHintTier>(hint_byte >> 2 & 0x3);
1034 : hint.top_tier =
1035 195 : static_cast<WasmCompilationHintTier>(hint_byte >> 4 & 0x3);
1036 :
1037 : // Check strategy.
1038 195 : if (hint.strategy > WasmCompilationHintStrategy::kEager) {
1039 : decoder.errorf(decoder.pc(),
1040 : "Invalid compilation hint %#x (unknown strategy)",
1041 8 : hint_byte);
1042 : }
1043 :
1044 : // Ensure that the top tier never downgrades a compilation result.
1045 : // If baseline and top tier are the same compilation will be invoked only
1046 : // once.
1047 195 : if (hint.top_tier < hint.baseline_tier &&
1048 : hint.top_tier != WasmCompilationHintTier::kDefault) {
1049 : decoder.errorf(decoder.pc(),
1050 : "Invalid compilation hint %#x (forbidden downgrade)",
1051 32 : hint_byte);
1052 : }
1053 :
1054 : // Happily accept compilation hint.
1055 195 : if (decoder.ok()) {
1056 155 : if (hint.strategy == WasmCompilationHintStrategy::kLazy) {
1057 56 : module_->num_lazy_compilation_hints++;
1058 : }
1059 155 : module_->compilation_hints.push_back(std::move(hint));
1060 : }
1061 : }
1062 :
1063 : // If section was invalid reset compilation hints.
1064 137 : if (decoder.failed()) {
1065 : module_->compilation_hints.clear();
1066 40 : module_->num_lazy_compilation_hints = 0;
1067 : }
1068 :
1069 : // @TODO(frgossen) Skip the whole compilation hints section in the outer
1070 : // decoder if inner decoder was used.
1071 : // consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1072 : }
1073 :
1074 : void DecodeDataCountSection() {
1075 : module_->num_declared_data_segments =
1076 48 : consume_count("data segments count", kV8MaxWasmDataSegments);
1077 : }
1078 :
1079 594 : void DecodeExceptionSection() {
1080 : uint32_t exception_count =
1081 594 : consume_count("exception count", kV8MaxWasmExceptions);
1082 1968 : for (uint32_t i = 0; ok() && i < exception_count; ++i) {
1083 : TRACE("DecodeException[%d] module+%d\n", i,
1084 : static_cast<int>(pc_ - start_));
1085 687 : WasmExceptionSig* exception_sig = nullptr;
1086 687 : consume_exception_attribute(); // Attribute ignored for now.
1087 687 : consume_exception_sig_index(module_.get(), &exception_sig);
1088 687 : module_->exceptions.emplace_back(exception_sig);
1089 : }
1090 594 : }
1091 :
1092 266758 : bool CheckMismatchedCounts() {
1093 : // The declared vs. defined function count is normally checked when
1094 : // decoding the code section, but we have to check it here too in case the
1095 : // code section is absent.
1096 266758 : if (module_->num_declared_functions != 0) {
1097 : DCHECK_LT(module_->num_imported_functions, module_->functions.size());
1098 : // We know that the code section has been decoded if the first
1099 : // non-imported function has its code set.
1100 516910 : if (!module_->functions[module_->num_imported_functions].code.is_set()) {
1101 22 : errorf(pc(), "function count is %u, but code section is absent",
1102 22 : module_->num_declared_functions);
1103 22 : return false;
1104 : }
1105 : }
1106 : // Perform a similar check for the DataCount and Data sections, where data
1107 : // segments are declared but the Data section is absent.
1108 266736 : if (!CheckDataSegmentsCount(
1109 : static_cast<uint32_t>(module_->data_segments.size()))) {
1110 : return false;
1111 : }
1112 266739 : return true;
1113 : }
1114 :
1115 282127 : ModuleResult FinishDecoding(bool verify_functions = true) {
1116 282127 : if (ok() && CheckMismatchedCounts()) {
1117 266740 : CalculateGlobalOffsets(module_.get());
1118 : }
1119 846390 : ModuleResult result = toResult(std::move(module_));
1120 282131 : if (verify_functions && result.ok() && intermediate_error_.has_error()) {
1121 : // Copy error message and location.
1122 15234 : return ModuleResult{std::move(intermediate_error_)};
1123 : }
1124 : return result;
1125 : }
1126 :
1127 : // Decodes an entire module.
1128 284965 : ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
1129 : bool verify_functions = true) {
1130 284965 : StartDecoding(counters, allocator);
1131 : uint32_t offset = 0;
1132 284971 : Vector<const byte> orig_bytes(start(), end() - start());
1133 284971 : DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
1134 284970 : if (failed()) {
1135 15238 : return FinishDecoding(verify_functions);
1136 : }
1137 : // Size of the module header.
1138 : offset += 8;
1139 277351 : Decoder decoder(start_ + offset, end_, offset);
1140 :
1141 : WasmSectionIterator section_iter(decoder);
1142 :
1143 4424763 : while (ok() && section_iter.more()) {
1144 : // Shift the offset by the section header length
1145 1292597 : offset += section_iter.payload_start() - section_iter.section_start();
1146 1292597 : if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
1147 2583870 : DecodeSection(section_iter.section_code(), section_iter.payload(),
1148 1291935 : offset, verify_functions);
1149 : }
1150 : // Shift the offset by the remaining section payload
1151 1292595 : offset += section_iter.payload_length();
1152 1292595 : section_iter.advance(true);
1153 : }
1154 :
1155 : if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
1156 :
1157 277349 : if (decoder.failed()) {
1158 6166 : return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
1159 : }
1160 :
1161 548529 : return FinishDecoding(verify_functions);
1162 : }
1163 :
1164 : // Decodes a single anonymous function starting at {start_}.
1165 1 : FunctionResult DecodeSingleFunction(Zone* zone,
1166 : const ModuleWireBytes& wire_bytes,
1167 : const WasmModule* module,
1168 : std::unique_ptr<WasmFunction> function) {
1169 1 : pc_ = start_;
1170 1 : function->sig = consume_sig(zone);
1171 2 : function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
1172 :
1173 1 : if (ok())
1174 : VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
1175 1 : function.get());
1176 :
1177 1 : if (intermediate_error_.has_error()) {
1178 0 : return FunctionResult{std::move(intermediate_error_)};
1179 : }
1180 :
1181 1 : return FunctionResult(std::move(function));
1182 : }
1183 :
1184 : // Decodes a single function signature at {start}.
1185 : FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
1186 262 : pc_ = start;
1187 262 : FunctionSig* result = consume_sig(zone);
1188 262 : return ok() ? result : nullptr;
1189 : }
1190 :
1191 : WasmInitExpr DecodeInitExpr(const byte* start) {
1192 22 : pc_ = start;
1193 22 : return consume_init_expr(nullptr, kWasmStmt);
1194 : }
1195 :
1196 764 : const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
1197 :
1198 : Counters* GetCounters() const {
1199 : DCHECK_NOT_NULL(counters_);
1200 : return counters_;
1201 : }
1202 :
1203 : void SetCounters(Counters* counters) {
1204 : DCHECK_NULL(counters_);
1205 285376 : counters_ = counters;
1206 : }
1207 :
1208 : private:
1209 : const WasmFeatures enabled_features_;
1210 : std::shared_ptr<WasmModule> module_;
1211 : Counters* counters_ = nullptr;
1212 : // The type section is the first section in a module.
1213 : uint8_t next_ordered_section_ = kFirstSectionInModule;
1214 : // We store next_ordered_section_ as uint8_t instead of SectionCode so that
1215 : // we can increment it. This static_assert should make sure that SectionCode
1216 : // does not get bigger than uint8_t accidentially.
1217 : static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
1218 : sizeof(SectionCode),
1219 : "type mismatch");
1220 : uint32_t seen_unordered_sections_ = 0;
1221 : static_assert(kBitsPerByte *
1222 : sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
1223 : kLastKnownModuleSection,
1224 : "not enough bits");
1225 : WasmError intermediate_error_;
1226 : ModuleOrigin origin_;
1227 :
1228 : bool has_seen_unordered_section(SectionCode section_code) {
1229 292457 : return seen_unordered_sections_ & (1 << section_code);
1230 : }
1231 :
1232 : void set_seen_unordered_section(SectionCode section_code) {
1233 24363 : seen_unordered_sections_ |= 1 << section_code;
1234 : }
1235 :
1236 : uint32_t off(const byte* ptr) {
1237 1 : return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
1238 : }
1239 :
1240 : bool AddTable(WasmModule* module) {
1241 4173 : if (enabled_features_.anyref) return true;
1242 4001 : if (module->tables.size() > 0) {
1243 32 : error("At most one table is supported");
1244 : return false;
1245 : } else {
1246 : return true;
1247 : }
1248 : }
1249 :
1250 : bool AddMemory(WasmModule* module) {
1251 15770 : if (module->has_memory) {
1252 64 : error("At most one memory is supported");
1253 : return false;
1254 : } else {
1255 15706 : module->has_memory = true;
1256 : return true;
1257 : }
1258 : }
1259 :
1260 : // Decodes a single global entry inside a module starting at {pc_}.
1261 441416 : void DecodeGlobalInModule(WasmModule* module, uint32_t index,
1262 : WasmGlobal* global) {
1263 441416 : global->type = consume_value_type();
1264 441416 : global->mutability = consume_mutability();
1265 : const byte* pos = pc();
1266 441416 : global->init = consume_init_expr(module, kWasmStmt);
1267 441416 : if (global->init.kind == WasmInitExpr::kGlobalIndex) {
1268 73 : uint32_t other_index = global->init.val.global_index;
1269 73 : if (other_index >= index) {
1270 0 : errorf(pos,
1271 : "invalid global index in init expression, "
1272 : "index %u, other_index %u",
1273 0 : index, other_index);
1274 146 : } else if (module->globals[other_index].type != global->type) {
1275 0 : errorf(pos,
1276 : "type mismatch in global initialization "
1277 : "(from global #%u), expected %s, got %s",
1278 : other_index, ValueTypes::TypeName(global->type),
1279 0 : ValueTypes::TypeName(module->globals[other_index].type));
1280 : }
1281 : } else {
1282 441343 : if (!ValueTypes::IsSubType(global->type, TypeOf(module, global->init))) {
1283 384 : errorf(pos, "type error in global initialization, expected %s, got %s",
1284 : ValueTypes::TypeName(global->type),
1285 384 : ValueTypes::TypeName(TypeOf(module, global->init)));
1286 : }
1287 : }
1288 441416 : }
1289 :
1290 : // Calculate individual global offsets and total size of globals table.
1291 269261 : void CalculateGlobalOffsets(WasmModule* module) {
1292 : uint32_t untagged_offset = 0;
1293 : uint32_t tagged_offset = 0;
1294 : uint32_t num_imported_mutable_globals = 0;
1295 1154038 : for (WasmGlobal& global : module->globals) {
1296 884777 : if (global.mutability && global.imported) {
1297 433 : global.index = num_imported_mutable_globals++;
1298 1768688 : } else if (ValueTypes::IsReferenceType(global.type)) {
1299 1126 : global.offset = tagged_offset;
1300 : // All entries in the tagged_globals_buffer have size 1.
1301 1126 : tagged_offset++;
1302 : } else {
1303 : byte size =
1304 883218 : ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
1305 883218 : untagged_offset = (untagged_offset + size - 1) & ~(size - 1); // align
1306 883218 : global.offset = untagged_offset;
1307 883218 : untagged_offset += size;
1308 : }
1309 : }
1310 269261 : module->untagged_globals_buffer_size = untagged_offset;
1311 269261 : module->tagged_globals_buffer_size = tagged_offset;
1312 269261 : }
1313 :
1314 : // Verifies the body (code) of a given function.
1315 136551 : void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
1316 : const ModuleWireBytes& wire_bytes,
1317 : const WasmModule* module, WasmFunction* function) {
1318 : WasmFunctionName func_name(function,
1319 136551 : wire_bytes.GetNameOrNull(function, module));
1320 : if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
1321 : StdoutStream os;
1322 : os << "Verifying wasm function " << func_name << std::endl;
1323 : }
1324 : FunctionBody body = {
1325 : function->sig, function->code.offset(),
1326 136551 : start_ + GetBufferRelativeOffset(function->code.offset()),
1327 409653 : start_ + GetBufferRelativeOffset(function->code.end_offset())};
1328 :
1329 : DecodeResult result;
1330 : {
1331 136551 : auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
1332 : wasm_decode, function_time);
1333 :
1334 : TimedHistogramScope wasm_decode_function_time_scope(time_counter);
1335 136551 : WasmFeatures unused_detected_features;
1336 273102 : result = VerifyWasmCode(allocator, enabled_features_, module,
1337 : &unused_detected_features, body);
1338 : }
1339 :
1340 : // If the decode failed and this is the first error, set error code and
1341 : // location.
1342 136551 : if (result.failed() && intermediate_error_.empty()) {
1343 : // Wrap the error message from the function decoder.
1344 15298 : std::ostringstream error_msg;
1345 7649 : error_msg << "in function " << func_name << ": "
1346 : << result.error().message();
1347 15298 : intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
1348 : }
1349 136551 : }
1350 :
1351 617005 : uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
1352 617005 : const byte* pos = pc_;
1353 617005 : uint32_t sig_index = consume_u32v("signature index");
1354 1234010 : if (sig_index >= module->signatures.size()) {
1355 5740 : errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
1356 5740 : static_cast<int>(module->signatures.size()));
1357 5740 : *sig = nullptr;
1358 5740 : return 0;
1359 : }
1360 611265 : *sig = module->signatures[sig_index];
1361 611265 : return sig_index;
1362 : }
1363 :
1364 792 : uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
1365 792 : const byte* pos = pc_;
1366 792 : uint32_t sig_index = consume_sig_index(module, sig);
1367 792 : if (*sig && (*sig)->return_count() != 0) {
1368 2 : errorf(pos, "exception signature %u has non-void return", sig_index);
1369 2 : *sig = nullptr;
1370 2 : return 0;
1371 : }
1372 : return sig_index;
1373 : }
1374 :
1375 2146256 : uint32_t consume_count(const char* name, size_t maximum) {
1376 2146256 : const byte* p = pc_;
1377 2146256 : uint32_t count = consume_u32v(name);
1378 2146269 : if (count > maximum) {
1379 118 : errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
1380 118 : return static_cast<uint32_t>(maximum);
1381 : }
1382 : return count;
1383 : }
1384 :
1385 : uint32_t consume_func_index(WasmModule* module, WasmFunction** func,
1386 : const char* name) {
1387 359074 : return consume_index(name, module->functions, func);
1388 : }
1389 :
1390 : uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
1391 1242 : return consume_index("global index", module->globals, global);
1392 : }
1393 :
1394 : uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
1395 744 : return consume_index("table index", module->tables, table);
1396 : }
1397 :
1398 : uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
1399 145 : return consume_index("exception index", module->exceptions, except);
1400 : }
1401 :
1402 : template <typename T>
1403 361205 : uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
1404 361205 : const byte* pos = pc_;
1405 361205 : uint32_t index = consume_u32v(name);
1406 722410 : if (index >= vector.size()) {
1407 115 : errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
1408 : static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
1409 115 : *ptr = nullptr;
1410 115 : return 0;
1411 : }
1412 361090 : *ptr = &vector[index];
1413 361090 : return index;
1414 : }
1415 :
1416 4141 : uint8_t validate_table_flags(const char* name) {
1417 4141 : uint8_t flags = consume_u8("resizable limits flags");
1418 : const byte* pos = pc();
1419 4141 : if (flags & 0xFE) {
1420 8 : errorf(pos - 1, "invalid %s limits flags", name);
1421 : }
1422 4141 : return flags;
1423 : }
1424 :
1425 15706 : uint8_t validate_memory_flags(bool* has_shared_memory) {
1426 15706 : uint8_t flags = consume_u8("resizable limits flags");
1427 : const byte* pos = pc();
1428 15707 : *has_shared_memory = false;
1429 15707 : if (enabled_features_.threads) {
1430 1556 : if (flags & 0xFC) {
1431 0 : errorf(pos - 1, "invalid memory limits flags");
1432 1556 : } else if (flags == 3) {
1433 : DCHECK_NOT_NULL(has_shared_memory);
1434 1480 : *has_shared_memory = true;
1435 76 : } else if (flags == 2) {
1436 8 : errorf(pos - 1,
1437 : "memory limits flags should have maximum defined if shared is "
1438 8 : "true");
1439 : }
1440 : } else {
1441 14151 : if (flags & 0xFE) {
1442 16 : errorf(pos - 1, "invalid memory limits flags");
1443 : }
1444 : }
1445 15707 : return flags;
1446 : }
1447 :
1448 19847 : void consume_resizable_limits(const char* name, const char* units,
1449 : uint32_t max_initial, uint32_t* initial,
1450 : bool* has_max, uint32_t max_maximum,
1451 : uint32_t* maximum, uint8_t flags) {
1452 : const byte* pos = pc();
1453 39697 : *initial = consume_u32v("initial size");
1454 19850 : *has_max = false;
1455 19850 : if (*initial > max_initial) {
1456 : errorf(pos,
1457 : "initial %s size (%u %s) is larger than implementation limit (%u)",
1458 56 : name, *initial, units, max_initial);
1459 : }
1460 19852 : if (flags & 1) {
1461 6043 : *has_max = true;
1462 : pos = pc();
1463 6043 : *maximum = consume_u32v("maximum size");
1464 6043 : if (*maximum > max_maximum) {
1465 : errorf(
1466 : pos,
1467 : "maximum %s size (%u %s) is larger than implementation limit (%u)",
1468 57 : name, *maximum, units, max_maximum);
1469 : }
1470 6043 : if (*maximum < *initial) {
1471 : errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
1472 16 : name, *maximum, units, *initial, units);
1473 : }
1474 : } else {
1475 13809 : *has_max = false;
1476 13809 : *maximum = max_initial;
1477 : }
1478 19852 : }
1479 :
1480 1013849 : bool expect_u8(const char* name, uint8_t expected) {
1481 : const byte* pos = pc();
1482 1013849 : uint8_t value = consume_u8(name);
1483 1013849 : if (value != expected) {
1484 680 : errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
1485 680 : return false;
1486 : }
1487 : return true;
1488 : }
1489 :
1490 445866 : WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
1491 : const byte* pos = pc();
1492 445866 : uint8_t opcode = consume_u8("opcode");
1493 : WasmInitExpr expr;
1494 : uint32_t len = 0;
1495 445866 : switch (opcode) {
1496 : case kExprGetGlobal: {
1497 : GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
1498 404 : if (module->globals.size() <= imm.index) {
1499 16 : error("global index is out of bounds");
1500 16 : expr.kind = WasmInitExpr::kNone;
1501 16 : expr.val.i32_const = 0;
1502 16 : break;
1503 : }
1504 : WasmGlobal* global = &module->globals[imm.index];
1505 388 : if (global->mutability || !global->imported) {
1506 : error(
1507 : "only immutable imported globals can be used in initializer "
1508 18 : "expressions");
1509 18 : expr.kind = WasmInitExpr::kNone;
1510 18 : expr.val.i32_const = 0;
1511 18 : break;
1512 : }
1513 370 : expr.kind = WasmInitExpr::kGlobalIndex;
1514 370 : expr.val.global_index = imm.index;
1515 370 : len = imm.length;
1516 370 : break;
1517 : }
1518 : case kExprI32Const: {
1519 : ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
1520 7889 : expr.kind = WasmInitExpr::kI32Const;
1521 7889 : expr.val.i32_const = imm.value;
1522 7889 : len = imm.length;
1523 : break;
1524 : }
1525 : case kExprF32Const: {
1526 436042 : ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
1527 436042 : expr.kind = WasmInitExpr::kF32Const;
1528 436042 : expr.val.f32_const = imm.value;
1529 436042 : len = imm.length;
1530 : break;
1531 : }
1532 : case kExprI64Const: {
1533 : ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
1534 316 : expr.kind = WasmInitExpr::kI64Const;
1535 316 : expr.val.i64_const = imm.value;
1536 316 : len = imm.length;
1537 : break;
1538 : }
1539 : case kExprF64Const: {
1540 571 : ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
1541 571 : expr.kind = WasmInitExpr::kF64Const;
1542 571 : expr.val.f64_const = imm.value;
1543 571 : len = imm.length;
1544 : break;
1545 : }
1546 : case kExprRefNull: {
1547 466 : if (enabled_features_.anyref || enabled_features_.eh) {
1548 466 : expr.kind = WasmInitExpr::kRefNullConst;
1549 : len = 0;
1550 466 : break;
1551 : }
1552 : V8_FALLTHROUGH;
1553 : }
1554 : default: {
1555 178 : error("invalid opcode in initialization expression");
1556 178 : expr.kind = WasmInitExpr::kNone;
1557 178 : expr.val.i32_const = 0;
1558 : }
1559 : }
1560 445866 : consume_bytes(len, "init code");
1561 445866 : if (!expect_u8("end opcode", kExprEnd)) {
1562 552 : expr.kind = WasmInitExpr::kNone;
1563 : }
1564 445866 : if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
1565 213 : errorf(pos, "type error in init expression, expected %s, got %s",
1566 : ValueTypes::TypeName(expected),
1567 426 : ValueTypes::TypeName(TypeOf(module, expr)));
1568 : }
1569 445866 : return expr;
1570 : }
1571 :
1572 : // Read a mutability flag
1573 443748 : bool consume_mutability() {
1574 443748 : byte val = consume_u8("mutability");
1575 443748 : if (val > 1) error(pc_ - 1, "invalid mutability");
1576 443748 : return val != 0;
1577 : }
1578 :
1579 : // Reads a single 8-bit integer, interpreting it as a local type.
1580 1333712 : ValueType consume_value_type() {
1581 1333712 : byte val = consume_u8("value type");
1582 : ValueTypeCode t = static_cast<ValueTypeCode>(val);
1583 1333714 : switch (t) {
1584 : case kLocalI32:
1585 : return kWasmI32;
1586 : case kLocalI64:
1587 34588 : return kWasmI64;
1588 : case kLocalF32:
1589 707080 : return kWasmF32;
1590 : case kLocalF64:
1591 278061 : return kWasmF64;
1592 : default:
1593 6343 : if (origin_ == kWasmOrigin) {
1594 6343 : switch (t) {
1595 : case kLocalS128:
1596 48 : if (enabled_features_.simd) return kWasmS128;
1597 : break;
1598 : case kLocalAnyFunc:
1599 837 : if (enabled_features_.anyref) return kWasmAnyFunc;
1600 : break;
1601 : case kLocalAnyRef:
1602 5256 : if (enabled_features_.anyref) return kWasmAnyRef;
1603 : break;
1604 : case kLocalExceptRef:
1605 176 : if (enabled_features_.eh) return kWasmExceptRef;
1606 : break;
1607 : default:
1608 : break;
1609 : }
1610 : }
1611 48 : error(pc_ - 1, "invalid local type");
1612 48 : return kWasmStmt;
1613 : }
1614 : }
1615 :
1616 : // Reads a single 8-bit integer, interpreting it as a reference type.
1617 4163 : ValueType consume_reference_type() {
1618 4163 : byte val = consume_u8("reference type");
1619 : ValueTypeCode t = static_cast<ValueTypeCode>(val);
1620 4163 : switch (t) {
1621 : case kLocalAnyFunc:
1622 : return kWasmAnyFunc;
1623 : case kLocalAnyRef:
1624 20 : if (!enabled_features_.anyref) {
1625 1 : error(pc_ - 1,
1626 1 : "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
1627 : }
1628 : return kWasmAnyRef;
1629 : default:
1630 : break;
1631 : }
1632 2 : error(pc_ - 1, "invalid reference type");
1633 2 : return kWasmStmt;
1634 : }
1635 :
1636 567929 : FunctionSig* consume_sig(Zone* zone) {
1637 567929 : if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
1638 : // parse parameter types
1639 : uint32_t param_count =
1640 567801 : consume_count("param count", kV8MaxWasmFunctionParams);
1641 567802 : if (failed()) return nullptr;
1642 : std::vector<ValueType> params;
1643 1707963 : for (uint32_t i = 0; ok() && i < param_count; ++i) {
1644 570081 : ValueType param = consume_value_type();
1645 570078 : params.push_back(param);
1646 : }
1647 : std::vector<ValueType> returns;
1648 : // parse return types
1649 567802 : const size_t max_return_count = enabled_features_.mv
1650 : ? kV8MaxWasmFunctionMultiReturns
1651 567802 : : kV8MaxWasmFunctionReturns;
1652 567802 : uint32_t return_count = consume_count("return count", max_return_count);
1653 567802 : if (failed()) return nullptr;
1654 1207489 : for (uint32_t i = 0; ok() && i < return_count; ++i) {
1655 319889 : ValueType ret = consume_value_type();
1656 319886 : returns.push_back(ret);
1657 : }
1658 :
1659 567712 : if (failed()) return nullptr;
1660 :
1661 : // FunctionSig stores the return types first.
1662 567699 : ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
1663 : uint32_t b = 0;
1664 1207453 : for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
1665 1707777 : for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
1666 :
1667 1135402 : return new (zone) FunctionSig(return_count, param_count, buffer);
1668 : }
1669 :
1670 : // Consume the attribute field of an exception.
1671 792 : uint32_t consume_exception_attribute() {
1672 792 : const byte* pos = pc_;
1673 792 : uint32_t attribute = consume_u32v("exception attribute");
1674 792 : if (attribute != kExceptionAttribute) {
1675 1 : errorf(pos, "exception attribute %u not supported", attribute);
1676 1 : return 0;
1677 : }
1678 : return attribute;
1679 : }
1680 :
1681 4499 : void consume_segment_header(const char* name, bool* is_active,
1682 : uint32_t* index, WasmInitExpr* offset) {
1683 : const byte* pos = pc();
1684 : // In the MVP, this is a table or memory index field that must be 0, but
1685 : // we've repurposed it as a flags field in the bulk memory proposal.
1686 : uint32_t flags;
1687 4499 : if (enabled_features_.bulk_memory) {
1688 4440 : flags = consume_u32v("flags");
1689 4440 : if (failed()) return;
1690 : } else {
1691 : // Without the bulk memory proposal, we should still read the table
1692 : // index. This is the same as reading the `ActiveWithIndex` flag with
1693 : // the bulk memory proposal.
1694 : flags = SegmentFlags::kActiveWithIndex;
1695 : }
1696 :
1697 : bool read_index;
1698 : bool read_offset;
1699 4499 : if (flags == SegmentFlags::kActiveNoIndex) {
1700 4288 : *is_active = true;
1701 : read_index = false;
1702 : read_offset = true;
1703 211 : } else if (flags == SegmentFlags::kPassive) {
1704 71 : *is_active = false;
1705 : read_index = false;
1706 : read_offset = false;
1707 140 : } else if (flags == SegmentFlags::kActiveWithIndex) {
1708 140 : *is_active = true;
1709 : read_index = true;
1710 : read_offset = true;
1711 : } else {
1712 0 : errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
1713 0 : return;
1714 : }
1715 :
1716 4499 : if (read_index) {
1717 280 : *index = consume_u32v(name);
1718 : } else {
1719 4359 : *index = 0;
1720 : }
1721 :
1722 4499 : if (read_offset) {
1723 4428 : *offset = consume_init_expr(module_.get(), kWasmI32);
1724 : }
1725 : }
1726 :
1727 : uint32_t consume_element_func_index() {
1728 8429 : WasmFunction* func = nullptr;
1729 : uint32_t index =
1730 : consume_func_index(module_.get(), &func, "element function index");
1731 : if (failed()) return index;
1732 : DCHECK_NE(func, nullptr);
1733 : DCHECK_EQ(index, func->func_index);
1734 : DCHECK_NE(index, WasmElemSegment::kNullIndex);
1735 : return index;
1736 : }
1737 :
1738 55 : uint32_t consume_passive_element() {
1739 : uint32_t index = WasmElemSegment::kNullIndex;
1740 55 : uint8_t opcode = consume_u8("element opcode");
1741 55 : if (failed()) return index;
1742 55 : switch (opcode) {
1743 : case kExprRefNull:
1744 : index = WasmElemSegment::kNullIndex;
1745 : break;
1746 : case kExprRefFunc:
1747 : index = consume_element_func_index();
1748 50 : if (failed()) return index;
1749 : break;
1750 : default:
1751 0 : error("invalid opcode in element");
1752 0 : break;
1753 : }
1754 55 : expect_u8("end opcode", kExprEnd);
1755 55 : return index;
1756 : }
1757 : };
1758 :
1759 284965 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
1760 : const byte* module_start, const byte* module_end,
1761 : bool verify_functions, ModuleOrigin origin,
1762 : Counters* counters,
1763 : AccountingAllocator* allocator) {
1764 : auto counter =
1765 284965 : SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
1766 : TimedHistogramScope wasm_decode_module_time_scope(counter);
1767 284968 : size_t size = module_end - module_start;
1768 284968 : CHECK_LE(module_start, module_end);
1769 284968 : if (size >= kV8MaxWasmModuleSize) {
1770 : return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
1771 0 : kV8MaxWasmModuleSize, size}};
1772 : }
1773 : // TODO(bradnelson): Improve histogram handling of size_t.
1774 : auto size_counter =
1775 284968 : SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
1776 284968 : size_counter->AddSample(static_cast<int>(size));
1777 : // Signatures are stored in zone memory, which have the same lifetime
1778 : // as the {module}.
1779 569940 : ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
1780 : ModuleResult result =
1781 854903 : decoder.DecodeModule(counters, allocator, verify_functions);
1782 : // TODO(bradnelson): Improve histogram handling of size_t.
1783 : // TODO(titzer): this isn't accurate, since it doesn't count the data
1784 : // allocated on the C++ heap.
1785 : // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
1786 284963 : if (result.ok()) {
1787 258932 : auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
1788 : module_peak_memory_bytes);
1789 258932 : peak_counter->AddSample(
1790 258932 : static_cast<int>(result.value()->signature_zone->allocation_size()));
1791 : }
1792 : return result;
1793 : }
1794 :
1795 452 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
1796 904 : : enabled_features_(enabled) {}
1797 :
1798 : ModuleDecoder::~ModuleDecoder() = default;
1799 :
1800 764 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
1801 764 : return impl_->shared_module();
1802 : }
1803 :
1804 408 : void ModuleDecoder::StartDecoding(Counters* counters,
1805 : AccountingAllocator* allocator,
1806 : ModuleOrigin origin) {
1807 : DCHECK_NULL(impl_);
1808 408 : impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
1809 408 : impl_->StartDecoding(counters, allocator);
1810 408 : }
1811 :
1812 408 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
1813 : uint32_t offset) {
1814 816 : impl_->DecodeModuleHeader(bytes, offset);
1815 408 : }
1816 :
1817 1060 : void ModuleDecoder::DecodeSection(SectionCode section_code,
1818 : Vector<const uint8_t> bytes, uint32_t offset,
1819 : bool verify_functions) {
1820 2120 : impl_->DecodeSection(section_code, bytes, offset, verify_functions);
1821 1060 : }
1822 :
1823 508 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
1824 : uint32_t offset, bool verify_functions) {
1825 1016 : impl_->DecodeFunctionBody(index, length, offset, verify_functions);
1826 508 : }
1827 :
1828 268 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
1829 : uint32_t offset) {
1830 268 : return impl_->CheckFunctionsCount(functions_count, offset);
1831 : }
1832 :
1833 248 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
1834 744 : return impl_->FinishDecoding(verify_functions);
1835 : }
1836 :
1837 36033 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
1838 : const byte* end) {
1839 36033 : WireBytesRef string = consume_string(decoder, true, "section name");
1840 36035 : if (decoder.failed() || decoder.pc() > end) {
1841 : return kUnknownSectionCode;
1842 : }
1843 : const byte* section_name_start =
1844 27848 : decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
1845 :
1846 : TRACE(" +%d section name : \"%.*s\"\n",
1847 : static_cast<int>(section_name_start - decoder.start()),
1848 : string.length() < 20 ? string.length() : 20, section_name_start);
1849 :
1850 54396 : if (string.length() == num_chars(kNameString) &&
1851 26548 : strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
1852 : num_chars(kNameString)) == 0) {
1853 : return kNameSectionCode;
1854 1635 : } else if (string.length() == num_chars(kSourceMappingURLString) &&
1855 297 : strncmp(reinterpret_cast<const char*>(section_name_start),
1856 : kSourceMappingURLString,
1857 : num_chars(kSourceMappingURLString)) == 0) {
1858 : return kSourceMappingURLSectionCode;
1859 1603 : } else if (string.length() == num_chars(kCompilationHintsString) &&
1860 281 : strncmp(reinterpret_cast<const char*>(section_name_start),
1861 : kCompilationHintsString,
1862 : num_chars(kCompilationHintsString)) == 0) {
1863 : return kCompilationHintsSectionCode;
1864 : }
1865 1169 : return kUnknownSectionCode;
1866 : }
1867 :
1868 2936 : bool ModuleDecoder::ok() { return impl_->ok(); }
1869 :
1870 262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
1871 : Zone* zone, const byte* start,
1872 : const byte* end) {
1873 524 : ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1874 262 : return decoder.DecodeFunctionSignature(zone, start);
1875 : }
1876 :
1877 22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
1878 : const byte* start, const byte* end) {
1879 44 : AccountingAllocator allocator;
1880 44 : ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1881 22 : return decoder.DecodeInitExpr(start);
1882 : }
1883 :
1884 1 : FunctionResult DecodeWasmFunctionForTesting(
1885 : const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
1886 : const WasmModule* module, const byte* function_start,
1887 : const byte* function_end, Counters* counters) {
1888 1 : size_t size = function_end - function_start;
1889 1 : CHECK_LE(function_start, function_end);
1890 1 : auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
1891 : function_size_bytes);
1892 : // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
1893 1 : size_histogram->AddSample(static_cast<int>(size));
1894 1 : if (size > kV8MaxWasmFunctionSize) {
1895 : return FunctionResult{WasmError{0,
1896 : "size > maximum function size (%zu): %zu",
1897 0 : kV8MaxWasmFunctionSize, size}};
1898 : }
1899 2 : ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
1900 : decoder.SetCounters(counters);
1901 2 : return decoder.DecodeSingleFunction(zone, wire_bytes, module,
1902 2 : base::make_unique<WasmFunction>());
1903 : }
1904 :
1905 140 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
1906 : const byte* tables_end) {
1907 140 : AsmJsOffsets table;
1908 :
1909 : Decoder decoder(tables_start, tables_end);
1910 : uint32_t functions_count = decoder.consume_u32v("functions count");
1911 : // Reserve space for the entries, taking care of invalid input.
1912 140 : if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
1913 140 : table.reserve(functions_count);
1914 : }
1915 :
1916 804 : for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1917 : uint32_t size = decoder.consume_u32v("table size");
1918 332 : if (size == 0) {
1919 140 : table.emplace_back();
1920 140 : continue;
1921 : }
1922 192 : if (!decoder.checkAvailable(size)) {
1923 0 : decoder.error("illegal asm function offset table size");
1924 : }
1925 192 : const byte* table_end = decoder.pc() + size;
1926 : uint32_t locals_size = decoder.consume_u32v("locals size");
1927 192 : int function_start_position = decoder.consume_u32v("function start pos");
1928 192 : int last_byte_offset = locals_size;
1929 : int last_asm_position = function_start_position;
1930 : std::vector<AsmJsOffsetEntry> func_asm_offsets;
1931 192 : func_asm_offsets.reserve(size / 4); // conservative estimation
1932 : // Add an entry for the stack check, associated with position 0.
1933 384 : func_asm_offsets.push_back(
1934 : {0, function_start_position, function_start_position});
1935 704 : while (decoder.ok() && decoder.pc() < table_end) {
1936 256 : last_byte_offset += decoder.consume_u32v("byte offset delta");
1937 : int call_position =
1938 256 : last_asm_position + decoder.consume_i32v("call position delta");
1939 : int to_number_position =
1940 256 : call_position + decoder.consume_i32v("to_number position delta");
1941 : last_asm_position = to_number_position;
1942 512 : func_asm_offsets.push_back(
1943 : {last_byte_offset, call_position, to_number_position});
1944 : }
1945 192 : if (decoder.pc() != table_end) {
1946 0 : decoder.error("broken asm offset table");
1947 : }
1948 : table.push_back(std::move(func_asm_offsets));
1949 : }
1950 140 : if (decoder.more()) decoder.error("unexpected additional bytes");
1951 :
1952 420 : return decoder.toResult(std::move(table));
1953 : }
1954 :
1955 250 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
1956 : const byte* end) {
1957 : Decoder decoder(start, end);
1958 250 : decoder.consume_bytes(4, "wasm magic");
1959 250 : decoder.consume_bytes(4, "wasm version");
1960 :
1961 : std::vector<CustomSectionOffset> result;
1962 :
1963 577 : while (decoder.more()) {
1964 : byte section_code = decoder.consume_u8("section code");
1965 : uint32_t section_length = decoder.consume_u32v("section length");
1966 : uint32_t section_start = decoder.pc_offset();
1967 335 : if (section_code != 0) {
1968 : // Skip known sections.
1969 2 : decoder.consume_bytes(section_length, "section bytes");
1970 2 : continue;
1971 : }
1972 : uint32_t name_length = decoder.consume_u32v("name length");
1973 : uint32_t name_offset = decoder.pc_offset();
1974 333 : decoder.consume_bytes(name_length, "section name");
1975 : uint32_t payload_offset = decoder.pc_offset();
1976 333 : if (section_length < (payload_offset - section_start)) {
1977 8 : decoder.error("invalid section length");
1978 8 : break;
1979 : }
1980 325 : uint32_t payload_length = section_length - (payload_offset - section_start);
1981 325 : decoder.consume_bytes(payload_length);
1982 325 : if (decoder.failed()) break;
1983 325 : result.push_back({{section_start, section_length},
1984 : {name_offset, name_length},
1985 : {payload_offset, payload_length}});
1986 : }
1987 :
1988 250 : return result;
1989 : }
1990 :
1991 : namespace {
1992 :
1993 127258 : bool FindNameSection(Decoder& decoder) {
1994 : static constexpr int kModuleHeaderSize = 8;
1995 127258 : decoder.consume_bytes(kModuleHeaderSize, "module header");
1996 :
1997 : WasmSectionIterator section_iter(decoder);
1998 :
1999 267686 : while (decoder.ok() && section_iter.more() &&
2000 : section_iter.section_code() != kNameSectionCode) {
2001 43195 : section_iter.advance(true);
2002 : }
2003 127258 : if (!section_iter.more()) return false;
2004 :
2005 : // Reset the decoder to not read beyond the name section end.
2006 : decoder.Reset(section_iter.payload(), decoder.pc_offset());
2007 2934 : return true;
2008 : }
2009 :
2010 : } // namespace
2011 :
2012 127238 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
2013 : std::unordered_map<uint32_t, WireBytesRef>* names) {
2014 : DCHECK_NOT_NULL(names);
2015 : DCHECK(names->empty());
2016 :
2017 : Decoder decoder(module_start, module_end);
2018 127238 : if (!FindNameSection(decoder)) return;
2019 :
2020 5844 : while (decoder.ok() && decoder.more()) {
2021 : uint8_t name_type = decoder.consume_u8("name type");
2022 2930 : if (name_type & 0x80) break; // no varuint7
2023 :
2024 : uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2025 2930 : if (!decoder.checkAvailable(name_payload_len)) break;
2026 :
2027 2930 : if (name_type != NameSectionKindCode::kFunction) {
2028 28 : decoder.consume_bytes(name_payload_len, "name subsection payload");
2029 28 : continue;
2030 : }
2031 : uint32_t functions_count = decoder.consume_u32v("functions count");
2032 :
2033 33024 : for (; decoder.ok() && functions_count > 0; --functions_count) {
2034 : uint32_t function_index = decoder.consume_u32v("function index");
2035 15061 : WireBytesRef name = consume_string(decoder, false, "function name");
2036 :
2037 : // Be lenient with errors in the name section: Ignore non-UTF8 names. You
2038 : // can even assign to the same function multiple times (last valid one
2039 : // wins).
2040 30122 : if (decoder.ok() && validate_utf8(&decoder, name)) {
2041 30106 : names->insert(std::make_pair(function_index, name));
2042 : }
2043 : }
2044 : }
2045 : }
2046 :
2047 20 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
2048 : LocalNames* result) {
2049 : DCHECK_NOT_NULL(result);
2050 : DCHECK(result->names.empty());
2051 :
2052 : Decoder decoder(module_start, module_end);
2053 20 : if (!FindNameSection(decoder)) return;
2054 :
2055 44 : while (decoder.ok() && decoder.more()) {
2056 : uint8_t name_type = decoder.consume_u8("name type");
2057 24 : if (name_type & 0x80) break; // no varuint7
2058 :
2059 : uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2060 24 : if (!decoder.checkAvailable(name_payload_len)) break;
2061 :
2062 24 : if (name_type != NameSectionKindCode::kLocal) {
2063 20 : decoder.consume_bytes(name_payload_len, "name subsection payload");
2064 20 : continue;
2065 : }
2066 :
2067 : uint32_t local_names_count = decoder.consume_u32v("local names count");
2068 12 : for (uint32_t i = 0; i < local_names_count; ++i) {
2069 : uint32_t func_index = decoder.consume_u32v("function index");
2070 4 : if (func_index > kMaxInt) continue;
2071 4 : result->names.emplace_back(static_cast<int>(func_index));
2072 : LocalNamesPerFunction& func_names = result->names.back();
2073 : result->max_function_index =
2074 8 : std::max(result->max_function_index, func_names.function_index);
2075 : uint32_t num_names = decoder.consume_u32v("namings count");
2076 28 : for (uint32_t k = 0; k < num_names; ++k) {
2077 : uint32_t local_index = decoder.consume_u32v("local index");
2078 12 : WireBytesRef name = consume_string(decoder, true, "local name");
2079 12 : if (!decoder.ok()) break;
2080 12 : if (local_index > kMaxInt) continue;
2081 : func_names.max_local_index =
2082 24 : std::max(func_names.max_local_index, static_cast<int>(local_index));
2083 12 : func_names.names.emplace_back(static_cast<int>(local_index), name);
2084 : }
2085 : }
2086 : }
2087 : }
2088 :
2089 : #undef TRACE
2090 :
2091 : } // namespace wasm
2092 : } // namespace internal
2093 122004 : } // namespace v8
|