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/macro-assembler.h" 13 #include "src/objects-inl.h" 14 #include "src/ostreams.h" 15 #include "src/v8.h" 16 #include "src/wasm/decoder.h" 17 #include "src/wasm/function-body-decoder-impl.h" 18 #include "src/wasm/wasm-engine.h" 19 #include "src/wasm/wasm-limits.h" 20 21 namespace v8 { 22 namespace internal { 23 namespace wasm { 24 25 #define TRACE(...) \ 26 do { \ 27 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ 28 } while (false) 29 30 namespace { 31 32 constexpr char kNameString[] = "name"; 33 constexpr char kExceptionString[] = "exception"; 34 constexpr char kUnknownString[] = "<unknown>"; 35 36 template <size_t N> 37 constexpr size_t num_chars(const char (&)[N]) { 38 return N - 1; // remove null character at end. 39 } 40 41 const char* ExternalKindName(ImportExportKindCode kind) { 42 switch (kind) { 43 case kExternalFunction: 44 return "function"; 45 case kExternalTable: 46 return "table"; 47 case kExternalMemory: 48 return "memory"; 49 case kExternalGlobal: 50 return "global"; 51 } 52 return "unknown"; 53 } 54 55 } // namespace 56 57 const char* SectionName(SectionCode code) { 58 switch (code) { 59 case kUnknownSectionCode: 60 return "Unknown"; 61 case kTypeSectionCode: 62 return "Type"; 63 case kImportSectionCode: 64 return "Import"; 65 case kFunctionSectionCode: 66 return "Function"; 67 case kTableSectionCode: 68 return "Table"; 69 case kMemorySectionCode: 70 return "Memory"; 71 case kGlobalSectionCode: 72 return "Global"; 73 case kExportSectionCode: 74 return "Export"; 75 case kStartSectionCode: 76 return "Start"; 77 case kCodeSectionCode: 78 return "Code"; 79 case kElementSectionCode: 80 return "Element"; 81 case kDataSectionCode: 82 return "Data"; 83 case kNameSectionCode: 84 return kNameString; 85 case kExceptionSectionCode: 86 return kExceptionString; 87 default: 88 return kUnknownString; 89 } 90 } 91 92 namespace { 93 94 bool validate_utf8(Decoder* decoder, WireBytesRef string) { 95 return unibrow::Utf8::ValidateEncoding( 96 decoder->start() + decoder->GetBufferRelativeOffset(string.offset()), 97 string.length()); 98 } 99 100 ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { 101 switch (expr.kind) { 102 case WasmInitExpr::kNone: 103 return kWasmStmt; 104 case WasmInitExpr::kGlobalIndex: 105 return expr.val.global_index < module->globals.size() 106 ? module->globals[expr.val.global_index].type 107 : kWasmStmt; 108 case WasmInitExpr::kI32Const: 109 return kWasmI32; 110 case WasmInitExpr::kI64Const: 111 return kWasmI64; 112 case WasmInitExpr::kF32Const: 113 return kWasmF32; 114 case WasmInitExpr::kF64Const: 115 return kWasmF64; 116 case WasmInitExpr::kAnyRefConst: 117 return kWasmAnyRef; 118 default: 119 UNREACHABLE(); 120 } 121 } 122 123 // Reads a length-prefixed string, checking that it is within bounds. Returns 124 // the offset of the string, and the length as an out parameter. 125 WireBytesRef consume_string(Decoder& decoder, bool validate_utf8, 126 const char* name) { 127 uint32_t length = decoder.consume_u32v("string length"); 128 uint32_t offset = decoder.pc_offset(); 129 const byte* string_start = decoder.pc(); 130 // Consume bytes before validation to guarantee that the string is not oob. 131 if (length > 0) { 132 decoder.consume_bytes(length, name); 133 if (decoder.ok() && validate_utf8 && 134 !unibrow::Utf8::ValidateEncoding(string_start, length)) { 135 decoder.errorf(string_start, "%s: no valid UTF-8 string", name); 136 } 137 } 138 return {offset, decoder.failed() ? 0 : length}; 139 } 140 141 // An iterator over the sections in a wasm binary module. 142 // Automatically skips all unknown sections. 143 class WasmSectionIterator { 144 public: 145 explicit WasmSectionIterator(Decoder& decoder) 146 : decoder_(decoder), 147 section_code_(kUnknownSectionCode), 148 section_start_(decoder.pc()), 149 section_end_(decoder.pc()) { 150 next(); 151 } 152 153 inline bool more() const { return decoder_.ok() && decoder_.more(); } 154 155 inline SectionCode section_code() const { return section_code_; } 156 157 inline const byte* section_start() const { return section_start_; } 158 159 inline uint32_t section_length() const { 160 return static_cast<uint32_t>(section_end_ - section_start_); 161 } 162 163 inline Vector<const uint8_t> payload() const { 164 return {payload_start_, payload_length()}; 165 } 166 167 inline const byte* payload_start() const { return payload_start_; } 168 169 inline uint32_t payload_length() const { 170 return static_cast<uint32_t>(section_end_ - payload_start_); 171 } 172 173 inline const byte* section_end() const { return section_end_; } 174 175 // Advances to the next section, checking that decoding the current section 176 // stopped at {section_end_}. 177 void advance(bool move_to_section_end = false) { 178 if (move_to_section_end && decoder_.pc() < section_end_) { 179 decoder_.consume_bytes( 180 static_cast<uint32_t>(section_end_ - decoder_.pc())); 181 } 182 if (decoder_.pc() != section_end_) { 183 const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; 184 decoder_.errorf(decoder_.pc(), 185 "section was %s than expected size " 186 "(%u bytes expected, %zu decoded)", 187 msg, section_length(), 188 static_cast<size_t>(decoder_.pc() - section_start_)); 189 } 190 next(); 191 } 192 193 private: 194 Decoder& decoder_; 195 SectionCode section_code_; 196 const byte* section_start_; 197 const byte* payload_start_; 198 const byte* section_end_; 199 200 // Reads the section code/name at the current position and sets up 201 // the embedder fields. 202 void next() { 203 if (!decoder_.more()) { 204 section_code_ = kUnknownSectionCode; 205 return; 206 } 207 section_start_ = decoder_.pc(); 208 uint8_t section_code = decoder_.consume_u8("section code"); 209 // Read and check the section size. 210 uint32_t section_length = decoder_.consume_u32v("section length"); 211 212 payload_start_ = decoder_.pc(); 213 if (decoder_.checkAvailable(section_length)) { 214 // Get the limit of the section within the module. 215 section_end_ = payload_start_ + section_length; 216 } else { 217 // The section would extend beyond the end of the module. 218 section_end_ = payload_start_; 219 } 220 221 if (section_code == kUnknownSectionCode) { 222 // Check for the known "name" section. 223 section_code = 224 ModuleDecoder::IdentifyUnknownSection(decoder_, section_end_); 225 // As a side effect, the above function will forward the decoder to after 226 // the identifier string. 227 payload_start_ = decoder_.pc(); 228 } else if (!IsValidSectionCode(section_code)) { 229 decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x", 230 section_code); 231 section_code = kUnknownSectionCode; 232 } 233 section_code_ = decoder_.failed() ? kUnknownSectionCode 234 : static_cast<SectionCode>(section_code); 235 236 if (section_code_ == kUnknownSectionCode && section_end_ > decoder_.pc()) { 237 // skip to the end of the unknown section. 238 uint32_t remaining = static_cast<uint32_t>(section_end_ - decoder_.pc()); 239 decoder_.consume_bytes(remaining, "section payload"); 240 } 241 } 242 }; 243 244 } // namespace 245 246 // The main logic for decoding the bytes of a module. 247 class ModuleDecoderImpl : public Decoder { 248 public: 249 explicit ModuleDecoderImpl(const WasmFeatures& enabled, ModuleOrigin origin) 250 : Decoder(nullptr, nullptr), 251 enabled_features_(enabled), 252 origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {} 253 254 ModuleDecoderImpl(const WasmFeatures& enabled, const byte* module_start, 255 const byte* module_end, ModuleOrigin origin) 256 : Decoder(module_start, module_end), 257 enabled_features_(enabled), 258 origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) { 259 if (end_ < start_) { 260 error(start_, "end is less than start"); 261 end_ = start_; 262 } 263 } 264 265 virtual void onFirstError() { 266 pc_ = end_; // On error, terminate section decoding loop. 267 } 268 269 void DumpModule(const Vector<const byte> module_bytes) { 270 std::string path; 271 if (FLAG_dump_wasm_module_path) { 272 path = FLAG_dump_wasm_module_path; 273 if (path.size() && 274 !base::OS::isDirectorySeparator(path[path.size() - 1])) { 275 path += base::OS::DirectorySeparator(); 276 } 277 } 278 // File are named `HASH.{ok,failed}.wasm`. 279 size_t hash = base::hash_range(module_bytes.start(), module_bytes.end()); 280 EmbeddedVector<char, 32> buf; 281 SNPrintF(buf, "%016zx.%s.wasm", hash, ok() ? "ok" : "failed"); 282 std::string name(buf.start()); 283 if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) { 284 if (fwrite(module_bytes.start(), module_bytes.length(), 1, wasm_file) != 285 1) { 286 OFStream os(stderr); 287 os << "Error while dumping wasm file" << std::endl; 288 } 289 fclose(wasm_file); 290 } 291 } 292 293 void StartDecoding(Counters* counters, AccountingAllocator* allocator) { 294 CHECK_NULL(module_); 295 SetCounters(counters); 296 module_.reset( 297 new WasmModule(base::make_unique<Zone>(allocator, "signatures"))); 298 module_->initial_pages = 0; 299 module_->maximum_pages = 0; 300 module_->mem_export = false; 301 module_->origin = origin_; 302 } 303 304 void DecodeModuleHeader(Vector<const uint8_t> bytes, uint8_t offset) { 305 if (failed()) return; 306 Reset(bytes, offset); 307 308 const byte* pos = pc_; 309 uint32_t magic_word = consume_u32("wasm magic"); 310 #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF 311 if (magic_word != kWasmMagic) { 312 errorf(pos, 313 "expected magic word %02x %02x %02x %02x, " 314 "found %02x %02x %02x %02x", 315 BYTES(kWasmMagic), BYTES(magic_word)); 316 } 317 318 pos = pc_; 319 { 320 uint32_t magic_version = consume_u32("wasm version"); 321 if (magic_version != kWasmVersion) { 322 errorf(pos, 323 "expected version %02x %02x %02x %02x, " 324 "found %02x %02x %02x %02x", 325 BYTES(kWasmVersion), BYTES(magic_version)); 326 } 327 } 328 #undef BYTES 329 } 330 331 void DecodeSection(SectionCode section_code, Vector<const uint8_t> bytes, 332 uint32_t offset, bool verify_functions = true) { 333 if (failed()) return; 334 Reset(bytes, offset); 335 TRACE("Section: %s\n", SectionName(section_code)); 336 TRACE("Decode Section %p - %p\n", static_cast<const void*>(bytes.begin()), 337 static_cast<const void*>(bytes.end())); 338 339 // Check if the section is out-of-order. 340 if (section_code < next_section_) { 341 errorf(pc(), "unexpected section: %s", SectionName(section_code)); 342 return; 343 } 344 345 switch (section_code) { 346 case kUnknownSectionCode: 347 break; 348 case kExceptionSectionCode: 349 // Note: kExceptionSectionCode > kCodeSectionCode, but must appear 350 // before the code section. Hence, treat it as a special case. 351 if (++number_of_exception_sections > 1) { 352 errorf(pc(), "Multiple exception sections not allowed"); 353 return; 354 } else if (next_section_ >= kCodeSectionCode) { 355 errorf(pc(), "Exception section must appear before the code section"); 356 return; 357 } 358 break; 359 default: 360 next_section_ = section_code; 361 ++next_section_; 362 break; 363 } 364 365 switch (section_code) { 366 case kUnknownSectionCode: 367 break; 368 case kTypeSectionCode: 369 DecodeTypeSection(); 370 break; 371 case kImportSectionCode: 372 DecodeImportSection(); 373 break; 374 case kFunctionSectionCode: 375 DecodeFunctionSection(); 376 break; 377 case kTableSectionCode: 378 DecodeTableSection(); 379 break; 380 case kMemorySectionCode: 381 DecodeMemorySection(); 382 break; 383 case kGlobalSectionCode: 384 DecodeGlobalSection(); 385 break; 386 case kExportSectionCode: 387 DecodeExportSection(); 388 break; 389 case kStartSectionCode: 390 DecodeStartSection(); 391 break; 392 case kCodeSectionCode: 393 DecodeCodeSection(verify_functions); 394 break; 395 case kElementSectionCode: 396 DecodeElementSection(); 397 break; 398 case kDataSectionCode: 399 DecodeDataSection(); 400 break; 401 case kNameSectionCode: 402 DecodeNameSection(); 403 break; 404 case kExceptionSectionCode: 405 if (enabled_features_.eh) { 406 DecodeExceptionSection(); 407 } else { 408 errorf(pc(), "unexpected section: %s", SectionName(section_code)); 409 } 410 break; 411 default: 412 errorf(pc(), "unexpected section: %s", SectionName(section_code)); 413 return; 414 } 415 416 if (pc() != bytes.end()) { 417 const char* msg = pc() < bytes.end() ? "shorter" : "longer"; 418 errorf(pc(), 419 "section was %s than expected size " 420 "(%zu bytes expected, %zu decoded)", 421 msg, bytes.size(), static_cast<size_t>(pc() - bytes.begin())); 422 } 423 } 424 425 void DecodeTypeSection() { 426 uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes); 427 module_->signatures.reserve(signatures_count); 428 for (uint32_t i = 0; ok() && i < signatures_count; ++i) { 429 TRACE("DecodeSignature[%d] module+%d\n", i, 430 static_cast<int>(pc_ - start_)); 431 FunctionSig* s = consume_sig(module_->signature_zone.get()); 432 module_->signatures.push_back(s); 433 uint32_t id = s ? module_->signature_map.FindOrInsert(*s) : 0; 434 module_->signature_ids.push_back(id); 435 } 436 module_->signature_map.Freeze(); 437 } 438 439 void DecodeImportSection() { 440 uint32_t import_table_count = 441 consume_count("imports count", kV8MaxWasmImports); 442 module_->import_table.reserve(import_table_count); 443 for (uint32_t i = 0; ok() && i < import_table_count; ++i) { 444 TRACE("DecodeImportTable[%d] module+%d\n", i, 445 static_cast<int>(pc_ - start_)); 446 447 module_->import_table.push_back({ 448 {0, 0}, // module_name 449 {0, 0}, // field_name 450 kExternalFunction, // kind 451 0 // index 452 }); 453 WasmImport* import = &module_->import_table.back(); 454 const byte* pos = pc_; 455 import->module_name = consume_string(*this, true, "module name"); 456 import->field_name = consume_string(*this, true, "field name"); 457 import->kind = 458 static_cast<ImportExportKindCode>(consume_u8("import kind")); 459 switch (import->kind) { 460 case kExternalFunction: { 461 // ===== Imported function ======================================= 462 import->index = static_cast<uint32_t>(module_->functions.size()); 463 module_->num_imported_functions++; 464 module_->functions.push_back({nullptr, // sig 465 import->index, // func_index 466 0, // sig_index 467 {0, 0}, // code 468 true, // imported 469 false}); // exported 470 WasmFunction* function = &module_->functions.back(); 471 function->sig_index = 472 consume_sig_index(module_.get(), &function->sig); 473 break; 474 } 475 case kExternalTable: { 476 // ===== Imported table ========================================== 477 if (!AddTable(module_.get())) break; 478 import->index = static_cast<uint32_t>(module_->tables.size()); 479 module_->tables.emplace_back(); 480 WasmTable* table = &module_->tables.back(); 481 table->imported = true; 482 ValueType type = consume_reference_type(); 483 if (!enabled_features_.anyref) { 484 if (type != kWasmAnyFunc) { 485 error(pc_ - 1, "invalid table type"); 486 break; 487 } 488 } 489 table->type = type; 490 uint8_t flags = validate_table_flags("element count"); 491 consume_resizable_limits( 492 "element count", "elements", FLAG_wasm_max_table_size, 493 &table->initial_size, &table->has_maximum_size, 494 FLAG_wasm_max_table_size, &table->maximum_size, flags); 495 break; 496 } 497 case kExternalMemory: { 498 // ===== Imported memory ========================================= 499 if (!AddMemory(module_.get())) break; 500 uint8_t flags = validate_memory_flags(&module_->has_shared_memory); 501 consume_resizable_limits( 502 "memory", "pages", FLAG_wasm_max_mem_pages, 503 &module_->initial_pages, &module_->has_maximum_pages, 504 kSpecMaxWasmMemoryPages, &module_->maximum_pages, flags); 505 break; 506 } 507 case kExternalGlobal: { 508 // ===== Imported global ========================================= 509 import->index = static_cast<uint32_t>(module_->globals.size()); 510 module_->globals.push_back( 511 {kWasmStmt, false, WasmInitExpr(), {0}, true, false}); 512 WasmGlobal* global = &module_->globals.back(); 513 global->type = consume_value_type(); 514 global->mutability = consume_mutability(); 515 if (global->mutability) { 516 if (enabled_features_.mut_global) { 517 module_->num_imported_mutable_globals++; 518 } else { 519 error("mutable globals cannot be imported"); 520 } 521 } 522 break; 523 } 524 default: 525 errorf(pos, "unknown import kind 0x%02x", import->kind); 526 break; 527 } 528 } 529 } 530 531 void DecodeFunctionSection() { 532 uint32_t functions_count = 533 consume_count("functions count", kV8MaxWasmFunctions); 534 auto counter = 535 SELECT_WASM_COUNTER(GetCounters(), origin_, wasm_functions_per, module); 536 counter->AddSample(static_cast<int>(functions_count)); 537 DCHECK_EQ(module_->functions.size(), module_->num_imported_functions); 538 uint32_t total_function_count = 539 module_->num_imported_functions + functions_count; 540 module_->functions.reserve(total_function_count); 541 module_->num_declared_functions = functions_count; 542 for (uint32_t i = 0; i < functions_count; ++i) { 543 uint32_t func_index = static_cast<uint32_t>(module_->functions.size()); 544 module_->functions.push_back({nullptr, // sig 545 func_index, // func_index 546 0, // sig_index 547 {0, 0}, // code 548 false, // imported 549 false}); // exported 550 WasmFunction* function = &module_->functions.back(); 551 function->sig_index = consume_sig_index(module_.get(), &function->sig); 552 if (!ok()) return; 553 } 554 DCHECK_EQ(module_->functions.size(), total_function_count); 555 } 556 557 void DecodeTableSection() { 558 // TODO(ahaas): Set the correct limit to {kV8MaxWasmTables} once the 559 // implementation of AnyRef landed. 560 uint32_t max_count = enabled_features_.anyref ? 10 : kV8MaxWasmTables; 561 uint32_t table_count = consume_count("table count", max_count); 562 563 for (uint32_t i = 0; ok() && i < table_count; i++) { 564 if (!AddTable(module_.get())) break; 565 module_->tables.emplace_back(); 566 WasmTable* table = &module_->tables.back(); 567 table->type = consume_reference_type(); 568 uint8_t flags = validate_table_flags("table elements"); 569 consume_resizable_limits( 570 "table elements", "elements", FLAG_wasm_max_table_size, 571 &table->initial_size, &table->has_maximum_size, 572 FLAG_wasm_max_table_size, &table->maximum_size, flags); 573 } 574 } 575 576 void DecodeMemorySection() { 577 uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories); 578 579 for (uint32_t i = 0; ok() && i < memory_count; i++) { 580 if (!AddMemory(module_.get())) break; 581 uint8_t flags = validate_memory_flags(&module_->has_shared_memory); 582 consume_resizable_limits( 583 "memory", "pages", FLAG_wasm_max_mem_pages, &module_->initial_pages, 584 &module_->has_maximum_pages, kSpecMaxWasmMemoryPages, 585 &module_->maximum_pages, flags); 586 } 587 } 588 589 void DecodeGlobalSection() { 590 uint32_t globals_count = consume_count("globals count", kV8MaxWasmGlobals); 591 uint32_t imported_globals = static_cast<uint32_t>(module_->globals.size()); 592 module_->globals.reserve(imported_globals + globals_count); 593 for (uint32_t i = 0; ok() && i < globals_count; ++i) { 594 TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast<int>(pc_ - start_)); 595 // Add an uninitialized global and pass a pointer to it. 596 module_->globals.push_back( 597 {kWasmStmt, false, WasmInitExpr(), {0}, false, false}); 598 WasmGlobal* global = &module_->globals.back(); 599 DecodeGlobalInModule(module_.get(), i + imported_globals, global); 600 } 601 if (ok()) CalculateGlobalOffsets(module_.get()); 602 } 603 604 void DecodeExportSection() { 605 uint32_t export_table_count = 606 consume_count("exports count", kV8MaxWasmExports); 607 module_->export_table.reserve(export_table_count); 608 for (uint32_t i = 0; ok() && i < export_table_count; ++i) { 609 TRACE("DecodeExportTable[%d] module+%d\n", i, 610 static_cast<int>(pc_ - start_)); 611 612 module_->export_table.push_back({ 613 {0, 0}, // name 614 kExternalFunction, // kind 615 0 // index 616 }); 617 WasmExport* exp = &module_->export_table.back(); 618 619 exp->name = consume_string(*this, true, "field name"); 620 621 const byte* pos = pc(); 622 exp->kind = static_cast<ImportExportKindCode>(consume_u8("export kind")); 623 switch (exp->kind) { 624 case kExternalFunction: { 625 WasmFunction* func = nullptr; 626 exp->index = consume_func_index(module_.get(), &func); 627 module_->num_exported_functions++; 628 if (func) func->exported = true; 629 break; 630 } 631 case kExternalTable: { 632 WasmTable* table = nullptr; 633 exp->index = consume_table_index(module_.get(), &table); 634 if (table) table->exported = true; 635 break; 636 } 637 case kExternalMemory: { 638 uint32_t index = consume_u32v("memory index"); 639 // TODO(titzer): This should become more regular 640 // once we support multiple memories. 641 if (!module_->has_memory || index != 0) { 642 error("invalid memory index != 0"); 643 } 644 module_->mem_export = true; 645 break; 646 } 647 case kExternalGlobal: { 648 WasmGlobal* global = nullptr; 649 exp->index = consume_global_index(module_.get(), &global); 650 if (global) { 651 if (!enabled_features_.mut_global && global->mutability) { 652 error("mutable globals cannot be exported"); 653 } 654 global->exported = true; 655 } 656 break; 657 } 658 default: 659 errorf(pos, "invalid export kind 0x%02x", exp->kind); 660 break; 661 } 662 } 663 // Check for duplicate exports (except for asm.js). 664 if (ok() && origin_ != kAsmJsOrigin && module_->export_table.size() > 1) { 665 std::vector<WasmExport> sorted_exports(module_->export_table); 666 667 auto cmp_less = [this](const WasmExport& a, const WasmExport& b) { 668 // Return true if a < b. 669 if (a.name.length() != b.name.length()) { 670 return a.name.length() < b.name.length(); 671 } 672 const byte* left = start() + GetBufferRelativeOffset(a.name.offset()); 673 const byte* right = start() + GetBufferRelativeOffset(b.name.offset()); 674 return memcmp(left, right, a.name.length()) < 0; 675 }; 676 std::stable_sort(sorted_exports.begin(), sorted_exports.end(), cmp_less); 677 678 auto it = sorted_exports.begin(); 679 WasmExport* last = &*it++; 680 for (auto end = sorted_exports.end(); it != end; last = &*it++) { 681 DCHECK(!cmp_less(*it, *last)); // Vector must be sorted. 682 if (!cmp_less(*last, *it)) { 683 const byte* pc = start() + GetBufferRelativeOffset(it->name.offset()); 684 TruncatedUserString<> name(pc, it->name.length()); 685 errorf(pc, "Duplicate export name '%.*s' for %s %d and %s %d", 686 name.length(), name.start(), ExternalKindName(last->kind), 687 last->index, ExternalKindName(it->kind), it->index); 688 break; 689 } 690 } 691 } 692 } 693 694 void DecodeStartSection() { 695 WasmFunction* func; 696 const byte* pos = pc_; 697 module_->start_function_index = consume_func_index(module_.get(), &func); 698 if (func && 699 (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) { 700 error(pos, "invalid start function: non-zero parameter or return count"); 701 } 702 } 703 704 void DecodeElementSection() { 705 uint32_t element_count = 706 consume_count("element count", FLAG_wasm_max_table_size); 707 708 if (element_count > 0 && module_->tables.size() == 0) { 709 error(pc_, "The element section requires a table"); 710 } 711 for (uint32_t i = 0; ok() && i < element_count; ++i) { 712 const byte* pos = pc(); 713 uint32_t table_index = consume_u32v("table index"); 714 if (!enabled_features_.anyref && table_index != 0) { 715 errorf(pos, "illegal table index %u != 0", table_index); 716 } 717 if (table_index >= module_->tables.size()) { 718 errorf(pos, "out of bounds table index %u", table_index); 719 break; 720 } 721 if (module_->tables[table_index].type != kWasmAnyFunc) { 722 errorf(pos, "Invalid element segment. Table %u is not of type AnyFunc", 723 table_index); 724 break; 725 } 726 WasmInitExpr offset = consume_init_expr(module_.get(), kWasmI32); 727 uint32_t num_elem = 728 consume_count("number of elements", kV8MaxWasmTableEntries); 729 module_->table_inits.emplace_back(table_index, offset); 730 WasmTableInit* init = &module_->table_inits.back(); 731 for (uint32_t j = 0; j < num_elem; j++) { 732 WasmFunction* func = nullptr; 733 uint32_t index = consume_func_index(module_.get(), &func); 734 DCHECK_IMPLIES(ok(), func != nullptr); 735 if (!ok()) break; 736 DCHECK_EQ(index, func->func_index); 737 init->entries.push_back(index); 738 } 739 } 740 } 741 742 void DecodeCodeSection(bool verify_functions) { 743 uint32_t pos = pc_offset(); 744 uint32_t functions_count = consume_u32v("functions count"); 745 CheckFunctionsCount(functions_count, pos); 746 for (uint32_t i = 0; ok() && i < functions_count; ++i) { 747 const byte* pos = pc(); 748 uint32_t size = consume_u32v("body size"); 749 if (size > kV8MaxWasmFunctionSize) { 750 errorf(pos, "size %u > maximum function size %zu", size, 751 kV8MaxWasmFunctionSize); 752 return; 753 } 754 uint32_t offset = pc_offset(); 755 consume_bytes(size, "function body"); 756 if (failed()) break; 757 DecodeFunctionBody(i, size, offset, verify_functions); 758 } 759 } 760 761 bool CheckFunctionsCount(uint32_t functions_count, uint32_t offset) { 762 if (functions_count != module_->num_declared_functions) { 763 Reset(nullptr, nullptr, offset); 764 errorf(nullptr, "function body count %u mismatch (%u expected)", 765 functions_count, module_->num_declared_functions); 766 return false; 767 } 768 return true; 769 } 770 771 void DecodeFunctionBody(uint32_t index, uint32_t length, uint32_t offset, 772 bool verify_functions) { 773 WasmFunction* function = 774 &module_->functions[index + module_->num_imported_functions]; 775 function->code = {offset, length}; 776 if (verify_functions) { 777 ModuleWireBytes bytes(start_, end_); 778 VerifyFunctionBody(module_->signature_zone->allocator(), 779 index + module_->num_imported_functions, bytes, 780 module_.get(), function); 781 } 782 } 783 784 void DecodeDataSection() { 785 uint32_t data_segments_count = 786 consume_count("data segments count", kV8MaxWasmDataSegments); 787 module_->data_segments.reserve(data_segments_count); 788 for (uint32_t i = 0; ok() && i < data_segments_count; ++i) { 789 if (!module_->has_memory) { 790 error("cannot load data without memory"); 791 break; 792 } 793 TRACE("DecodeDataSegment[%d] module+%d\n", i, 794 static_cast<int>(pc_ - start_)); 795 module_->data_segments.push_back({ 796 WasmInitExpr(), // dest_addr 797 {0, 0} // source 798 }); 799 WasmDataSegment* segment = &module_->data_segments.back(); 800 DecodeDataSegmentInModule(module_.get(), segment); 801 } 802 } 803 804 void DecodeNameSection() { 805 // TODO(titzer): find a way to report name errors as warnings. 806 // Use an inner decoder so that errors don't fail the outer decoder. 807 Decoder inner(start_, pc_, end_, buffer_offset_); 808 // Decode all name subsections. 809 // Be lenient with their order. 810 while (inner.ok() && inner.more()) { 811 uint8_t name_type = inner.consume_u8("name type"); 812 if (name_type & 0x80) inner.error("name type if not varuint7"); 813 814 uint32_t name_payload_len = inner.consume_u32v("name payload length"); 815 if (!inner.checkAvailable(name_payload_len)) break; 816 817 // Decode module name, ignore the rest. 818 // Function and local names will be decoded when needed. 819 if (name_type == NameSectionKindCode::kModule) { 820 WireBytesRef name = consume_string(inner, false, "module name"); 821 if (inner.ok() && validate_utf8(&inner, name)) module_->name = name; 822 } else { 823 inner.consume_bytes(name_payload_len, "name subsection payload"); 824 } 825 } 826 // Skip the whole names section in the outer decoder. 827 consume_bytes(static_cast<uint32_t>(end_ - start_), nullptr); 828 } 829 830 void DecodeExceptionSection() { 831 uint32_t exception_count = 832 consume_count("exception count", kV8MaxWasmExceptions); 833 for (uint32_t i = 0; ok() && i < exception_count; ++i) { 834 TRACE("DecodeExceptionSignature[%d] module+%d\n", i, 835 static_cast<int>(pc_ - start_)); 836 module_->exceptions.emplace_back( 837 consume_exception_sig(module_->signature_zone.get())); 838 } 839 } 840 841 ModuleResult FinishDecoding(bool verify_functions = true) { 842 if (ok()) { 843 CalculateGlobalOffsets(module_.get()); 844 } 845 ModuleResult result = toResult(std::move(module_)); 846 if (verify_functions && result.ok()) { 847 // Copy error code and location. 848 result.MoveErrorFrom(intermediate_result_); 849 } 850 return result; 851 } 852 853 // Decodes an entire module. 854 ModuleResult DecodeModule(Counters* counters, AccountingAllocator* allocator, 855 bool verify_functions = true) { 856 StartDecoding(counters, allocator); 857 uint32_t offset = 0; 858 Vector<const byte> orig_bytes(start(), end() - start()); 859 DecodeModuleHeader(Vector<const uint8_t>(start(), end() - start()), offset); 860 if (failed()) { 861 return FinishDecoding(verify_functions); 862 } 863 // Size of the module header. 864 offset += 8; 865 Decoder decoder(start_ + offset, end_, offset); 866 867 WasmSectionIterator section_iter(decoder); 868 869 while (ok() && section_iter.more()) { 870 // Shift the offset by the section header length 871 offset += section_iter.payload_start() - section_iter.section_start(); 872 if (section_iter.section_code() != SectionCode::kUnknownSectionCode) { 873 DecodeSection(section_iter.section_code(), section_iter.payload(), 874 offset, verify_functions); 875 } 876 // Shift the offset by the remaining section payload 877 offset += section_iter.payload_length(); 878 section_iter.advance(true); 879 } 880 881 if (FLAG_dump_wasm_module) DumpModule(orig_bytes); 882 883 if (decoder.failed()) { 884 return decoder.toResult<std::unique_ptr<WasmModule>>(nullptr); 885 } 886 887 return FinishDecoding(verify_functions); 888 } 889 890 // Decodes a single anonymous function starting at {start_}. 891 FunctionResult DecodeSingleFunction(Zone* zone, 892 const ModuleWireBytes& wire_bytes, 893 const WasmModule* module, 894 std::unique_ptr<WasmFunction> function) { 895 pc_ = start_; 896 function->sig = consume_sig(zone); 897 function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)}; 898 899 if (ok()) 900 VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module, 901 function.get()); 902 903 FunctionResult result(std::move(function)); 904 // Copy error code and location. 905 result.MoveErrorFrom(intermediate_result_); 906 return result; 907 } 908 909 // Decodes a single function signature at {start}. 910 FunctionSig* DecodeFunctionSignature(Zone* zone, const byte* start) { 911 pc_ = start; 912 FunctionSig* result = consume_sig(zone); 913 return ok() ? result : nullptr; 914 } 915 916 WasmInitExpr DecodeInitExpr(const byte* start) { 917 pc_ = start; 918 return consume_init_expr(nullptr, kWasmStmt); 919 } 920 921 const std::shared_ptr<WasmModule>& shared_module() const { return module_; } 922 923 Counters* GetCounters() const { 924 DCHECK_NOT_NULL(counters_); 925 return counters_; 926 } 927 928 void SetCounters(Counters* counters) { 929 DCHECK_NULL(counters_); 930 counters_ = counters; 931 } 932 933 private: 934 const WasmFeatures enabled_features_; 935 std::shared_ptr<WasmModule> module_; 936 Counters* counters_ = nullptr; 937 // The type section is the first section in a module. 938 uint8_t next_section_ = kFirstSectionInModule; 939 uint32_t number_of_exception_sections = 0; 940 // We store next_section_ as uint8_t instead of SectionCode so that we can 941 // increment it. This static_assert should make sure that SectionCode does not 942 // get bigger than uint8_t accidentially. 943 static_assert(sizeof(ModuleDecoderImpl::next_section_) == sizeof(SectionCode), 944 "type mismatch"); 945 Result<bool> intermediate_result_; 946 ModuleOrigin origin_; 947 948 uint32_t off(const byte* ptr) { 949 return static_cast<uint32_t>(ptr - start_) + buffer_offset_; 950 } 951 952 bool AddTable(WasmModule* module) { 953 if (enabled_features_.anyref) return true; 954 if (module->tables.size() > 0) { 955 error("At most one table is supported"); 956 return false; 957 } else { 958 return true; 959 } 960 } 961 962 bool AddMemory(WasmModule* module) { 963 if (module->has_memory) { 964 error("At most one memory is supported"); 965 return false; 966 } else { 967 module->has_memory = true; 968 return true; 969 } 970 } 971 972 // Decodes a single global entry inside a module starting at {pc_}. 973 void DecodeGlobalInModule(WasmModule* module, uint32_t index, 974 WasmGlobal* global) { 975 global->type = consume_value_type(); 976 global->mutability = consume_mutability(); 977 const byte* pos = pc(); 978 global->init = consume_init_expr(module, kWasmStmt); 979 if (global->init.kind == WasmInitExpr::kGlobalIndex) { 980 uint32_t other_index = global->init.val.global_index; 981 if (other_index >= index) { 982 errorf(pos, 983 "invalid global index in init expression, " 984 "index %u, other_index %u", 985 index, other_index); 986 } else if (module->globals[other_index].type != global->type) { 987 errorf(pos, 988 "type mismatch in global initialization " 989 "(from global #%u), expected %s, got %s", 990 other_index, ValueTypes::TypeName(global->type), 991 ValueTypes::TypeName(module->globals[other_index].type)); 992 } 993 } else { 994 if (global->type != TypeOf(module, global->init)) { 995 errorf(pos, "type error in global initialization, expected %s, got %s", 996 ValueTypes::TypeName(global->type), 997 ValueTypes::TypeName(TypeOf(module, global->init))); 998 } 999 } 1000 } 1001 1002 // Decodes a single data segment entry inside a module starting at {pc_}. 1003 void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) { 1004 expect_u8("linear memory index", 0); 1005 segment->dest_addr = consume_init_expr(module, kWasmI32); 1006 uint32_t source_length = consume_u32v("source size"); 1007 uint32_t source_offset = pc_offset(); 1008 1009 consume_bytes(source_length, "segment data"); 1010 if (failed()) return; 1011 1012 segment->source = {source_offset, source_length}; 1013 } 1014 1015 // Calculate individual global offsets and total size of globals table. 1016 void CalculateGlobalOffsets(WasmModule* module) { 1017 uint32_t offset = 0; 1018 uint32_t num_imported_mutable_globals = 0; 1019 if (module->globals.size() == 0) { 1020 module->globals_buffer_size = 0; 1021 return; 1022 } 1023 for (WasmGlobal& global : module->globals) { 1024 byte size = ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type)); 1025 if (global.mutability && global.imported) { 1026 DCHECK(enabled_features_.mut_global); 1027 global.index = num_imported_mutable_globals++; 1028 } else { 1029 offset = (offset + size - 1) & ~(size - 1); // align 1030 global.offset = offset; 1031 offset += size; 1032 } 1033 } 1034 module->globals_buffer_size = offset; 1035 } 1036 1037 // Verifies the body (code) of a given function. 1038 void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num, 1039 const ModuleWireBytes& wire_bytes, 1040 const WasmModule* module, WasmFunction* function) { 1041 WasmFunctionName func_name(function, 1042 wire_bytes.GetNameOrNull(function, module)); 1043 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { 1044 StdoutStream os; 1045 os << "Verifying wasm function " << func_name << std::endl; 1046 } 1047 FunctionBody body = { 1048 function->sig, function->code.offset(), 1049 start_ + GetBufferRelativeOffset(function->code.offset()), 1050 start_ + GetBufferRelativeOffset(function->code.end_offset())}; 1051 1052 DecodeResult result; 1053 { 1054 auto time_counter = SELECT_WASM_COUNTER(GetCounters(), origin_, 1055 wasm_decode, function_time); 1056 1057 TimedHistogramScope wasm_decode_function_time_scope(time_counter); 1058 WasmFeatures unused_detected_features; 1059 result = VerifyWasmCode(allocator, enabled_features_, module, 1060 &unused_detected_features, body); 1061 } 1062 1063 if (result.failed()) { 1064 // Wrap the error message from the function decoder. 1065 std::ostringstream wrapped; 1066 wrapped << "in function " << func_name << ": " << result.error_msg(); 1067 result.error(result.error_offset(), wrapped.str()); 1068 1069 // Set error code and location, if this is the first error. 1070 if (intermediate_result_.ok()) { 1071 intermediate_result_.MoveErrorFrom(result); 1072 } 1073 } 1074 } 1075 1076 uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) { 1077 const byte* pos = pc_; 1078 uint32_t sig_index = consume_u32v("signature index"); 1079 if (sig_index >= module->signatures.size()) { 1080 errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index, 1081 static_cast<int>(module->signatures.size())); 1082 *sig = nullptr; 1083 return 0; 1084 } 1085 *sig = module->signatures[sig_index]; 1086 return sig_index; 1087 } 1088 1089 uint32_t consume_count(const char* name, size_t maximum) { 1090 const byte* p = pc_; 1091 uint32_t count = consume_u32v(name); 1092 if (count > maximum) { 1093 errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum); 1094 return static_cast<uint32_t>(maximum); 1095 } 1096 return count; 1097 } 1098 1099 uint32_t consume_func_index(WasmModule* module, WasmFunction** func) { 1100 return consume_index("function index", module->functions, func); 1101 } 1102 1103 uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) { 1104 return consume_index("global index", module->globals, global); 1105 } 1106 1107 uint32_t consume_table_index(WasmModule* module, WasmTable** table) { 1108 return consume_index("table index", module->tables, table); 1109 } 1110 1111 template <typename T> 1112 uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) { 1113 const byte* pos = pc_; 1114 uint32_t index = consume_u32v(name); 1115 if (index >= vector.size()) { 1116 errorf(pos, "%s %u out of bounds (%d entr%s)", name, index, 1117 static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies"); 1118 *ptr = nullptr; 1119 return 0; 1120 } 1121 *ptr = &vector[index]; 1122 return index; 1123 } 1124 1125 uint8_t validate_table_flags(const char* name) { 1126 uint8_t flags = consume_u8("resizable limits flags"); 1127 const byte* pos = pc(); 1128 if (flags & 0xFE) { 1129 errorf(pos - 1, "invalid %s limits flags", name); 1130 } 1131 return flags; 1132 } 1133 1134 uint8_t validate_memory_flags(bool* has_shared_memory) { 1135 uint8_t flags = consume_u8("resizable limits flags"); 1136 const byte* pos = pc(); 1137 *has_shared_memory = false; 1138 if (enabled_features_.threads) { 1139 if (flags & 0xFC) { 1140 errorf(pos - 1, "invalid memory limits flags"); 1141 } else if (flags == 3) { 1142 DCHECK_NOT_NULL(has_shared_memory); 1143 *has_shared_memory = true; 1144 } else if (flags == 2) { 1145 errorf(pos - 1, 1146 "memory limits flags should have maximum defined if shared is " 1147 "true"); 1148 } 1149 } else { 1150 if (flags & 0xFE) { 1151 errorf(pos - 1, "invalid memory limits flags"); 1152 } 1153 } 1154 return flags; 1155 } 1156 1157 void consume_resizable_limits(const char* name, const char* units, 1158 uint32_t max_initial, uint32_t* initial, 1159 bool* has_max, uint32_t max_maximum, 1160 uint32_t* maximum, uint8_t flags) { 1161 const byte* pos = pc(); 1162 *initial = consume_u32v("initial size"); 1163 *has_max = false; 1164 if (*initial > max_initial) { 1165 errorf(pos, 1166 "initial %s size (%u %s) is larger than implementation limit (%u)", 1167 name, *initial, units, max_initial); 1168 } 1169 if (flags & 1) { 1170 *has_max = true; 1171 pos = pc(); 1172 *maximum = consume_u32v("maximum size"); 1173 if (*maximum > max_maximum) { 1174 errorf( 1175 pos, 1176 "maximum %s size (%u %s) is larger than implementation limit (%u)", 1177 name, *maximum, units, max_maximum); 1178 } 1179 if (*maximum < *initial) { 1180 errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)", 1181 name, *maximum, units, *initial, units); 1182 } 1183 } else { 1184 *has_max = false; 1185 *maximum = max_initial; 1186 } 1187 } 1188 1189 bool expect_u8(const char* name, uint8_t expected) { 1190 const byte* pos = pc(); 1191 uint8_t value = consume_u8(name); 1192 if (value != expected) { 1193 errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); 1194 return false; 1195 } 1196 return true; 1197 } 1198 1199 WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) { 1200 const byte* pos = pc(); 1201 uint8_t opcode = consume_u8("opcode"); 1202 WasmInitExpr expr; 1203 unsigned len = 0; 1204 switch (opcode) { 1205 case kExprGetGlobal: { 1206 GlobalIndexImmediate<Decoder::kValidate> imm(this, pc() - 1); 1207 if (module->globals.size() <= imm.index) { 1208 error("global index is out of bounds"); 1209 expr.kind = WasmInitExpr::kNone; 1210 expr.val.i32_const = 0; 1211 break; 1212 } 1213 WasmGlobal* global = &module->globals[imm.index]; 1214 if (global->mutability || !global->imported) { 1215 error( 1216 "only immutable imported globals can be used in initializer " 1217 "expressions"); 1218 expr.kind = WasmInitExpr::kNone; 1219 expr.val.i32_const = 0; 1220 break; 1221 } 1222 expr.kind = WasmInitExpr::kGlobalIndex; 1223 expr.val.global_index = imm.index; 1224 len = imm.length; 1225 break; 1226 } 1227 case kExprI32Const: { 1228 ImmI32Immediate<Decoder::kValidate> imm(this, pc() - 1); 1229 expr.kind = WasmInitExpr::kI32Const; 1230 expr.val.i32_const = imm.value; 1231 len = imm.length; 1232 break; 1233 } 1234 case kExprF32Const: { 1235 ImmF32Immediate<Decoder::kValidate> imm(this, pc() - 1); 1236 expr.kind = WasmInitExpr::kF32Const; 1237 expr.val.f32_const = imm.value; 1238 len = imm.length; 1239 break; 1240 } 1241 case kExprI64Const: { 1242 ImmI64Immediate<Decoder::kValidate> imm(this, pc() - 1); 1243 expr.kind = WasmInitExpr::kI64Const; 1244 expr.val.i64_const = imm.value; 1245 len = imm.length; 1246 break; 1247 } 1248 case kExprF64Const: { 1249 ImmF64Immediate<Decoder::kValidate> imm(this, pc() - 1); 1250 expr.kind = WasmInitExpr::kF64Const; 1251 expr.val.f64_const = imm.value; 1252 len = imm.length; 1253 break; 1254 } 1255 case kExprRefNull: { 1256 if (enabled_features_.anyref) { 1257 expr.kind = WasmInitExpr::kAnyRefConst; 1258 len = 0; 1259 break; 1260 } 1261 V8_FALLTHROUGH; 1262 } 1263 default: { 1264 error("invalid opcode in initialization expression"); 1265 expr.kind = WasmInitExpr::kNone; 1266 expr.val.i32_const = 0; 1267 } 1268 } 1269 consume_bytes(len, "init code"); 1270 if (!expect_u8("end opcode", kExprEnd)) { 1271 expr.kind = WasmInitExpr::kNone; 1272 } 1273 if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) { 1274 errorf(pos, "type error in init expression, expected %s, got %s", 1275 ValueTypes::TypeName(expected), 1276 ValueTypes::TypeName(TypeOf(module, expr))); 1277 } 1278 return expr; 1279 } 1280 1281 // Read a mutability flag 1282 bool consume_mutability() { 1283 byte val = consume_u8("mutability"); 1284 if (val > 1) error(pc_ - 1, "invalid mutability"); 1285 return val != 0; 1286 } 1287 1288 // Reads a single 8-bit integer, interpreting it as a local type. 1289 ValueType consume_value_type() { 1290 byte val = consume_u8("value type"); 1291 ValueTypeCode t = static_cast<ValueTypeCode>(val); 1292 switch (t) { 1293 case kLocalI32: 1294 return kWasmI32; 1295 case kLocalI64: 1296 return kWasmI64; 1297 case kLocalF32: 1298 return kWasmF32; 1299 case kLocalF64: 1300 return kWasmF64; 1301 default: 1302 if (origin_ == kWasmOrigin) { 1303 switch (t) { 1304 case kLocalS128: 1305 if (enabled_features_.simd) return kWasmS128; 1306 break; 1307 case kLocalAnyFunc: 1308 if (enabled_features_.anyref) return kWasmAnyFunc; 1309 break; 1310 case kLocalAnyRef: 1311 if (enabled_features_.anyref) return kWasmAnyRef; 1312 break; 1313 default: 1314 break; 1315 } 1316 } 1317 error(pc_ - 1, "invalid local type"); 1318 return kWasmStmt; 1319 } 1320 } 1321 1322 // Reads a single 8-bit integer, interpreting it as a reference type. 1323 ValueType consume_reference_type() { 1324 byte val = consume_u8("reference type"); 1325 ValueTypeCode t = static_cast<ValueTypeCode>(val); 1326 switch (t) { 1327 case kLocalAnyFunc: 1328 return kWasmAnyFunc; 1329 case kLocalAnyRef: 1330 if (!enabled_features_.anyref) { 1331 error(pc_ - 1, 1332 "Invalid type. Set --experimental-wasm-anyref to use 'AnyRef'"); 1333 } 1334 return kWasmAnyRef; 1335 default: 1336 break; 1337 } 1338 error(pc_ - 1, "invalid reference type"); 1339 return kWasmStmt; 1340 } 1341 1342 FunctionSig* consume_sig(Zone* zone) { 1343 constexpr bool has_return_values = true; 1344 return consume_sig_internal(zone, has_return_values); 1345 } 1346 1347 WasmExceptionSig* consume_exception_sig(Zone* zone) { 1348 constexpr bool has_return_values = true; 1349 return consume_sig_internal(zone, !has_return_values); 1350 } 1351 1352 private: 1353 FunctionSig* consume_sig_internal(Zone* zone, bool has_return_values) { 1354 if (has_return_values && !expect_u8("type form", kWasmFunctionTypeCode)) 1355 return nullptr; 1356 // parse parameter types 1357 uint32_t param_count = 1358 consume_count("param count", kV8MaxWasmFunctionParams); 1359 if (failed()) return nullptr; 1360 std::vector<ValueType> params; 1361 for (uint32_t i = 0; ok() && i < param_count; ++i) { 1362 ValueType param = consume_value_type(); 1363 params.push_back(param); 1364 } 1365 std::vector<ValueType> returns; 1366 uint32_t return_count = 0; 1367 if (has_return_values) { 1368 // parse return types 1369 const size_t max_return_count = enabled_features_.mv 1370 ? kV8MaxWasmFunctionMultiReturns 1371 : kV8MaxWasmFunctionReturns; 1372 return_count = consume_count("return count", max_return_count); 1373 if (failed()) return nullptr; 1374 for (uint32_t i = 0; ok() && i < return_count; ++i) { 1375 ValueType ret = consume_value_type(); 1376 returns.push_back(ret); 1377 } 1378 } 1379 1380 if (failed()) return nullptr; 1381 1382 // FunctionSig stores the return types first. 1383 ValueType* buffer = zone->NewArray<ValueType>(param_count + return_count); 1384 uint32_t b = 0; 1385 for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i]; 1386 for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i]; 1387 1388 return new (zone) FunctionSig(return_count, param_count, buffer); 1389 } 1390 }; 1391 1392 ModuleResult DecodeWasmModule(const WasmFeatures& enabled, 1393 const byte* module_start, const byte* module_end, 1394 bool verify_functions, ModuleOrigin origin, 1395 Counters* counters, 1396 AccountingAllocator* allocator) { 1397 auto counter = 1398 SELECT_WASM_COUNTER(counters, origin, wasm_decode, module_time); 1399 TimedHistogramScope wasm_decode_module_time_scope(counter); 1400 size_t size = module_end - module_start; 1401 if (module_start > module_end) return ModuleResult::Error("start > end"); 1402 if (size >= kV8MaxWasmModuleSize) 1403 return ModuleResult::Error("size > maximum module size: %zu", size); 1404 // TODO(bradnelson): Improve histogram handling of size_t. 1405 auto size_counter = 1406 SELECT_WASM_COUNTER(counters, origin, wasm, module_size_bytes); 1407 size_counter->AddSample(static_cast<int>(size)); 1408 // Signatures are stored in zone memory, which have the same lifetime 1409 // as the {module}. 1410 ModuleDecoderImpl decoder(enabled, module_start, module_end, origin); 1411 ModuleResult result = 1412 decoder.DecodeModule(counters, allocator, verify_functions); 1413 // TODO(bradnelson): Improve histogram handling of size_t. 1414 // TODO(titzer): this isn't accurate, since it doesn't count the data 1415 // allocated on the C++ heap. 1416 // https://bugs.chromium.org/p/chromium/issues/detail?id=657320 1417 if (result.ok()) { 1418 auto peak_counter = SELECT_WASM_COUNTER(counters, origin, wasm_decode, 1419 module_peak_memory_bytes); 1420 peak_counter->AddSample( 1421 static_cast<int>(result.val->signature_zone->allocation_size())); 1422 } 1423 return result; 1424 } 1425 1426 ModuleDecoder::ModuleDecoder(const WasmFeatures& enabled) 1427 : enabled_features_(enabled) {} 1428 1429 ModuleDecoder::~ModuleDecoder() = default; 1430 1431 const std::shared_ptr<WasmModule>& ModuleDecoder::shared_module() const { 1432 return impl_->shared_module(); 1433 } 1434 1435 void ModuleDecoder::StartDecoding(Counters* counters, 1436 AccountingAllocator* allocator, 1437 ModuleOrigin origin) { 1438 DCHECK_NULL(impl_); 1439 impl_.reset(new ModuleDecoderImpl(enabled_features_, origin)); 1440 impl_->StartDecoding(counters, allocator); 1441 } 1442 1443 void ModuleDecoder::DecodeModuleHeader(Vector<const uint8_t> bytes, 1444 uint32_t offset) { 1445 impl_->DecodeModuleHeader(bytes, offset); 1446 } 1447 1448 void ModuleDecoder::DecodeSection(SectionCode section_code, 1449 Vector<const uint8_t> bytes, uint32_t offset, 1450 bool verify_functions) { 1451 impl_->DecodeSection(section_code, bytes, offset, verify_functions); 1452 } 1453 1454 void ModuleDecoder::DecodeFunctionBody(uint32_t index, uint32_t length, 1455 uint32_t offset, bool verify_functions) { 1456 impl_->DecodeFunctionBody(index, length, offset, verify_functions); 1457 } 1458 1459 bool ModuleDecoder::CheckFunctionsCount(uint32_t functions_count, 1460 uint32_t offset) { 1461 return impl_->CheckFunctionsCount(functions_count, offset); 1462 } 1463 1464 ModuleResult ModuleDecoder::FinishDecoding(bool verify_functions) { 1465 return impl_->FinishDecoding(verify_functions); 1466 } 1467 1468 SectionCode ModuleDecoder::IdentifyUnknownSection(Decoder& decoder, 1469 const byte* end) { 1470 WireBytesRef string = consume_string(decoder, true, "section name"); 1471 if (decoder.failed() || decoder.pc() > end) { 1472 return kUnknownSectionCode; 1473 } 1474 const byte* section_name_start = 1475 decoder.start() + decoder.GetBufferRelativeOffset(string.offset()); 1476 1477 TRACE(" +%d section name : \"%.*s\"\n", 1478 static_cast<int>(section_name_start - decoder.start()), 1479 string.length() < 20 ? string.length() : 20, section_name_start); 1480 1481 if (string.length() == num_chars(kNameString) && 1482 strncmp(reinterpret_cast<const char*>(section_name_start), kNameString, 1483 num_chars(kNameString)) == 0) { 1484 return kNameSectionCode; 1485 } 1486 return kUnknownSectionCode; 1487 } 1488 1489 bool ModuleDecoder::ok() { return impl_->ok(); } 1490 1491 FunctionSig* DecodeWasmSignatureForTesting(const WasmFeatures& enabled, 1492 Zone* zone, const byte* start, 1493 const byte* end) { 1494 ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin); 1495 return decoder.DecodeFunctionSignature(zone, start); 1496 } 1497 1498 WasmInitExpr DecodeWasmInitExprForTesting(const WasmFeatures& enabled, 1499 const byte* start, const byte* end) { 1500 AccountingAllocator allocator; 1501 ModuleDecoderImpl decoder(enabled, start, end, kWasmOrigin); 1502 return decoder.DecodeInitExpr(start); 1503 } 1504 1505 FunctionResult DecodeWasmFunctionForTesting( 1506 const WasmFeatures& enabled, Zone* zone, const ModuleWireBytes& wire_bytes, 1507 const WasmModule* module, const byte* function_start, 1508 const byte* function_end, Counters* counters) { 1509 size_t size = function_end - function_start; 1510 if (function_start > function_end) 1511 return FunctionResult::Error("start > end"); 1512 auto size_histogram = SELECT_WASM_COUNTER(counters, module->origin, wasm, 1513 function_size_bytes); 1514 // TODO(bradnelson): Improve histogram handling of ptrdiff_t. 1515 size_histogram->AddSample(static_cast<int>(size)); 1516 if (size > kV8MaxWasmFunctionSize) 1517 return FunctionResult::Error("size > maximum function size: %zu", size); 1518 ModuleDecoderImpl decoder(enabled, function_start, function_end, kWasmOrigin); 1519 decoder.SetCounters(counters); 1520 return decoder.DecodeSingleFunction(zone, wire_bytes, module, 1521 base::make_unique<WasmFunction>()); 1522 } 1523 1524 AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start, 1525 const byte* tables_end) { 1526 AsmJsOffsets table; 1527 1528 Decoder decoder(tables_start, tables_end); 1529 uint32_t functions_count = decoder.consume_u32v("functions count"); 1530 // Reserve space for the entries, taking care of invalid input. 1531 if (functions_count < static_cast<unsigned>(tables_end - tables_start)) { 1532 table.reserve(functions_count); 1533 } 1534 1535 for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) { 1536 uint32_t size = decoder.consume_u32v("table size"); 1537 if (size == 0) { 1538 table.emplace_back(); 1539 continue; 1540 } 1541 if (!decoder.checkAvailable(size)) { 1542 decoder.error("illegal asm function offset table size"); 1543 } 1544 const byte* table_end = decoder.pc() + size; 1545 uint32_t locals_size = decoder.consume_u32v("locals size"); 1546 int function_start_position = decoder.consume_u32v("function start pos"); 1547 int last_byte_offset = locals_size; 1548 int last_asm_position = function_start_position; 1549 std::vector<AsmJsOffsetEntry> func_asm_offsets; 1550 func_asm_offsets.reserve(size / 4); // conservative estimation 1551 // Add an entry for the stack check, associated with position 0. 1552 func_asm_offsets.push_back( 1553 {0, function_start_position, function_start_position}); 1554 while (decoder.ok() && decoder.pc() < table_end) { 1555 last_byte_offset += decoder.consume_u32v("byte offset delta"); 1556 int call_position = 1557 last_asm_position + decoder.consume_i32v("call position delta"); 1558 int to_number_position = 1559 call_position + decoder.consume_i32v("to_number position delta"); 1560 last_asm_position = to_number_position; 1561 func_asm_offsets.push_back( 1562 {last_byte_offset, call_position, to_number_position}); 1563 } 1564 if (decoder.pc() != table_end) { 1565 decoder.error("broken asm offset table"); 1566 } 1567 table.push_back(std::move(func_asm_offsets)); 1568 } 1569 if (decoder.more()) decoder.error("unexpected additional bytes"); 1570 1571 return decoder.toResult(std::move(table)); 1572 } 1573 1574 std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start, 1575 const byte* end) { 1576 Decoder decoder(start, end); 1577 decoder.consume_bytes(4, "wasm magic"); 1578 decoder.consume_bytes(4, "wasm version"); 1579 1580 std::vector<CustomSectionOffset> result; 1581 1582 while (decoder.more()) { 1583 byte section_code = decoder.consume_u8("section code"); 1584 uint32_t section_length = decoder.consume_u32v("section length"); 1585 uint32_t section_start = decoder.pc_offset(); 1586 if (section_code != 0) { 1587 // Skip known sections. 1588 decoder.consume_bytes(section_length, "section bytes"); 1589 continue; 1590 } 1591 uint32_t name_length = decoder.consume_u32v("name length"); 1592 uint32_t name_offset = decoder.pc_offset(); 1593 decoder.consume_bytes(name_length, "section name"); 1594 uint32_t payload_offset = decoder.pc_offset(); 1595 if (section_length < (payload_offset - section_start)) { 1596 decoder.error("invalid section length"); 1597 break; 1598 } 1599 uint32_t payload_length = section_length - (payload_offset - section_start); 1600 decoder.consume_bytes(payload_length); 1601 if (decoder.failed()) break; 1602 result.push_back({{section_start, section_length}, 1603 {name_offset, name_length}, 1604 {payload_offset, payload_length}}); 1605 } 1606 1607 return result; 1608 } 1609 1610 namespace { 1611 1612 bool FindSection(Decoder& decoder, SectionCode section_code) { 1613 static constexpr int kModuleHeaderSize = 8; 1614 decoder.consume_bytes(kModuleHeaderSize, "module header"); 1615 1616 WasmSectionIterator section_iter(decoder); 1617 1618 while (decoder.ok() && section_iter.more() && 1619 section_iter.section_code() != kNameSectionCode) { 1620 section_iter.advance(true); 1621 } 1622 if (!section_iter.more()) return false; 1623 1624 // Reset the decoder to not read beyond the name section end. 1625 decoder.Reset(section_iter.payload(), decoder.pc_offset()); 1626 return true; 1627 } 1628 1629 } // namespace 1630 1631 void DecodeFunctionNames(const byte* module_start, const byte* module_end, 1632 std::unordered_map<uint32_t, WireBytesRef>* names) { 1633 DCHECK_NOT_NULL(names); 1634 DCHECK(names->empty()); 1635 1636 Decoder decoder(module_start, module_end); 1637 if (!FindSection(decoder, kNameSectionCode)) return; 1638 1639 while (decoder.ok() && decoder.more()) { 1640 uint8_t name_type = decoder.consume_u8("name type"); 1641 if (name_type & 0x80) break; // no varuint7 1642 1643 uint32_t name_payload_len = decoder.consume_u32v("name payload length"); 1644 if (!decoder.checkAvailable(name_payload_len)) break; 1645 1646 if (name_type != NameSectionKindCode::kFunction) { 1647 decoder.consume_bytes(name_payload_len, "name subsection payload"); 1648 continue; 1649 } 1650 uint32_t functions_count = decoder.consume_u32v("functions count"); 1651 1652 for (; decoder.ok() && functions_count > 0; --functions_count) { 1653 uint32_t function_index = decoder.consume_u32v("function index"); 1654 WireBytesRef name = consume_string(decoder, false, "function name"); 1655 1656 // Be lenient with errors in the name section: Ignore non-UTF8 names. You 1657 // can even assign to the same function multiple times (last valid one 1658 // wins). 1659 if (decoder.ok() && validate_utf8(&decoder, name)) { 1660 names->insert(std::make_pair(function_index, name)); 1661 } 1662 } 1663 } 1664 } 1665 1666 void DecodeLocalNames(const byte* module_start, const byte* module_end, 1667 LocalNames* result) { 1668 DCHECK_NOT_NULL(result); 1669 DCHECK(result->names.empty()); 1670 1671 Decoder decoder(module_start, module_end); 1672 if (!FindSection(decoder, kNameSectionCode)) return; 1673 1674 while (decoder.ok() && decoder.more()) { 1675 uint8_t name_type = decoder.consume_u8("name type"); 1676 if (name_type & 0x80) break; // no varuint7 1677 1678 uint32_t name_payload_len = decoder.consume_u32v("name payload length"); 1679 if (!decoder.checkAvailable(name_payload_len)) break; 1680 1681 if (name_type != NameSectionKindCode::kLocal) { 1682 decoder.consume_bytes(name_payload_len, "name subsection payload"); 1683 continue; 1684 } 1685 1686 uint32_t local_names_count = decoder.consume_u32v("local names count"); 1687 for (uint32_t i = 0; i < local_names_count; ++i) { 1688 uint32_t func_index = decoder.consume_u32v("function index"); 1689 if (func_index > kMaxInt) continue; 1690 result->names.emplace_back(static_cast<int>(func_index)); 1691 LocalNamesPerFunction& func_names = result->names.back(); 1692 result->max_function_index = 1693 std::max(result->max_function_index, func_names.function_index); 1694 uint32_t num_names = decoder.consume_u32v("namings count"); 1695 for (uint32_t k = 0; k < num_names; ++k) { 1696 uint32_t local_index = decoder.consume_u32v("local index"); 1697 WireBytesRef name = consume_string(decoder, true, "local name"); 1698 if (!decoder.ok()) break; 1699 if (local_index > kMaxInt) continue; 1700 func_names.max_local_index = 1701 std::max(func_names.max_local_index, static_cast<int>(local_index)); 1702 func_names.names.emplace_back(static_cast<int>(local_index), name); 1703 } 1704 } 1705 } 1706 } 1707 1708 #undef TRACE 1709 1710 } // namespace wasm 1711 } // namespace internal 1712 } // namespace v8 1713