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