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 30116 : return unibrow::Utf8::ValidateEncoding(
103 : decoder->start() + decoder->GetBufferRelativeOffset(string.offset()),
104 15058 : string.length());
105 : }
106 :
107 445960 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
108 445960 : 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 873898 : 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 873898 : if (length > 0) {
139 862855 : decoder.consume_bytes(length, name);
140 1708293 : if (decoder.ok() && validate_utf8 &&
141 845427 : !unibrow::Utf8::ValidateEncoding(string_start, length)) {
142 8642 : decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
143 : }
144 : }
145 873912 : 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 404042 : section_end_(decoder.pc()) {
157 404042 : next();
158 : }
159 :
160 1738852 : 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 1293875 : 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 2579751 : 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 1331699 : void advance(bool move_to_section_end = false) {
185 1331699 : if (move_to_section_end && decoder_.pc() < section_end_) {
186 1330079 : decoder_.consume_bytes(
187 2660158 : static_cast<uint32_t>(section_end_ - decoder_.pc()));
188 : }
189 1331696 : 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 1331696 : next();
198 1331716 : }
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 1735737 : void next() {
210 1735737 : if (!decoder_.more()) {
211 280857 : section_code_ = kUnknownSectionCode;
212 280857 : return;
213 : }
214 1454880 : section_start_ = decoder_.pc();
215 : uint8_t section_code = decoder_.consume_u8("section code");
216 : // Read and check the section size.
217 1454888 : uint32_t section_length = decoder_.consume_u32v("section length");
218 :
219 1454892 : payload_start_ = decoder_.pc();
220 1454896 : if (decoder_.checkAvailable(section_length)) {
221 : // Get the limit of the section within the module.
222 1343044 : section_end_ = payload_start_ + section_length;
223 : } else {
224 : // The section would extend beyond the end of the module.
225 111852 : section_end_ = payload_start_;
226 : }
227 :
228 1454896 : if (section_code == kUnknownSectionCode) {
229 : // Check for the known "name", "sourceMappingURL", or "compilationHints"
230 : // section.
231 : section_code =
232 34967 : ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_);
233 : // As a side effect, the above function will forward the decoder to after
234 : // the identifier string.
235 34961 : payload_start_ = decoder_.pc();
236 1419929 : } else if (!IsValidSectionCode(section_code)) {
237 110928 : decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
238 110928 : section_code);
239 : section_code = kUnknownSectionCode;
240 : }
241 1454897 : section_code_ = decoder_.failed() ? kUnknownSectionCode
242 1454897 : : static_cast<SectionCode>(section_code);
243 :
244 1454897 : if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) {
245 : // skip to the end of the unknown section.
246 3848 : uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc());
247 3848 : 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 570326 : class ModuleDecoderImpl : public Decoder {
256 : public:
257 : explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin)
258 : : Decoder(nullptr, nullptr),
259 : enabled_features_(enabled),
260 1056 : origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {}
261 :
262 284634 : 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 853902 : origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
267 284634 : if (end_ < start_) {
268 0 : error(start_, "end is less than start");
269 0 : end_ = start_;
270 : }
271 284634 : }
272 :
273 15545 : void onFirstError() override {
274 15545 : pc_ = end_; // On error, terminate section decoding loop.
275 15545 : }
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 284695 : void StartDecoding(Counters* counters, AccountingAllocator* allocator) {
302 284695 : CHECK_NULL(module_);
303 : SetCounters(counters);
304 569400 : module_.reset(
305 854099 : new WasmModule(base::make_unique<Zone>(allocator, "signatures")));
306 284705 : module_->initial_pages = 0;
307 284705 : module_->maximum_pages = 0;
308 284705 : module_->mem_export = false;
309 284705 : module_->origin = origin_;
310 284705 : }
311 :
312 284699 : void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) {
313 284699 : if (failed()) return;
314 284700 : Reset(bytes, offset);
315 :
316 284694 : 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 284704 : 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 284704 : pos = pc_;
327 : {
328 : uint32_t magic_version = consume_u32("wasm version");
329 284703 : 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 441 : bool CheckSectionOrder(SectionCode section_code,
340 : SectionCode prev_section_code,
341 : SectionCode next_section_code) {
342 441 : 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 438 : if (next_ordered_section_ <= prev_section_code) {
348 428 : next_ordered_section_ = prev_section_code + 1;
349 : }
350 : return true;
351 : }
352 :
353 442 : bool CheckUnorderedSection(SectionCode section_code) {
354 442 : 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 441 : return true;
361 : }
362 :
363 1288904 : void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes,
364 : uint32_t offset, bool verify_functions = true) {
365 1288904 : if (failed()) return;
366 1288909 : 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 1288916 : 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 1288904 : switch (section_code) {
379 : case kUnknownSectionCode:
380 : break;
381 : case kDataCountSectionCode:
382 44 : if (!CheckUnorderedSection(section_code)) return;
383 43 : if (!CheckSectionOrder(section_code, kElementSectionCode,
384 : kCodeSectionCode))
385 : return;
386 : break;
387 : case kExceptionSectionCode:
388 398 : if (!CheckUnorderedSection(section_code)) return;
389 398 : 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 1265723 : next_ordered_section_ = section_code + 1;
410 1265723 : break;
411 : }
412 :
413 1288863 : switch (section_code) {
414 : case kUnknownSectionCode:
415 : break;
416 : case kTypeSectionCode:
417 260289 : DecodeTypeSection();
418 260299 : break;
419 : case kImportSectionCode:
420 232106 : DecodeImportSection();
421 232110 : break;
422 : case kFunctionSectionCode:
423 258430 : DecodeFunctionSection();
424 258434 : break;
425 : case kTableSectionCode:
426 2624 : DecodeTableSection();
427 2624 : break;
428 : case kMemorySectionCode:
429 10972 : DecodeMemorySection();
430 10972 : break;
431 : case kGlobalSectionCode:
432 2827 : DecodeGlobalSection();
433 2827 : break;
434 : case kExportSectionCode:
435 234116 : DecodeExportSection();
436 234114 : break;
437 : case kStartSectionCode:
438 2762 : DecodeStartSection();
439 2762 : break;
440 : case kCodeSectionCode:
441 257770 : DecodeCodeSection(verify_functions);
442 257774 : break;
443 : case kElementSectionCode:
444 2334 : DecodeElementSection();
445 2334 : break;
446 : case kDataSectionCode:
447 1466 : DecodeDataSection();
448 1466 : break;
449 : case kNameSectionCode:
450 22665 : DecodeNameSection();
451 22667 : break;
452 : case kSourceMappingURLSectionCode:
453 8 : DecodeSourceMappingURLSection();
454 8 : break;
455 : case kCompilationHintsSectionCode:
456 57 : if (enabled_features_.compilation_hints) {
457 57 : DecodeCompilationHintsSection();
458 : } else {
459 : // Ignore this section when feature was disabled. It is an optional
460 : // custom section anyways.
461 : }
462 : break;
463 : case kDataCountSectionCode:
464 42 : if (enabled_features_.bulk_memory) {
465 : DecodeDataCountSection();
466 : } else {
467 2 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
468 : }
469 : break;
470 : case kExceptionSectionCode:
471 396 : if (enabled_features_.eh) {
472 386 : DecodeExceptionSection();
473 : } else {
474 10 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
475 : }
476 : break;
477 : default:
478 0 : errorf(pc(), "unexpected section <%s>", SectionName(section_code));
479 0 : return;
480 : }
481 :
482 1288885 : if (pc() != bytes.end()) {
483 132 : const char* msg = pc() < bytes.end() ? "shorter" : "longer";
484 132 : errorf(pc(),
485 : "section was %s than expected size "
486 : "(%zu bytes expected, %zu decoded)",
487 264 : msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin()));
488 : }
489 : }
490 :
491 260288 : void DecodeTypeSection() {
492 260288 : uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
493 260294 : module_->signatures.reserve(signatures_count);
494 1393490 : for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
495 : TRACE("DecodeSignature[%d] module+%d\n", i,
496 : static_cast<int>(pc_ - start_));
497 566595 : FunctionSig* s = consume_sig(module_->signature_zone.get());
498 566595 : module_->signatures.push_back(s);
499 566595 : uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0;
500 566593 : module_->signature_ids.push_back(id);
501 : }
502 : module_->signature_map.Freeze();
503 260301 : }
504 :
505 232106 : void DecodeImportSection() {
506 : uint32_t import_table_count =
507 232106 : consume_count("imports count", kV8MaxWasmImports);
508 232112 : module_->import_table.reserve(import_table_count);
509 704639 : for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
510 : TRACE("DecodeImportTable[%d] module+%d\n", i,
511 : static_cast<int>(pc_ - start_));
512 :
513 472533 : module_->import_table.push_back({
514 : {0, 0}, // module_name
515 : {0, 0}, // field_name
516 : kExternalFunction, // kind
517 : 0 // index
518 : });
519 : WasmImport* import = &module_->import_table.back();
520 236265 : const byte* pos = pc_;
521 236265 : import->module_name = consume_string(*this, true, "module name");
522 236263 : import->field_name = consume_string(*this, true, "field name");
523 : import->kind =
524 236253 : static_cast<ImportExportKindCode>(consume_u8("import kind"));
525 236253 : switch (import->kind) {
526 : case kExternalFunction: {
527 : // ===== Imported function ===========================================
528 227354 : import->index = static_cast<uint32_t>(module_->functions.size());
529 227354 : module_->num_imported_functions++;
530 909415 : module_->functions.push_back({nullptr, // sig
531 227354 : import->index, // func_index
532 : 0, // sig_index
533 : {0, 0}, // code
534 : true, // imported
535 : false}); // exported
536 : WasmFunction* function = &module_->functions.back();
537 : function->sig_index =
538 227353 : consume_sig_index(module_.get(), &function->sig);
539 227353 : break;
540 : }
541 : case kExternalTable: {
542 : // ===== Imported table ==============================================
543 1618 : if (!AddTable(module_.get())) break;
544 1607 : import->index = static_cast<uint32_t>(module_->tables.size());
545 1607 : module_->num_imported_tables++;
546 1607 : module_->tables.emplace_back();
547 : WasmTable* table = &module_->tables.back();
548 1607 : table->imported = true;
549 1607 : ValueType type = consume_reference_type();
550 1607 : if (!enabled_features_.anyref) {
551 1545 : if (type != kWasmAnyFunc) {
552 0 : error(pc_ - 1, "invalid table type");
553 0 : break;
554 : }
555 : }
556 1607 : table->type = type;
557 1607 : uint8_t flags = validate_table_flags("element count");
558 1607 : consume_resizable_limits(
559 : "element count", "elements", FLAG_wasm_max_table_size,
560 : &table->initial_size, &table->has_maximum_size,
561 1607 : FLAG_wasm_max_table_size, &table->maximum_size, flags);
562 1607 : break;
563 : }
564 : case kExternalMemory: {
565 : // ===== Imported memory =============================================
566 4975 : if (!AddMemory(module_.get())) break;
567 4951 : uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
568 4953 : consume_resizable_limits(
569 : "memory", "pages", kSpecMaxWasmMemoryPages,
570 : &module_->initial_pages, &module_->has_maximum_pages,
571 4953 : kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags);
572 4961 : break;
573 : }
574 : case kExternalGlobal: {
575 : // ===== Imported global =============================================
576 2196 : import->index = static_cast<uint32_t>(module_->globals.size());
577 6588 : module_->globals.push_back(
578 : {kWasmStmt, false, WasmInitExpr(), {0}, true, false});
579 : WasmGlobal* global = &module_->globals.back();
580 2196 : global->type = consume_value_type();
581 2196 : global->mutability = consume_mutability();
582 2196 : if (global->mutability) {
583 339 : module_->num_imported_mutable_globals++;
584 : }
585 : break;
586 : }
587 : case kExternalException: {
588 : // ===== Imported exception ==========================================
589 106 : if (!enabled_features_.eh) {
590 1 : errorf(pos, "unknown import kind 0x%02x", import->kind);
591 1 : break;
592 : }
593 105 : import->index = static_cast<uint32_t>(module_->exceptions.size());
594 105 : WasmExceptionSig* exception_sig = nullptr;
595 105 : consume_exception_attribute(); // Attribute ignored for now.
596 105 : consume_exception_sig_index(module_.get(), &exception_sig);
597 105 : module_->exceptions.emplace_back(exception_sig);
598 105 : break;
599 : }
600 : default:
601 0 : errorf(pos, "unknown import kind 0x%02x", import->kind);
602 0 : break;
603 : }
604 : }
605 232113 : }
606 :
607 258422 : void DecodeFunctionSection() {
608 : uint32_t functions_count =
609 258422 : consume_count("functions count", kV8MaxWasmFunctions);
610 : auto counter =
611 258426 : SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module);
612 258426 : counter->AddSample(static_cast<int>(functions_count));
613 : DCHECK_EQ(module_->functions.size(), module_->num_imported_functions);
614 : uint32_t total_function_count =
615 258434 : module_->num_imported_functions + functions_count;
616 258434 : module_->functions.reserve(total_function_count);
617 258430 : module_->num_declared_functions = functions_count;
618 1034422 : for (uint32_t i = 0; i < functions_count; ++i) {
619 388034 : uint32_t func_index = static_cast<uint32_t>(module_->functions.size());
620 1164103 : module_->functions.push_back({nullptr, // sig
621 : func_index, // func_index
622 : 0, // sig_index
623 : {0, 0}, // code
624 : false, // imported
625 : false}); // exported
626 : WasmFunction* function = &module_->functions.back();
627 388035 : function->sig_index = consume_sig_index(module_.get(), &function->sig);
628 388037 : if (!ok()) return;
629 : }
630 : DCHECK_EQ(module_->functions.size(), total_function_count);
631 : }
632 :
633 2624 : void DecodeTableSection() {
634 : // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the
635 : // implementation of AnyRef landed.
636 2624 : uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables;
637 2624 : uint32_t table_count = consume_count("table count", max_count);
638 :
639 7900 : for (uint32_t i = 0; ok() && i < table_count; i++) {
640 2654 : if (!AddTable(module_.get())) break;
641 2638 : module_->tables.emplace_back();
642 : WasmTable* table = &module_->tables.back();
643 2638 : table->type = consume_reference_type();
644 2638 : uint8_t flags = validate_table_flags("table elements");
645 2638 : consume_resizable_limits(
646 : "table elements", "elements", FLAG_wasm_max_table_size,
647 : &table->initial_size, &table->has_maximum_size,
648 2638 : FLAG_wasm_max_table_size, &table->maximum_size, flags);
649 : }
650 2624 : }
651 :
652 10972 : void DecodeMemorySection() {
653 10972 : uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
654 :
655 32736 : for (uint32_t i = 0; ok() && i < memory_count; i++) {
656 10922 : if (!AddMemory(module_.get())) break;
657 10882 : uint8_t flags = validate_memory_flags(&module_->has_shared_memory);
658 10882 : consume_resizable_limits(
659 : "memory", "pages", kSpecMaxWasmMemoryPages, &module_->initial_pages,
660 : &module_->has_maximum_pages, kSpecMaxWasmMemoryPages,
661 10882 : &module_->maximum_pages, flags);
662 : }
663 10972 : }
664 :
665 2827 : void DecodeGlobalSection() {
666 2827 : uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals);
667 2827 : uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size());
668 2827 : module_->globals.reserve(imported_globals + globals_count);
669 885195 : for (uint32_t i = 0; ok() && i < globals_count; ++i) {
670 : TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_));
671 : // Add an uninitialized global and pass a pointer to it.
672 1323552 : module_->globals.push_back(
673 : {kWasmStmt, false, WasmInitExpr(), {0}, false, false});
674 : WasmGlobal* global = &module_->globals.back();
675 441184 : DecodeGlobalInModule(module_.get(), i + imported_globals, global);
676 : }
677 2827 : if (ok()) CalculateGlobalOffsets(module_.get());
678 2827 : }
679 :
680 234107 : void DecodeExportSection() {
681 : uint32_t export_table_count =
682 234107 : consume_count("exports count", kV8MaxWasmExports);
683 234112 : module_->export_table.reserve(export_table_count);
684 936468 : for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
685 : TRACE("DecodeExportTable[%d] module+%d\n", i,
686 : static_cast<int>(pc_ - start_));
687 :
688 702368 : module_->export_table.push_back({
689 : {0, 0}, // name
690 : kExternalFunction, // kind
691 : 0 // index
692 : });
693 : WasmExport* exp = &module_->export_table.back();
694 :
695 351183 : exp->name = consume_string(*this, true, "field name");
696 :
697 : const byte* pos = pc();
698 351173 : exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind"));
699 351173 : switch (exp->kind) {
700 : case kExternalFunction: {
701 347406 : WasmFunction* func = nullptr;
702 : exp->index =
703 347404 : consume_func_index(module_.get(), &func, "export function index");
704 347404 : module_->num_exported_functions++;
705 347404 : if (func) func->exported = true;
706 : break;
707 : }
708 : case kExternalTable: {
709 768 : WasmTable* table = nullptr;
710 768 : exp->index = consume_table_index(module_.get(), &table);
711 768 : if (table) table->exported = true;
712 : break;
713 : }
714 : case kExternalMemory: {
715 : uint32_t index = consume_u32v("memory index");
716 : // TODO(titzer): This should become more regular
717 : // once we support multiple memories.
718 1740 : if (!module_->has_memory || index != 0) {
719 24 : error("invalid memory index != 0");
720 : }
721 1740 : module_->mem_export = true;
722 1740 : break;
723 : }
724 : case kExternalGlobal: {
725 1114 : WasmGlobal* global = nullptr;
726 1114 : exp->index = consume_global_index(module_.get(), &global);
727 1114 : if (global) {
728 1098 : global->exported = true;
729 : }
730 : break;
731 : }
732 : case kExternalException: {
733 145 : if (!enabled_features_.eh) {
734 0 : errorf(pos, "invalid export kind 0x%02x", exp->kind);
735 0 : break;
736 : }
737 145 : WasmException* exception = nullptr;
738 145 : exp->index = consume_exception_index(module_.get(), &exception);
739 145 : break;
740 : }
741 : default:
742 0 : errorf(pos, "invalid export kind 0x%02x", exp->kind);
743 0 : break;
744 : }
745 : }
746 : // Check for duplicate exports (except for asm.js).
747 465654 : if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) {
748 7602 : std::vector<WasmExport> sorted_exports(module_->export_table);
749 :
750 1107862 : auto cmp_less = [this](const WasmExport& a, const WasmExport& b) {
751 : // Return true if a < b.
752 631566 : if (a.name.length() != b.name.length()) {
753 155270 : return a.name.length() < b.name.length();
754 : }
755 476296 : const byte* left = start() + GetBufferRelativeOffset(a.name.offset());
756 476296 : const byte* right = start() + GetBufferRelativeOffset(b.name.offset());
757 476296 : return memcmp(left, right, a.name.length()) < 0;
758 7602 : };
759 : std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less);
760 :
761 : auto it = sorted_exports.begin();
762 : WasmExport* last = &*it++;
763 237482 : for (auto end = sorted_exports.end(); it != end; last = &*it++) {
764 : DCHECK(!cmp_less(*it, *last)); // Vector must be sorted.
765 115268 : if (!cmp_less(*last, *it)) {
766 328 : const byte* pc = start() + GetBufferRelativeOffset(it->name.offset());
767 328 : TruncatedUserString<> name(pc, it->name.length());
768 984 : errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d",
769 328 : name.length(), name.start(), ExternalKindName(last->kind),
770 656 : last->index, ExternalKindName(it->kind), it->index);
771 : break;
772 : }
773 : }
774 : }
775 234112 : }
776 :
777 2762 : void DecodeStartSection() {
778 : WasmFunction* func;
779 2762 : const byte* pos = pc_;
780 : module_->start_function_index =
781 2762 : consume_func_index(module_.get(), &func, "start function index");
782 8246 : if (func &&
783 5404 : (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
784 64 : error(pos, "invalid start function: non-zero parameter or return count");
785 : }
786 2762 : }
787 :
788 2334 : void DecodeElementSection() {
789 : uint32_t element_count =
790 2334 : consume_count("element count", FLAG_wasm_max_table_size);
791 :
792 4648 : if (element_count > 0 && module_->tables.size() == 0) {
793 49 : error(pc_, "The element section requires a table");
794 : }
795 7868 : for (uint32_t i = 0; ok() && i < element_count; ++i) {
796 : const byte* pos = pc();
797 :
798 : bool is_active;
799 : uint32_t table_index;
800 : WasmInitExpr offset;
801 2899 : consume_segment_header("table index", &is_active, &table_index, &offset);
802 3028 : if (failed()) return;
803 :
804 2770 : if (is_active) {
805 5448 : if (table_index >= module_->tables.size()) {
806 0 : errorf(pos, "out of bounds table index %u", table_index);
807 0 : break;
808 : }
809 2724 : if (module_->tables[table_index].type != kWasmAnyFunc) {
810 2 : errorf(pos,
811 : "Invalid element segment. Table %u is not of type AnyFunc",
812 2 : table_index);
813 2 : break;
814 : }
815 : } else {
816 46 : ValueType type = consume_reference_type();
817 46 : if (type != kWasmAnyFunc) {
818 1 : error(pc_ - 1, "invalid element segment type");
819 1 : break;
820 : }
821 : }
822 :
823 : uint32_t num_elem =
824 2767 : consume_count("number of elements", max_table_init_entries());
825 2767 : if (is_active) {
826 2722 : module_->elem_segments.emplace_back(table_index, offset);
827 : } else {
828 45 : module_->elem_segments.emplace_back();
829 : }
830 :
831 : WasmElemSegment* init = &module_->elem_segments.back();
832 20033 : for (uint32_t j = 0; j < num_elem; j++) {
833 : uint32_t index = is_active ? consume_element_func_index()
834 8817 : : consume_passive_element();
835 8650 : if (failed()) break;
836 8633 : init->entries.push_back(index);
837 : }
838 : }
839 : }
840 :
841 257760 : void DecodeCodeSection(bool verify_functions) {
842 : uint32_t pos = pc_offset();
843 257760 : uint32_t functions_count = consume_u32v("functions count");
844 257764 : CheckFunctionsCount(functions_count, pos);
845 1031472 : for (uint32_t i = 0; ok() && i < functions_count; ++i) {
846 : const byte* pos = pc();
847 : uint32_t size = consume_u32v("body size");
848 386851 : if (size > kV8MaxWasmFunctionSize) {
849 : errorf(pos, "size %u > maximum function size %zu", size,
850 3 : kV8MaxWasmFunctionSize);
851 3 : return;
852 : }
853 : uint32_t offset = pc_offset();
854 386848 : consume_bytes(size, "function body");
855 386853 : if (failed()) break;
856 386852 : DecodeFunctionBody(i, size, offset, verify_functions);
857 : }
858 : }
859 :
860 257989 : bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) {
861 257989 : if (functions_count != module_->num_declared_functions) {
862 79 : Reset(nullptr, nullptr, offset);
863 79 : errorf(nullptr, "function body count %u mismatch (%u expected)",
864 79 : functions_count, module_->num_declared_functions);
865 79 : return false;
866 : }
867 : return true;
868 : }
869 :
870 387305 : void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset,
871 : bool verify_functions) {
872 : WasmFunction* function =
873 387305 : &module_->functions[index + module_->num_imported_functions];
874 387305 : function->code = {offset, length};
875 387305 : if (verify_functions) {
876 136690 : ModuleWireBytes bytes(start_, end_);
877 136690 : VerifyFunctionBody(module_->signature_zone->allocator(),
878 136690 : index + module_->num_imported_functions, bytes,
879 136690 : module_.get(), function);
880 : }
881 387305 : }
882 :
883 267557 : bool CheckDataSegmentsCount(uint32_t data_segments_count) {
884 267627 : if (has_seen_unordered_section(kDataCountSectionCode) &&
885 70 : data_segments_count != module_->num_declared_data_segments) {
886 3 : errorf(pc(), "data segments count %u mismatch (%u expected)",
887 3 : data_segments_count, module_->num_declared_data_segments);
888 3 : return false;
889 : }
890 : return true;
891 : }
892 :
893 1466 : void DecodeDataSection() {
894 : uint32_t data_segments_count =
895 1466 : consume_count("data segments count", kV8MaxWasmDataSegments);
896 1466 : if (!CheckDataSegmentsCount(data_segments_count)) return;
897 :
898 1464 : module_->data_segments.reserve(data_segments_count);
899 4926 : for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
900 : const byte* pos = pc();
901 1881 : if (!module_->has_memory) {
902 65 : error("cannot load data without memory");
903 65 : break;
904 : }
905 : TRACE("DecodeDataSegment[%d] module+%d\n", i,
906 : static_cast<int>(pc_ - start_));
907 :
908 : bool is_active;
909 : uint32_t memory_index;
910 : WasmInitExpr dest_addr;
911 : consume_segment_header("memory index", &is_active, &memory_index,
912 1816 : &dest_addr);
913 1816 : if (failed()) break;
914 :
915 1732 : if (is_active && memory_index != 0) {
916 0 : errorf(pos, "illegal memory index %u != 0", memory_index);
917 0 : break;
918 : }
919 :
920 1732 : uint32_t source_length = consume_u32v("source size");
921 : uint32_t source_offset = pc_offset();
922 :
923 1732 : if (is_active) {
924 1691 : module_->data_segments.emplace_back(dest_addr);
925 : } else {
926 41 : module_->data_segments.emplace_back();
927 : }
928 :
929 : WasmDataSegment* segment = &module_->data_segments.back();
930 :
931 1732 : consume_bytes(source_length, "segment data");
932 1732 : if (failed()) break;
933 :
934 1731 : segment->source = {source_offset, source_length};
935 : }
936 : }
937 :
938 22657 : void DecodeNameSection() {
939 : // TODO(titzer): find a way to report name errors as warnings.
940 : // Ignore all but the first occurrence of name section.
941 22657 : if (!has_seen_unordered_section(kNameSectionCode)) {
942 : set_seen_unordered_section(kNameSectionCode);
943 : // Use an inner decoder so that errors don't fail the outer decoder.
944 22657 : Decoder inner(start_, pc_, end_, buffer_offset_);
945 : // Decode all name subsections.
946 : // Be lenient with their order.
947 45403 : while (inner.ok() && inner.more()) {
948 : uint8_t name_type = inner.consume_u8("name type");
949 22773 : if (name_type & 0x80) inner.error("name type if not varuint7");
950 :
951 : uint32_t name_payload_len = inner.consume_u32v("name payload length");
952 22770 : if (!inner.checkAvailable(name_payload_len)) break;
953 :
954 : // Decode module name, ignore the rest.
955 : // Function and local names will be decoded when needed.
956 22744 : if (name_type == NameSectionKindCode::kModule) {
957 139 : WireBytesRef name = consume_string(inner, false, "module name");
958 196 : if (inner.ok() && validate_utf8(&inner, name)) module_->name = name;
959 : } else {
960 22605 : inner.consume_bytes(name_payload_len, "name subsection payload");
961 : }
962 : }
963 : }
964 : // Skip the whole names section in the outer decoder.
965 22655 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
966 22667 : }
967 :
968 8 : void DecodeSourceMappingURLSection() {
969 8 : Decoder inner(start_, pc_, end_, buffer_offset_);
970 8 : WireBytesRef url = wasm::consume_string(inner, true, "module name");
971 15 : if (inner.ok() &&
972 : !has_seen_unordered_section(kSourceMappingURLSectionCode)) {
973 : const byte* url_start =
974 6 : inner.start() + inner.GetBufferRelativeOffset(url.offset());
975 : module_->source_map_url.assign(reinterpret_cast<const char*>(url_start),
976 6 : url.length());
977 : set_seen_unordered_section(kSourceMappingURLSectionCode);
978 : }
979 8 : consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
980 8 : }
981 :
982 57 : void DecodeCompilationHintsSection() {
983 : TRACE("DecodeCompilationHints module+%d\n", static_cast<int>(pc_ - start_));
984 :
985 : // TODO(frgossen): Find a way to report compilation hint errors as warnings.
986 : // All except first occurrence after function section and before code
987 : // section are ignored.
988 : const bool before_function_section =
989 57 : next_ordered_section_ <= kFunctionSectionCode;
990 57 : const bool after_code_section = next_ordered_section_ > kCodeSectionCode;
991 114 : if (before_function_section || after_code_section ||
992 : has_seen_unordered_section(kCompilationHintsSectionCode)) {
993 : return;
994 : }
995 : set_seen_unordered_section(kCompilationHintsSectionCode);
996 :
997 : // TODO(frgossen) Propagate errors to outer decoder in experimental phase.
998 : // We should use an inner decoder later and propagate its errors as
999 : // warnings.
1000 57 : Decoder& decoder = *this;
1001 : // Decoder decoder(start_, pc_, end_, buffer_offset_);
1002 :
1003 : // Ensure exactly one compilation hint per function.
1004 : uint32_t hint_count = decoder.consume_u32v("compilation hint count");
1005 57 : if (hint_count != module_->num_declared_functions) {
1006 : decoder.errorf(decoder.pc(), "Expected %u compilation hints (%u found)",
1007 0 : module_->num_declared_functions, hint_count);
1008 : }
1009 :
1010 : // Decode sequence of compilation hints.
1011 57 : if (decoder.ok()) module_->compilation_hints.reserve(hint_count);
1012 239 : for (uint32_t i = 0; decoder.ok() && i < hint_count; i++) {
1013 : TRACE("DecodeCompilationHints[%d] module+%d\n", i,
1014 : static_cast<int>(pc_ - start_));
1015 :
1016 : // Compilation hints are encoded in one byte each.
1017 : // +-------+-------------+------------+------------------+
1018 : // | 2 bit | 2 bit | 2 bit | 2 bit |
1019 : // | ... | Second tier | First tier | Lazy compilation |
1020 : // +-------+-------------+------------+------------------+
1021 : uint8_t hint_byte = decoder.consume_u8("compilation hint");
1022 91 : if (!decoder.ok()) break;
1023 :
1024 : // Decode compilation hint.
1025 : WasmCompilationHint hint;
1026 : hint.strategy =
1027 91 : static_cast<WasmCompilationHintStrategy>(hint_byte & 0x03);
1028 : hint.first_tier =
1029 91 : static_cast<WasmCompilationHintTier>(hint_byte >> 2 & 0x3);
1030 : hint.second_tier =
1031 91 : static_cast<WasmCompilationHintTier>(hint_byte >> 4 & 0x3);
1032 :
1033 : // Check strategy.
1034 91 : if (hint.strategy > WasmCompilationHintStrategy::kEager) {
1035 : decoder.errorf(decoder.pc(),
1036 : "Invalid compilation hint %#x (unknown strategy)",
1037 8 : hint_byte);
1038 : }
1039 :
1040 : // Ensure that the second tier never downgrades the compilation result.
1041 : // If first and secod tier are the same it will be invoked only once.
1042 91 : if (hint.second_tier < hint.first_tier &&
1043 : hint.second_tier != WasmCompilationHintTier::kDefault) {
1044 : decoder.errorf(decoder.pc(),
1045 : "Invalid compilation hint %#x (forbidden downgrade)",
1046 8 : hint_byte);
1047 : }
1048 :
1049 : // Happily accept compilation hint.
1050 91 : if (decoder.ok()) module_->compilation_hints.push_back(std::move(hint));
1051 : }
1052 :
1053 : // If section was invalid reset compilation hints.
1054 57 : if (decoder.failed()) {
1055 : module_->compilation_hints.clear();
1056 : }
1057 :
1058 : // @TODO(frgossen) Skip the whole compilation hints section in the outer
1059 : // decoder if inner decoder was used.
1060 : // consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr);
1061 : }
1062 :
1063 : void DecodeDataCountSection() {
1064 : module_->num_declared_data_segments =
1065 40 : consume_count("data segments count", kV8MaxWasmDataSegments);
1066 : }
1067 :
1068 386 : void DecodeExceptionSection() {
1069 : uint32_t exception_count =
1070 386 : consume_count("exception count", kV8MaxWasmExceptions);
1071 1264 : for (uint32_t i = 0; ok() && i < exception_count; ++i) {
1072 : TRACE("DecodeException[%d] module+%d\n", i,
1073 : static_cast<int>(pc_ - start_));
1074 439 : WasmExceptionSig* exception_sig = nullptr;
1075 439 : consume_exception_attribute(); // Attribute ignored for now.
1076 439 : consume_exception_sig_index(module_.get(), &exception_sig);
1077 439 : module_->exceptions.emplace_back(exception_sig);
1078 : }
1079 386 : }
1080 :
1081 266112 : bool CheckMismatchedCounts() {
1082 : // The declared vs. defined function count is normally checked when
1083 : // decoding the code section, but we have to check it here too in case the
1084 : // code section is absent.
1085 266112 : if (module_->num_declared_functions != 0) {
1086 : DCHECK_LT(module_->num_imported_functions, module_->functions.size());
1087 : // We know that the code section has been decoded if the first
1088 : // non-imported function has its code set.
1089 515470 : if (!module_->functions[module_->num_imported_functions].code.is_set()) {
1090 22 : errorf(pc(), "function count is %u, but code section is absent",
1091 22 : module_->num_declared_functions);
1092 22 : return false;
1093 : }
1094 : }
1095 : // Perform a similar check for the DataCount and Data sections, where data
1096 : // segments are declared but the Data section is absent.
1097 266090 : if (!CheckDataSegmentsCount(
1098 : static_cast<uint32_t>(module_->data_segments.size()))) {
1099 : return false;
1100 : }
1101 266088 : return true;
1102 : }
1103 :
1104 281455 : ModuleResult FinishDecoding(bool verify_functions = true) {
1105 281455 : if (ok() && CheckMismatchedCounts()) {
1106 266089 : CalculateGlobalOffsets(module_.get());
1107 : }
1108 844374 : ModuleResult result = toResult(std::move(module_));
1109 281459 : if (verify_functions && result.ok() && intermediate_error_.has_error()) {
1110 : // Copy error message and location.
1111 15234 : return ModuleResult{std::move(intermediate_error_)};
1112 : }
1113 : return result;
1114 : }
1115 :
1116 : // Decodes an entire module.
1117 284346 : ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator,
1118 : bool verify_functions = true) {
1119 284346 : StartDecoding(counters, allocator);
1120 : uint32_t offset = 0;
1121 284353 : Vector<const byte> orig_bytes(start(), end() - start());
1122 284353 : DecodeModuleHeader(VectorOf(start(), end() - start()), offset);
1123 284351 : if (failed()) {
1124 15238 : return FinishDecoding(verify_functions);
1125 : }
1126 : // Size of the module header.
1127 : offset += 8;
1128 276732 : Decoder decoder(start_ + offset, end_, offset);
1129 :
1130 : WasmSectionIterator section_iter(decoder);
1131 :
1132 4412049 : while (ok() && section_iter.more()) {
1133 : // Shift the offset by the section header length
1134 1288765 : offset += section_iter.payload_start() - section_iter.section_start();
1135 1288765 : if (section_iter.section_code() != SectionCode::kUnknownSectionCode) {
1136 2576206 : DecodeSection(section_iter.section_code(), section_iter.payload(),
1137 1288103 : offset, verify_functions);
1138 : }
1139 : // Shift the offset by the remaining section payload
1140 1288762 : offset += section_iter.payload_length();
1141 1288762 : section_iter.advance(true);
1142 : }
1143 :
1144 : if (FLAG_dump_wasm_module) DumpModule(orig_bytes);
1145 :
1146 276730 : if (decoder.failed()) {
1147 6166 : return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr);
1148 : }
1149 :
1150 547290 : return FinishDecoding(verify_functions);
1151 : }
1152 :
1153 : // Decodes a single anonymous function starting at {start_}.
1154 1 : FunctionResult DecodeSingleFunction(Zone* zone,
1155 : const ModuleWireBytes& wire_bytes,
1156 : const WasmModule* module,
1157 : std::unique_ptr<WasmFunction> function) {
1158 1 : pc_ = start_;
1159 1 : function->sig = consume_sig(zone);
1160 2 : function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
1161 :
1162 1 : if (ok())
1163 : VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
1164 1 : function.get());
1165 :
1166 1 : if (intermediate_error_.has_error()) {
1167 0 : return FunctionResult{std::move(intermediate_error_)};
1168 : }
1169 :
1170 1 : return FunctionResult(std::move(function));
1171 : }
1172 :
1173 : // Decodes a single function signature at {start}.
1174 : FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) {
1175 262 : pc_ = start;
1176 262 : FunctionSig* result = consume_sig(zone);
1177 262 : return ok() ? result : nullptr;
1178 : }
1179 :
1180 : WasmInitExpr DecodeInitExpr(const byte* start) {
1181 22 : pc_ = start;
1182 22 : return consume_init_expr(nullptr, kWasmStmt);
1183 : }
1184 :
1185 668 : const std::shared_ptr<WasmModule>& shared_module() const { return module_; }
1186 :
1187 : Counters* GetCounters() const {
1188 : DCHECK_NOT_NULL(counters_);
1189 : return counters_;
1190 : }
1191 :
1192 : void SetCounters(Counters* counters) {
1193 : DCHECK_NULL(counters_);
1194 284696 : counters_ = counters;
1195 : }
1196 :
1197 : private:
1198 : const WasmFeatures enabled_features_;
1199 : std::shared_ptr<WasmModule> module_;
1200 : Counters* counters_ = nullptr;
1201 : // The type section is the first section in a module.
1202 : uint8_t next_ordered_section_ = kFirstSectionInModule;
1203 : // We store next_ordered_section_ as uint8_t instead of SectionCode so that
1204 : // we can increment it. This static_assert should make sure that SectionCode
1205 : // does not get bigger than uint8_t accidentially.
1206 : static_assert(sizeof(ModuleDecoderImpl::next_ordered_section_) ==
1207 : sizeof(SectionCode),
1208 : "type mismatch");
1209 : uint32_t seen_unordered_sections_ = 0;
1210 : static_assert(kBitsPerByte *
1211 : sizeof(ModuleDecoderImpl::seen_unordered_sections_) >
1212 : kLastKnownModuleSection,
1213 : "not enough bits");
1214 : WasmError intermediate_error_;
1215 : ModuleOrigin origin_;
1216 :
1217 : bool has_seen_unordered_section(SectionCode section_code) {
1218 290720 : return seen_unordered_sections_ & (1 << section_code);
1219 : }
1220 :
1221 : void set_seen_unordered_section(SectionCode section_code) {
1222 23161 : seen_unordered_sections_ |= 1 << section_code;
1223 : }
1224 :
1225 : uint32_t off(const byte* ptr) {
1226 1 : return static_cast<uint32_t>(ptr - start_) + buffer_offset_;
1227 : }
1228 :
1229 : bool AddTable(WasmModule* module) {
1230 4277 : if (enabled_features_.anyref) return true;
1231 4105 : if (module->tables.size() > 0) {
1232 32 : error("At most one table is supported");
1233 : return false;
1234 : } else {
1235 : return true;
1236 : }
1237 : }
1238 :
1239 : bool AddMemory(WasmModule* module) {
1240 15896 : if (module->has_memory) {
1241 64 : error("At most one memory is supported");
1242 : return false;
1243 : } else {
1244 15832 : module->has_memory = true;
1245 : return true;
1246 : }
1247 : }
1248 :
1249 : // Decodes a single global entry inside a module starting at {pc_}.
1250 441184 : void DecodeGlobalInModule(WasmModule* module, uint32_t index,
1251 : WasmGlobal* global) {
1252 441184 : global->type = consume_value_type();
1253 441184 : global->mutability = consume_mutability();
1254 : const byte* pos = pc();
1255 441184 : global->init = consume_init_expr(module, kWasmStmt);
1256 441184 : if (global->init.kind == WasmInitExpr::kGlobalIndex) {
1257 65 : uint32_t other_index = global->init.val.global_index;
1258 65 : if (other_index >= index) {
1259 0 : errorf(pos,
1260 : "invalid global index in init expression, "
1261 : "index %u, other_index %u",
1262 0 : index, other_index);
1263 130 : } else if (module->globals[other_index].type != global->type) {
1264 0 : errorf(pos,
1265 : "type mismatch in global initialization "
1266 : "(from global #%u), expected %s, got %s",
1267 : other_index, ValueTypes::TypeName(global->type),
1268 0 : ValueTypes::TypeName(module->globals[other_index].type));
1269 : }
1270 : } else {
1271 441119 : if (!ValueTypes::IsSubType(global->type, TypeOf(module, global->init))) {
1272 384 : errorf(pos, "type error in global initialization, expected %s, got %s",
1273 : ValueTypes::TypeName(global->type),
1274 384 : ValueTypes::TypeName(TypeOf(module, global->init)));
1275 : }
1276 : }
1277 441184 : }
1278 :
1279 : // Calculate individual global offsets and total size of globals table.
1280 268515 : void CalculateGlobalOffsets(WasmModule* module) {
1281 : uint32_t untagged_offset = 0;
1282 : uint32_t tagged_offset = 0;
1283 : uint32_t num_imported_mutable_globals = 0;
1284 1152700 : for (WasmGlobal& global : module->globals) {
1285 884185 : if (global.mutability && global.imported) {
1286 361 : global.index = num_imported_mutable_globals++;
1287 1767648 : } else if (ValueTypes::IsReferenceType(global.type)) {
1288 534 : global.offset = tagged_offset;
1289 : // All entries in the tagged_globals_buffer have size 1.
1290 534 : tagged_offset++;
1291 : } else {
1292 : byte size =
1293 883290 : ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
1294 883290 : untagged_offset = (untagged_offset + size - 1) & ~(size - 1); // align
1295 883290 : global.offset = untagged_offset;
1296 883290 : untagged_offset += size;
1297 : }
1298 : }
1299 268515 : module->untagged_globals_buffer_size = untagged_offset;
1300 268515 : module->tagged_globals_buffer_size = tagged_offset;
1301 268515 : }
1302 :
1303 : // Verifies the body (code) of a given function.
1304 136691 : void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
1305 : const ModuleWireBytes& wire_bytes,
1306 : const WasmModule* module, WasmFunction* function) {
1307 : WasmFunctionName func_name(function,
1308 136691 : wire_bytes.GetNameOrNull(function, module));
1309 : if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
1310 : StdoutStream os;
1311 : os << "Verifying wasm function " << func_name << std::endl;
1312 : }
1313 : FunctionBody body = {
1314 : function->sig, function->code.offset(),
1315 136691 : start_ + GetBufferRelativeOffset(function->code.offset()),
1316 410073 : start_ + GetBufferRelativeOffset(function->code.end_offset())};
1317 :
1318 : DecodeResult result;
1319 : {
1320 136691 : auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_,
1321 : wasm_decode, function_time);
1322 :
1323 : TimedHistogramScope wasm_decode_function_time_scope(time_counter);
1324 136691 : WasmFeatures unused_detected_features;
1325 273382 : result = VerifyWasmCode(allocator, enabled_features_, module,
1326 : &unused_detected_features, body);
1327 : }
1328 :
1329 : // If the decode failed and this is the first error, set error code and
1330 : // location.
1331 136691 : if (result.failed() && intermediate_error_.empty()) {
1332 : // Wrap the error message from the function decoder.
1333 15298 : std::ostringstream error_msg;
1334 7649 : error_msg << "in function " << func_name << ": "
1335 : << result.error().message();
1336 15298 : intermediate_error_ = WasmError{result.error().offset(), error_msg.str()};
1337 : }
1338 136691 : }
1339 :
1340 615931 : uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
1341 615931 : const byte* pos = pc_;
1342 615931 : uint32_t sig_index = consume_u32v("signature index");
1343 1231866 : if (sig_index >= module->signatures.size()) {
1344 5740 : errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
1345 5740 : static_cast<int>(module->signatures.size()));
1346 5740 : *sig = nullptr;
1347 5740 : return 0;
1348 : }
1349 610193 : *sig = module->signatures[sig_index];
1350 610193 : return sig_index;
1351 : }
1352 :
1353 544 : uint32_t consume_exception_sig_index(WasmModule* module, FunctionSig** sig) {
1354 544 : const byte* pos = pc_;
1355 544 : uint32_t sig_index = consume_sig_index(module, sig);
1356 544 : if (*sig && (*sig)->return_count() != 0) {
1357 2 : errorf(pos, "exception signature %u has non-void return", sig_index);
1358 2 : *sig = nullptr;
1359 2 : return 0;
1360 : }
1361 : return sig_index;
1362 : }
1363 :
1364 2141796 : uint32_t consume_count(const char* name, size_t maximum) {
1365 2141796 : const byte* p = pc_;
1366 2141796 : uint32_t count = consume_u32v(name);
1367 2141811 : if (count > maximum) {
1368 118 : errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
1369 118 : return static_cast<uint32_t>(maximum);
1370 : }
1371 : return count;
1372 : }
1373 :
1374 : uint32_t consume_func_index(WasmModule* module, WasmFunction** func,
1375 : const char* name) {
1376 358805 : return consume_index(name, module->functions, func);
1377 : }
1378 :
1379 : uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
1380 1114 : return consume_index("global index", module->globals, global);
1381 : }
1382 :
1383 : uint32_t consume_table_index(WasmModule* module, WasmTable** table) {
1384 768 : return consume_index("table index", module->tables, table);
1385 : }
1386 :
1387 : uint32_t consume_exception_index(WasmModule* module, WasmException** except) {
1388 145 : return consume_index("exception index", module->exceptions, except);
1389 : }
1390 :
1391 : template <typename T>
1392 360830 : uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
1393 360830 : const byte* pos = pc_;
1394 360830 : uint32_t index = consume_u32v(name);
1395 721670 : if (index >= vector.size()) {
1396 115 : errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
1397 : static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
1398 115 : *ptr = nullptr;
1399 115 : return 0;
1400 : }
1401 360720 : *ptr = &vector[index];
1402 360720 : return index;
1403 : }
1404 :
1405 4245 : uint8_t validate_table_flags(const char* name) {
1406 4245 : uint8_t flags = consume_u8("resizable limits flags");
1407 : const byte* pos = pc();
1408 4245 : if (flags & 0xFE) {
1409 8 : errorf(pos - 1, "invalid %s limits flags", name);
1410 : }
1411 4245 : return flags;
1412 : }
1413 :
1414 15833 : uint8_t validate_memory_flags(bool* has_shared_memory) {
1415 15833 : uint8_t flags = consume_u8("resizable limits flags");
1416 : const byte* pos = pc();
1417 15831 : *has_shared_memory = false;
1418 15831 : if (enabled_features_.threads) {
1419 1547 : if (flags & 0xFC) {
1420 0 : errorf(pos - 1, "invalid memory limits flags");
1421 1547 : } else if (flags == 3) {
1422 : DCHECK_NOT_NULL(has_shared_memory);
1423 1471 : *has_shared_memory = true;
1424 76 : } else if (flags == 2) {
1425 8 : errorf(pos - 1,
1426 : "memory limits flags should have maximum defined if shared is "
1427 8 : "true");
1428 : }
1429 : } else {
1430 14284 : if (flags & 0xFE) {
1431 16 : errorf(pos - 1, "invalid memory limits flags");
1432 : }
1433 : }
1434 15831 : return flags;
1435 : }
1436 :
1437 20080 : void consume_resizable_limits(const char* name, const char* units,
1438 : uint32_t max_initial, uint32_t* initial,
1439 : bool* has_max, uint32_t max_maximum,
1440 : uint32_t* maximum, uint8_t flags) {
1441 : const byte* pos = pc();
1442 40162 : *initial = consume_u32v("initial size");
1443 20082 : *has_max = false;
1444 20082 : if (*initial > max_initial) {
1445 : errorf(pos,
1446 : "initial %s size (%u %s) is larger than implementation limit (%u)",
1447 56 : name, *initial, units, max_initial);
1448 : }
1449 20083 : if (flags & 1) {
1450 6102 : *has_max = true;
1451 : pos = pc();
1452 6108 : *maximum = consume_u32v("maximum size");
1453 6108 : if (*maximum > max_maximum) {
1454 : errorf(
1455 : pos,
1456 : "maximum %s size (%u %s) is larger than implementation limit (%u)",
1457 57 : name, *maximum, units, max_maximum);
1458 : }
1459 6107 : if (*maximum < *initial) {
1460 : errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
1461 16 : name, *maximum, units, *initial, units);
1462 : }
1463 : } else {
1464 13981 : *has_max = false;
1465 13981 : *maximum = max_initial;
1466 : }
1467 20088 : }
1468 :
1469 1012855 : bool expect_u8(const char* name, uint8_t expected) {
1470 : const byte* pos = pc();
1471 1012855 : uint8_t value = consume_u8(name);
1472 1012856 : if (value != expected) {
1473 680 : errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
1474 680 : return false;
1475 : }
1476 : return true;
1477 : }
1478 :
1479 445834 : WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
1480 : const byte* pos = pc();
1481 445834 : uint8_t opcode = consume_u8("opcode");
1482 : WasmInitExpr expr;
1483 : uint32_t len = 0;
1484 445834 : switch (opcode) {
1485 : case kExprGetGlobal: {
1486 : GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1);
1487 396 : if (module->globals.size() <= imm.index) {
1488 16 : error("global index is out of bounds");
1489 16 : expr.kind = WasmInitExpr::kNone;
1490 16 : expr.val.i32_const = 0;
1491 16 : break;
1492 : }
1493 : WasmGlobal* global = &module->globals[imm.index];
1494 380 : if (global->mutability || !global->imported) {
1495 : error(
1496 : "only immutable imported globals can be used in initializer "
1497 18 : "expressions");
1498 18 : expr.kind = WasmInitExpr::kNone;
1499 18 : expr.val.i32_const = 0;
1500 18 : break;
1501 : }
1502 362 : expr.kind = WasmInitExpr::kGlobalIndex;
1503 362 : expr.val.global_index = imm.index;
1504 362 : len = imm.length;
1505 362 : break;
1506 : }
1507 : case kExprI32Const: {
1508 : ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1);
1509 8093 : expr.kind = WasmInitExpr::kI32Const;
1510 8093 : expr.val.i32_const = imm.value;
1511 8093 : len = imm.length;
1512 : break;
1513 : }
1514 : case kExprF32Const: {
1515 436042 : ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1);
1516 436042 : expr.kind = WasmInitExpr::kF32Const;
1517 436042 : expr.val.f32_const = imm.value;
1518 436042 : len = imm.length;
1519 : break;
1520 : }
1521 : case kExprI64Const: {
1522 : ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1);
1523 316 : expr.kind = WasmInitExpr::kI64Const;
1524 316 : expr.val.i64_const = imm.value;
1525 316 : len = imm.length;
1526 : break;
1527 : }
1528 : case kExprF64Const: {
1529 575 : ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1);
1530 575 : expr.kind = WasmInitExpr::kF64Const;
1531 575 : expr.val.f64_const = imm.value;
1532 575 : len = imm.length;
1533 : break;
1534 : }
1535 : case kExprRefNull: {
1536 234 : if (enabled_features_.anyref || enabled_features_.eh) {
1537 234 : expr.kind = WasmInitExpr::kRefNullConst;
1538 : len = 0;
1539 234 : break;
1540 : }
1541 : V8_FALLTHROUGH;
1542 : }
1543 : default: {
1544 178 : error("invalid opcode in initialization expression");
1545 178 : expr.kind = WasmInitExpr::kNone;
1546 178 : expr.val.i32_const = 0;
1547 : }
1548 : }
1549 445834 : consume_bytes(len, "init code");
1550 445834 : if (!expect_u8("end opcode", kExprEnd)) {
1551 552 : expr.kind = WasmInitExpr::kNone;
1552 : }
1553 445834 : if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
1554 213 : errorf(pos, "type error in init expression, expected %s, got %s",
1555 : ValueTypes::TypeName(expected),
1556 426 : ValueTypes::TypeName(TypeOf(module, expr)));
1557 : }
1558 445834 : return expr;
1559 : }
1560 :
1561 : // Read a mutability flag
1562 443380 : bool consume_mutability() {
1563 443380 : byte val = consume_u8("mutability");
1564 443380 : if (val > 1) error(pc_ - 1, "invalid mutability");
1565 443380 : return val != 0;
1566 : }
1567 :
1568 : // Reads a single 8-bit integer, interpreting it as a local type.
1569 1331210 : ValueType consume_value_type() {
1570 1331210 : byte val = consume_u8("value type");
1571 : ValueTypeCode t = static_cast<ValueTypeCode>(val);
1572 1331210 : switch (t) {
1573 : case kLocalI32:
1574 : return kWasmI32;
1575 : case kLocalI64:
1576 34564 : return kWasmI64;
1577 : case kLocalF32:
1578 707004 : return kWasmF32;
1579 : case kLocalF64:
1580 277993 : return kWasmF64;
1581 : default:
1582 3279 : if (origin_ == kWasmOrigin) {
1583 3279 : switch (t) {
1584 : case kLocalS128:
1585 32 : if (enabled_features_.simd) return kWasmS128;
1586 : break;
1587 : case kLocalAnyFunc:
1588 469 : if (enabled_features_.anyref) return kWasmAnyFunc;
1589 : break;
1590 : case kLocalAnyRef:
1591 2688 : if (enabled_features_.anyref) return kWasmAnyRef;
1592 : break;
1593 : case kLocalExceptRef:
1594 64 : if (enabled_features_.eh) return kWasmExceptRef;
1595 : break;
1596 : default:
1597 : break;
1598 : }
1599 : }
1600 48 : error(pc_ - 1, "invalid local type");
1601 48 : return kWasmStmt;
1602 : }
1603 : }
1604 :
1605 : // Reads a single 8-bit integer, interpreting it as a reference type.
1606 4291 : ValueType consume_reference_type() {
1607 4291 : byte val = consume_u8("reference type");
1608 : ValueTypeCode t = static_cast<ValueTypeCode>(val);
1609 4291 : switch (t) {
1610 : case kLocalAnyFunc:
1611 : return kWasmAnyFunc;
1612 : case kLocalAnyRef:
1613 20 : if (!enabled_features_.anyref) {
1614 1 : error(pc_ - 1,
1615 1 : "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'");
1616 : }
1617 : return kWasmAnyRef;
1618 : default:
1619 : break;
1620 : }
1621 2 : error(pc_ - 1, "invalid reference type");
1622 2 : return kWasmStmt;
1623 : }
1624 :
1625 566856 : FunctionSig* consume_sig(Zone* zone) {
1626 566856 : if (!expect_u8("type form", kWasmFunctionTypeCode)) return nullptr;
1627 : // parse parameter types
1628 : uint32_t param_count =
1629 566729 : consume_count("param count", kV8MaxWasmFunctionParams);
1630 566727 : if (failed()) return nullptr;
1631 : std::vector<ValueType> params;
1632 1703294 : for (uint32_t i = 0; ok() && i < param_count; ++i) {
1633 568283 : ValueType param = consume_value_type();
1634 568278 : params.push_back(param);
1635 : }
1636 : std::vector<ValueType> returns;
1637 : // parse return types
1638 566729 : const size_t max_return_count = enabled_features_.mv
1639 : ? kV8MaxWasmFunctionMultiReturns
1640 566729 : : kV8MaxWasmFunctionReturns;
1641 566729 : uint32_t return_count = consume_count("return count", max_return_count);
1642 566729 : if (failed()) return nullptr;
1643 1205744 : for (uint32_t i = 0; ok() && i < return_count; ++i) {
1644 319551 : ValueType ret = consume_value_type();
1645 319551 : returns.push_back(ret);
1646 : }
1647 :
1648 566642 : if (failed()) return nullptr;
1649 :
1650 : // FunctionSig stores the return types first.
1651 566629 : ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count);
1652 : uint32_t b = 0;
1653 1205704 : for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
1654 1703106 : for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
1655 :
1656 1133246 : return new (zone) FunctionSig(return_count, param_count, buffer);
1657 : }
1658 :
1659 : // Consume the attribute field of an exception.
1660 544 : uint32_t consume_exception_attribute() {
1661 544 : const byte* pos = pc_;
1662 544 : uint32_t attribute = consume_u32v("exception attribute");
1663 544 : if (attribute != kExceptionAttribute) {
1664 1 : errorf(pos, "exception attribute %u not supported", attribute);
1665 1 : return 0;
1666 : }
1667 : return attribute;
1668 : }
1669 :
1670 4715 : void consume_segment_header(const char* name, bool* is_active,
1671 : uint32_t* index, WasmInitExpr* offset) {
1672 : const byte* pos = pc();
1673 : // In the MVP, this is a table or memory index field that must be 0, but
1674 : // we've repurposed it as a flags field in the bulk memory proposal.
1675 : uint32_t flags;
1676 4715 : if (enabled_features_.bulk_memory) {
1677 128 : flags = consume_u32v("flags");
1678 128 : if (failed()) return;
1679 : } else {
1680 : // Without the bulk memory proposal, we should still read the table
1681 : // index. This is the same as reading the `ActiveWithIndex` flag with
1682 : // the bulk memory proposal.
1683 : flags = SegmentFlags::kActiveWithIndex;
1684 : }
1685 :
1686 : bool read_index;
1687 : bool read_offset;
1688 4715 : if (flags == SegmentFlags::kActiveNoIndex) {
1689 32 : *is_active = true;
1690 : read_index = false;
1691 : read_offset = true;
1692 4683 : } else if (flags == SegmentFlags::kPassive) {
1693 87 : *is_active = false;
1694 : read_index = false;
1695 : read_offset = false;
1696 4596 : } else if (flags == SegmentFlags::kActiveWithIndex) {
1697 4596 : *is_active = true;
1698 : read_index = true;
1699 : read_offset = true;
1700 : } else {
1701 0 : errorf(pos, "illegal flag value %u. Must be 0, 1, or 2", flags);
1702 0 : return;
1703 : }
1704 :
1705 4715 : if (read_index) {
1706 9192 : *index = consume_u32v(name);
1707 : } else {
1708 119 : *index = 0;
1709 : }
1710 :
1711 4715 : if (read_offset) {
1712 4628 : *offset = consume_init_expr(module_.get(), kWasmI32);
1713 : }
1714 : }
1715 :
1716 : uint32_t consume_element_func_index() {
1717 8637 : WasmFunction* func = nullptr;
1718 : uint32_t index =
1719 : consume_func_index(module_.get(), &func, "element function index");
1720 : if (failed()) return index;
1721 : DCHECK_NE(func, nullptr);
1722 : DCHECK_EQ(index, func->func_index);
1723 : DCHECK_NE(index, WasmElemSegment::kNullIndex);
1724 : return index;
1725 : }
1726 :
1727 167 : uint32_t consume_passive_element() {
1728 : uint32_t index = WasmElemSegment::kNullIndex;
1729 167 : uint8_t opcode = consume_u8("element opcode");
1730 167 : if (failed()) return index;
1731 167 : switch (opcode) {
1732 : case kExprRefNull:
1733 : index = WasmElemSegment::kNullIndex;
1734 : break;
1735 : case kExprRefFunc:
1736 : index = consume_element_func_index();
1737 154 : if (failed()) return index;
1738 : break;
1739 : default:
1740 0 : error("invalid opcode in element");
1741 0 : break;
1742 : }
1743 167 : expect_u8("end opcode", kExprEnd);
1744 167 : return index;
1745 : }
1746 : };
1747 :
1748 284339 : ModuleResult DecodeWasmModule(const WasmFeatures& enabled,
1749 : const byte* module_start, const byte* module_end,
1750 : bool verify_functions, ModuleOrigin origin,
1751 : Counters* counters,
1752 : AccountingAllocator* allocator) {
1753 : auto counter =
1754 284339 : SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time);
1755 : TimedHistogramScope wasm_decode_module_time_scope(counter);
1756 284351 : size_t size = module_end - module_start;
1757 284351 : CHECK_LE(module_start, module_end);
1758 284351 : if (size >= kV8MaxWasmModuleSize) {
1759 : return ModuleResult{WasmError{0, "size > maximum module size (%zu): %zu",
1760 0 : kV8MaxWasmModuleSize, size}};
1761 : }
1762 : // TODO(bradnelson): Improve histogram handling of size_t.
1763 : auto size_counter =
1764 284351 : SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes);
1765 284351 : size_counter->AddSample(static_cast<int>(size));
1766 : // Signatures are stored in zone memory, which have the same lifetime
1767 : // as the {module}.
1768 568703 : ModuleDecoderImpl decoder(enabled, module_start, module_end, origin);
1769 : ModuleResult result =
1770 853039 : decoder.DecodeModule(counters, allocator, verify_functions);
1771 : // TODO(bradnelson): Improve histogram handling of size_t.
1772 : // TODO(titzer): this isn't accurate, since it doesn't count the data
1773 : // allocated on the C++ heap.
1774 : // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
1775 284346 : if (result.ok()) {
1776 258331 : auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode,
1777 : module_peak_memory_bytes);
1778 258331 : peak_counter->AddSample(
1779 258331 : static_cast<int>(result.value()->signature_zone->allocation_size()));
1780 : }
1781 : return result;
1782 : }
1783 :
1784 380 : ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled)
1785 760 : : enabled_features_(enabled) {}
1786 :
1787 : ModuleDecoder::~ModuleDecoder() = default;
1788 :
1789 668 : const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const {
1790 668 : return impl_->shared_module();
1791 : }
1792 :
1793 352 : void ModuleDecoder::StartDecoding(Counters* counters,
1794 : AccountingAllocator* allocator,
1795 : ModuleOrigin origin) {
1796 : DCHECK_NULL(impl_);
1797 352 : impl_.reset(new ModuleDecoderImpl(enabled_features_, origin));
1798 352 : impl_->StartDecoding(counters, allocator);
1799 352 : }
1800 :
1801 352 : void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes,
1802 : uint32_t offset) {
1803 704 : impl_->DecodeModuleHeader(bytes, offset);
1804 352 : }
1805 :
1806 804 : void ModuleDecoder::DecodeSection(SectionCode section_code,
1807 : Vector<const uint8_t> bytes, uint32_t offset,
1808 : bool verify_functions) {
1809 1608 : impl_->DecodeSection(section_code, bytes, offset, verify_functions);
1810 804 : }
1811 :
1812 452 : void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length,
1813 : uint32_t offset, bool verify_functions) {
1814 904 : impl_->DecodeFunctionBody(index, length, offset, verify_functions);
1815 452 : }
1816 :
1817 228 : bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count,
1818 : uint32_t offset) {
1819 228 : return impl_->CheckFunctionsCount(functions_count, offset);
1820 : }
1821 :
1822 200 : ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) {
1823 600 : return impl_->FinishDecoding(verify_functions);
1824 : }
1825 :
1826 35029 : SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder,
1827 : const byte* end) {
1828 35029 : WireBytesRef string = consume_string(decoder, true, "section name");
1829 35039 : if (decoder.failed() || decoder.pc() > end) {
1830 : return kUnknownSectionCode;
1831 : }
1832 : const byte* section_name_start =
1833 26797 : decoder.start() + decoder.GetBufferRelativeOffset(string.offset());
1834 :
1835 : TRACE(" +%d section name : \"%.*s\"\n",
1836 : static_cast<int>(section_name_start - decoder.start()),
1837 : string.length() < 20 ? string.length() : 20, section_name_start);
1838 :
1839 52396 : if (string.length() == num_chars(kNameString) &&
1840 25599 : strncmp(reinterpret_cast<const char*>(section_name_start), kNameString,
1841 : num_chars(kNameString)) == 0) {
1842 : return kNameSectionCode;
1843 1451 : } else if (string.length() == num_chars(kSourceMappingURLString) &&
1844 201 : strncmp(reinterpret_cast<const char*>(section_name_start),
1845 : kSourceMappingURLString,
1846 : num_chars(kSourceMappingURLString)) == 0) {
1847 : return kSourceMappingURLSectionCode;
1848 1419 : } else if (string.length() == num_chars(kCompilationHintsString) &&
1849 185 : strncmp(reinterpret_cast<const char*>(section_name_start),
1850 : kCompilationHintsString,
1851 : num_chars(kCompilationHintsString)) == 0) {
1852 : return kCompilationHintsSectionCode;
1853 : }
1854 1177 : return kUnknownSectionCode;
1855 : }
1856 :
1857 2312 : bool ModuleDecoder::ok() { return impl_->ok(); }
1858 :
1859 262 : FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled,
1860 : Zone* zone, const byte* start,
1861 : const byte* end) {
1862 524 : ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1863 262 : return decoder.DecodeFunctionSignature(zone, start);
1864 : }
1865 :
1866 22 : WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled,
1867 : const byte* start, const byte* end) {
1868 44 : AccountingAllocator allocator;
1869 44 : ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin);
1870 22 : return decoder.DecodeInitExpr(start);
1871 : }
1872 :
1873 1 : FunctionResult DecodeWasmFunctionForTesting(
1874 : const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes,
1875 : const WasmModule* module, const byte* function_start,
1876 : const byte* function_end, Counters* counters) {
1877 1 : size_t size = function_end - function_start;
1878 1 : CHECK_LE(function_start, function_end);
1879 1 : auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm,
1880 : function_size_bytes);
1881 : // TODO(bradnelson): Improve histogram handling of ptrdiff_t.
1882 1 : size_histogram->AddSample(static_cast<int>(size));
1883 1 : if (size > kV8MaxWasmFunctionSize) {
1884 : return FunctionResult{WasmError{0,
1885 : "size > maximum function size (%zu): %zu",
1886 0 : kV8MaxWasmFunctionSize, size}};
1887 : }
1888 2 : ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin);
1889 : decoder.SetCounters(counters);
1890 2 : return decoder.DecodeSingleFunction(zone, wire_bytes, module,
1891 2 : base::make_unique<WasmFunction>());
1892 : }
1893 :
1894 140 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
1895 : const byte* tables_end) {
1896 140 : AsmJsOffsets table;
1897 :
1898 : Decoder decoder(tables_start, tables_end);
1899 : uint32_t functions_count = decoder.consume_u32v("functions count");
1900 : // Reserve space for the entries, taking care of invalid input.
1901 140 : if (functions_count < static_cast<uint32_t>(tables_end - tables_start)) {
1902 140 : table.reserve(functions_count);
1903 : }
1904 :
1905 804 : for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
1906 : uint32_t size = decoder.consume_u32v("table size");
1907 332 : if (size == 0) {
1908 140 : table.emplace_back();
1909 140 : continue;
1910 : }
1911 192 : if (!decoder.checkAvailable(size)) {
1912 0 : decoder.error("illegal asm function offset table size");
1913 : }
1914 192 : const byte* table_end = decoder.pc() + size;
1915 : uint32_t locals_size = decoder.consume_u32v("locals size");
1916 192 : int function_start_position = decoder.consume_u32v("function start pos");
1917 192 : int last_byte_offset = locals_size;
1918 : int last_asm_position = function_start_position;
1919 : std::vector<AsmJsOffsetEntry> func_asm_offsets;
1920 192 : func_asm_offsets.reserve(size / 4); // conservative estimation
1921 : // Add an entry for the stack check, associated with position 0.
1922 384 : func_asm_offsets.push_back(
1923 : {0, function_start_position, function_start_position});
1924 704 : while (decoder.ok() && decoder.pc() < table_end) {
1925 256 : last_byte_offset += decoder.consume_u32v("byte offset delta");
1926 : int call_position =
1927 256 : last_asm_position + decoder.consume_i32v("call position delta");
1928 : int to_number_position =
1929 256 : call_position + decoder.consume_i32v("to_number position delta");
1930 : last_asm_position = to_number_position;
1931 512 : func_asm_offsets.push_back(
1932 : {last_byte_offset, call_position, to_number_position});
1933 : }
1934 192 : if (decoder.pc() != table_end) {
1935 0 : decoder.error("broken asm offset table");
1936 : }
1937 : table.push_back(std::move(func_asm_offsets));
1938 : }
1939 140 : if (decoder.more()) decoder.error("unexpected additional bytes");
1940 :
1941 420 : return decoder.toResult(std::move(table));
1942 : }
1943 :
1944 250 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
1945 : const byte* end) {
1946 : Decoder decoder(start, end);
1947 250 : decoder.consume_bytes(4, "wasm magic");
1948 250 : decoder.consume_bytes(4, "wasm version");
1949 :
1950 : std::vector<CustomSectionOffset> result;
1951 :
1952 577 : while (decoder.more()) {
1953 : byte section_code = decoder.consume_u8("section code");
1954 : uint32_t section_length = decoder.consume_u32v("section length");
1955 : uint32_t section_start = decoder.pc_offset();
1956 335 : if (section_code != 0) {
1957 : // Skip known sections.
1958 2 : decoder.consume_bytes(section_length, "section bytes");
1959 2 : continue;
1960 : }
1961 : uint32_t name_length = decoder.consume_u32v("name length");
1962 : uint32_t name_offset = decoder.pc_offset();
1963 333 : decoder.consume_bytes(name_length, "section name");
1964 : uint32_t payload_offset = decoder.pc_offset();
1965 333 : if (section_length < (payload_offset - section_start)) {
1966 8 : decoder.error("invalid section length");
1967 8 : break;
1968 : }
1969 325 : uint32_t payload_length = section_length - (payload_offset - section_start);
1970 325 : decoder.consume_bytes(payload_length);
1971 325 : if (decoder.failed()) break;
1972 325 : result.push_back({{section_start, section_length},
1973 : {name_offset, name_length},
1974 : {payload_offset, payload_length}});
1975 : }
1976 :
1977 250 : return result;
1978 : }
1979 :
1980 : namespace {
1981 :
1982 127310 : bool FindNameSection(Decoder& decoder) {
1983 : static constexpr int kModuleHeaderSize = 8;
1984 127310 : decoder.consume_bytes(kModuleHeaderSize, "module header");
1985 :
1986 : WasmSectionIterator section_iter(decoder);
1987 :
1988 266962 : while (decoder.ok() && section_iter.more() &&
1989 : section_iter.section_code() != kNameSectionCode) {
1990 42947 : section_iter.advance(true);
1991 : }
1992 127310 : if (!section_iter.more()) return false;
1993 :
1994 : // Reset the decoder to not read beyond the name section end.
1995 : decoder.Reset(section_iter.payload(), decoder.pc_offset());
1996 2886 : return true;
1997 : }
1998 :
1999 : } // namespace
2000 :
2001 127290 : void DecodeFunctionNames(const byte* module_start, const byte* module_end,
2002 : std::unordered_map<uint32_t, WireBytesRef>* names) {
2003 : DCHECK_NOT_NULL(names);
2004 : DCHECK(names->empty());
2005 :
2006 : Decoder decoder(module_start, module_end);
2007 127290 : if (!FindNameSection(decoder)) return;
2008 :
2009 5748 : while (decoder.ok() && decoder.more()) {
2010 : uint8_t name_type = decoder.consume_u8("name type");
2011 2882 : if (name_type & 0x80) break; // no varuint7
2012 :
2013 : uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2014 2882 : if (!decoder.checkAvailable(name_payload_len)) break;
2015 :
2016 2882 : if (name_type != NameSectionKindCode::kFunction) {
2017 28 : decoder.consume_bytes(name_payload_len, "name subsection payload");
2018 28 : continue;
2019 : }
2020 : uint32_t functions_count = decoder.consume_u32v("functions count");
2021 :
2022 32856 : for (; decoder.ok() && functions_count > 0; --functions_count) {
2023 : uint32_t function_index = decoder.consume_u32v("function index");
2024 15001 : WireBytesRef name = consume_string(decoder, false, "function name");
2025 :
2026 : // Be lenient with errors in the name section: Ignore non-UTF8 names. You
2027 : // can even assign to the same function multiple times (last valid one
2028 : // wins).
2029 30002 : if (decoder.ok() && validate_utf8(&decoder, name)) {
2030 29986 : names->insert(std::make_pair(function_index, name));
2031 : }
2032 : }
2033 : }
2034 : }
2035 :
2036 20 : void DecodeLocalNames(const byte* module_start, const byte* module_end,
2037 : LocalNames* result) {
2038 : DCHECK_NOT_NULL(result);
2039 : DCHECK(result->names.empty());
2040 :
2041 : Decoder decoder(module_start, module_end);
2042 20 : if (!FindNameSection(decoder)) return;
2043 :
2044 44 : while (decoder.ok() && decoder.more()) {
2045 : uint8_t name_type = decoder.consume_u8("name type");
2046 24 : if (name_type & 0x80) break; // no varuint7
2047 :
2048 : uint32_t name_payload_len = decoder.consume_u32v("name payload length");
2049 24 : if (!decoder.checkAvailable(name_payload_len)) break;
2050 :
2051 24 : if (name_type != NameSectionKindCode::kLocal) {
2052 20 : decoder.consume_bytes(name_payload_len, "name subsection payload");
2053 20 : continue;
2054 : }
2055 :
2056 : uint32_t local_names_count = decoder.consume_u32v("local names count");
2057 12 : for (uint32_t i = 0; i < local_names_count; ++i) {
2058 : uint32_t func_index = decoder.consume_u32v("function index");
2059 4 : if (func_index > kMaxInt) continue;
2060 4 : result->names.emplace_back(static_cast<int>(func_index));
2061 : LocalNamesPerFunction& func_names = result->names.back();
2062 : result->max_function_index =
2063 8 : std::max(result->max_function_index, func_names.function_index);
2064 : uint32_t num_names = decoder.consume_u32v("namings count");
2065 28 : for (uint32_t k = 0; k < num_names; ++k) {
2066 : uint32_t local_index = decoder.consume_u32v("local index");
2067 12 : WireBytesRef name = consume_string(decoder, true, "local name");
2068 12 : if (!decoder.ok()) break;
2069 12 : if (local_index > kMaxInt) continue;
2070 : func_names.max_local_index =
2071 24 : std::max(func_names.max_local_index, static_cast<int>(local_index));
2072 12 : func_names.names.emplace_back(static_cast<int>(local_index), name);
2073 : }
2074 : }
2075 : }
2076 : }
2077 :
2078 : #undef TRACE
2079 :
2080 : } // namespace wasm
2081 : } // namespace internal
2082 120216 : } // namespace v8
|