OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/wasm/module-decoder.h" | 5 #include "src/wasm/module-decoder.h" |
6 | 6 |
7 #include "src/base/functional.h" | 7 #include "src/base/functional.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/flags.h" | 9 #include "src/flags.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 } while (false) | 24 } while (false) |
25 #else | 25 #else |
26 #define TRACE(...) | 26 #define TRACE(...) |
27 #endif | 27 #endif |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 const char* kNameString = "name"; | 31 const char* kNameString = "name"; |
32 const size_t kNameStringLength = 4; | 32 const size_t kNameStringLength = 4; |
33 | 33 |
34 static const uint32_t kMaxTableSize = 1 << 28; | |
35 | |
36 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { | 34 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { |
37 switch (expr.kind) { | 35 switch (expr.kind) { |
38 case WasmInitExpr::kNone: | 36 case WasmInitExpr::kNone: |
39 return kAstStmt; | 37 return kAstStmt; |
40 case WasmInitExpr::kGlobalIndex: | 38 case WasmInitExpr::kGlobalIndex: |
41 return expr.val.global_index < module->globals.size() | 39 return expr.val.global_index < module->globals.size() |
42 ? module->globals[expr.val.global_index].type | 40 ? module->globals[expr.val.global_index].type |
43 : kAstStmt; | 41 : kAstStmt; |
44 case WasmInitExpr::kI32Const: | 42 case WasmInitExpr::kI32Const: |
45 return kAstI32; | 43 return kAstI32; |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 true, // imported | 302 true, // imported |
305 false}); // exported | 303 false}); // exported |
306 WasmFunction* function = &module->functions.back(); | 304 WasmFunction* function = &module->functions.back(); |
307 function->sig_index = consume_sig_index(module, &function->sig); | 305 function->sig_index = consume_sig_index(module, &function->sig); |
308 break; | 306 break; |
309 } | 307 } |
310 case kExternalTable: { | 308 case kExternalTable: { |
311 // ===== Imported table ========================================== | 309 // ===== Imported table ========================================== |
312 import->index = | 310 import->index = |
313 static_cast<uint32_t>(module->function_tables.size()); | 311 static_cast<uint32_t>(module->function_tables.size()); |
314 module->function_tables.push_back( | 312 module->function_tables.push_back({0, 0, false, |
315 {0, 0, std::vector<int32_t>(), true, false, SignatureMap()}); | 313 std::vector<int32_t>(), true, |
| 314 false, SignatureMap()}); |
316 expect_u8("element type", kWasmAnyFunctionTypeForm); | 315 expect_u8("element type", kWasmAnyFunctionTypeForm); |
317 WasmIndirectFunctionTable* table = &module->function_tables.back(); | 316 WasmIndirectFunctionTable* table = &module->function_tables.back(); |
318 consume_resizable_limits("element count", "elements", kMaxTableSize, | 317 consume_resizable_limits( |
319 &table->size, &table->max_size); | 318 "element count", "elements", WasmModule::kV8MaxTableSize, |
| 319 &table->min_size, &table->has_max, &table->max_size); |
320 break; | 320 break; |
321 } | 321 } |
322 case kExternalMemory: { | 322 case kExternalMemory: { |
323 // ===== Imported memory ========================================= | 323 // ===== Imported memory ========================================= |
324 consume_resizable_limits( | 324 bool has_max = false; |
325 "memory", "pages", WasmModule::kMaxLegalPages, | 325 consume_resizable_limits("memory", "pages", WasmModule::kV8MaxPages, |
326 &module->min_mem_pages, &module->max_mem_pages); | 326 &module->min_mem_pages, &has_max, |
| 327 &module->max_mem_pages); |
327 break; | 328 break; |
328 } | 329 } |
329 case kExternalGlobal: { | 330 case kExternalGlobal: { |
330 // ===== Imported global ========================================= | 331 // ===== Imported global ========================================= |
331 import->index = static_cast<uint32_t>(module->globals.size()); | 332 import->index = static_cast<uint32_t>(module->globals.size()); |
332 module->globals.push_back( | 333 module->globals.push_back( |
333 {kAstStmt, false, WasmInitExpr(), 0, true, false}); | 334 {kAstStmt, false, WasmInitExpr(), 0, true, false}); |
334 WasmGlobal* global = &module->globals.back(); | 335 WasmGlobal* global = &module->globals.back(); |
335 global->type = consume_value_type(); | 336 global->type = consume_value_type(); |
336 global->mutability = consume_u8("mutability") != 0; | 337 global->mutability = consume_u8("mutability") != 0; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 369 |
369 // ===== Table section =================================================== | 370 // ===== Table section =================================================== |
370 if (section_iter.section_code() == kTableSectionCode) { | 371 if (section_iter.section_code() == kTableSectionCode) { |
371 const byte* pos = pc_; | 372 const byte* pos = pc_; |
372 uint32_t table_count = consume_u32v("table count"); | 373 uint32_t table_count = consume_u32v("table count"); |
373 // Require at most one table for now. | 374 // Require at most one table for now. |
374 if (table_count > 1) { | 375 if (table_count > 1) { |
375 error(pos, pos, "invalid table count %d, maximum 1", table_count); | 376 error(pos, pos, "invalid table count %d, maximum 1", table_count); |
376 } | 377 } |
377 if (module->function_tables.size() < 1) { | 378 if (module->function_tables.size() < 1) { |
378 module->function_tables.push_back( | 379 module->function_tables.push_back({0, 0, false, std::vector<int32_t>(), |
379 {0, 0, std::vector<int32_t>(), false, false, SignatureMap()}); | 380 false, false, SignatureMap()}); |
380 } | 381 } |
381 | 382 |
382 for (uint32_t i = 0; ok() && i < table_count; i++) { | 383 for (uint32_t i = 0; ok() && i < table_count; i++) { |
383 WasmIndirectFunctionTable* table = &module->function_tables.back(); | 384 WasmIndirectFunctionTable* table = &module->function_tables.back(); |
384 expect_u8("table type", kWasmAnyFunctionTypeForm); | 385 expect_u8("table type", kWasmAnyFunctionTypeForm); |
385 consume_resizable_limits("table elements", "elements", kMaxUInt32, | 386 consume_resizable_limits("table elements", "elements", |
386 &table->size, &table->max_size); | 387 WasmModule::kV8MaxTableSize, &table->min_size, |
| 388 &table->has_max, &table->max_size); |
387 } | 389 } |
388 section_iter.advance(); | 390 section_iter.advance(); |
389 } | 391 } |
390 | 392 |
391 // ===== Memory section ================================================== | 393 // ===== Memory section ================================================== |
392 if (section_iter.section_code() == kMemorySectionCode) { | 394 if (section_iter.section_code() == kMemorySectionCode) { |
393 const byte* pos = pc_; | 395 const byte* pos = pc_; |
394 uint32_t memory_count = consume_u32v("memory count"); | 396 uint32_t memory_count = consume_u32v("memory count"); |
395 // Require at most one memory for now. | 397 // Require at most one memory for now. |
396 if (memory_count > 1) { | 398 if (memory_count > 1) { |
397 error(pos, pos, "invalid memory count %d, maximum 1", memory_count); | 399 error(pos, pos, "invalid memory count %d, maximum 1", memory_count); |
398 } | 400 } |
399 | 401 |
400 for (uint32_t i = 0; ok() && i < memory_count; i++) { | 402 for (uint32_t i = 0; ok() && i < memory_count; i++) { |
401 consume_resizable_limits("memory", "pages", WasmModule::kMaxLegalPages, | 403 bool has_max = false; |
402 &module->min_mem_pages, | 404 consume_resizable_limits("memory", "pages", WasmModule::kV8MaxPages, |
| 405 &module->min_mem_pages, &has_max, |
403 &module->max_mem_pages); | 406 &module->max_mem_pages); |
404 } | 407 } |
405 section_iter.advance(); | 408 section_iter.advance(); |
406 } | 409 } |
407 | 410 |
408 // ===== Global section ================================================== | 411 // ===== Global section ================================================== |
409 if (section_iter.section_code() == kGlobalSectionCode) { | 412 if (section_iter.section_code() == kGlobalSectionCode) { |
410 uint32_t globals_count = consume_u32v("globals count"); | 413 uint32_t globals_count = consume_u32v("globals count"); |
411 uint32_t imported_globals = static_cast<uint32_t>(module->globals.size()); | 414 uint32_t imported_globals = static_cast<uint32_t>(module->globals.size()); |
412 if (!IsWithinLimit(std::numeric_limits<int32_t>::max(), globals_count, | 415 if (!IsWithinLimit(std::numeric_limits<int32_t>::max(), globals_count, |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 } | 617 } |
615 | 618 |
616 // ===== Remaining sections ============================================== | 619 // ===== Remaining sections ============================================== |
617 if (section_iter.more() && ok()) { | 620 if (section_iter.more() && ok()) { |
618 error(pc(), pc(), "unexpected section: %s", | 621 error(pc(), pc(), "unexpected section: %s", |
619 SectionName(section_iter.section_code())); | 622 SectionName(section_iter.section_code())); |
620 } | 623 } |
621 | 624 |
622 if (ok()) { | 625 if (ok()) { |
623 CalculateGlobalOffsets(module); | 626 CalculateGlobalOffsets(module); |
624 PreinitializeIndirectFunctionTables(module); | |
625 } | 627 } |
626 const WasmModule* finished_module = module; | 628 const WasmModule* finished_module = module; |
627 ModuleResult result = toResult(finished_module); | 629 ModuleResult result = toResult(finished_module); |
628 if (FLAG_dump_wasm_module) DumpModule(module, result); | 630 if (FLAG_dump_wasm_module) DumpModule(module, result); |
629 return result; | 631 return result; |
630 } | 632 } |
631 | 633 |
632 uint32_t SafeReserve(uint32_t count) { | 634 uint32_t SafeReserve(uint32_t count) { |
633 // Avoid OOM by only reserving up to a certain size. | 635 // Avoid OOM by only reserving up to a certain size. |
634 const uint32_t kMaxReserve = 20000; | 636 const uint32_t kMaxReserve = 20000; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 for (WasmGlobal& global : module->globals) { | 742 for (WasmGlobal& global : module->globals) { |
741 byte size = | 743 byte size = |
742 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); | 744 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); |
743 offset = (offset + size - 1) & ~(size - 1); // align | 745 offset = (offset + size - 1) & ~(size - 1); // align |
744 global.offset = offset; | 746 global.offset = offset; |
745 offset += size; | 747 offset += size; |
746 } | 748 } |
747 module->globals_size = offset; | 749 module->globals_size = offset; |
748 } | 750 } |
749 | 751 |
750 // TODO(titzer): this only works without overlapping initializations from | |
751 // global bases for entries | |
752 void PreinitializeIndirectFunctionTables(WasmModule* module) { | |
753 // Fill all tables with invalid entries first. | |
754 for (WasmIndirectFunctionTable& table : module->function_tables) { | |
755 table.values.resize(table.size); | |
756 for (size_t i = 0; i < table.size; i++) { | |
757 table.values[i] = kInvalidFunctionIndex; | |
758 } | |
759 } | |
760 for (WasmTableInit& init : module->table_inits) { | |
761 if (init.offset.kind != WasmInitExpr::kI32Const) continue; | |
762 if (init.table_index >= module->function_tables.size()) continue; | |
763 WasmIndirectFunctionTable& table = | |
764 module->function_tables[init.table_index]; | |
765 for (size_t i = 0; i < init.entries.size(); i++) { | |
766 size_t index = i + init.offset.val.i32_const; | |
767 if (index < table.values.size()) { | |
768 table.values[index] = init.entries[i]; | |
769 } | |
770 } | |
771 } | |
772 } | |
773 | |
774 // Verifies the body (code) of a given function. | 752 // Verifies the body (code) of a given function. |
775 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, | 753 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, |
776 WasmFunction* function) { | 754 WasmFunction* function) { |
777 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { | 755 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { |
778 OFStream os(stdout); | 756 OFStream os(stdout); |
779 os << "Verifying WASM function " << WasmFunctionName(function, menv) | 757 os << "Verifying WASM function " << WasmFunctionName(function, menv) |
780 << std::endl; | 758 << std::endl; |
781 } | 759 } |
782 FunctionBody body = {menv, function->sig, start_, | 760 FunctionBody body = {menv, function->sig, start_, |
783 start_ + function->code_start_offset, | 761 start_ + function->code_start_offset, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 static_cast<int>(vector.size())); | 835 static_cast<int>(vector.size())); |
858 *ptr = nullptr; | 836 *ptr = nullptr; |
859 return 0; | 837 return 0; |
860 } | 838 } |
861 *ptr = &vector[index]; | 839 *ptr = &vector[index]; |
862 return index; | 840 return index; |
863 } | 841 } |
864 | 842 |
865 void consume_resizable_limits(const char* name, const char* units, | 843 void consume_resizable_limits(const char* name, const char* units, |
866 uint32_t max_value, uint32_t* initial, | 844 uint32_t max_value, uint32_t* initial, |
867 uint32_t* maximum) { | 845 bool* has_max, uint32_t* maximum) { |
868 uint32_t flags = consume_u32v("resizable limits flags"); | 846 uint32_t flags = consume_u32v("resizable limits flags"); |
869 const byte* pos = pc(); | 847 const byte* pos = pc(); |
870 *initial = consume_u32v("initial size"); | 848 *initial = consume_u32v("initial size"); |
| 849 *has_max = false; |
871 if (*initial > max_value) { | 850 if (*initial > max_value) { |
872 error(pos, pos, | 851 error(pos, pos, |
873 "initial %s size (%u %s) is larger than maximum allowable (%u)", | 852 "initial %s size (%u %s) is larger than implementation limit (%u)", |
874 name, *initial, units, max_value); | 853 name, *initial, units, max_value); |
875 } | 854 } |
876 if (flags & 1) { | 855 if (flags & 1) { |
| 856 *has_max = true; |
877 pos = pc(); | 857 pos = pc(); |
878 *maximum = consume_u32v("maximum size"); | 858 *maximum = consume_u32v("maximum size"); |
879 if (*maximum > max_value) { | 859 if (*maximum > max_value) { |
880 error(pos, pos, | 860 error( |
881 "maximum %s size (%u %s) is larger than maximum allowable (%u)", | 861 pos, pos, |
882 name, *maximum, units, max_value); | 862 "maximum %s size (%u %s) is larger than implementation limit (%u)", |
| 863 name, *maximum, units, max_value); |
883 } | 864 } |
884 if (*maximum < *initial) { | 865 if (*maximum < *initial) { |
885 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", | 866 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", |
886 name, *maximum, units, *initial, units); | 867 name, *maximum, units, *initial, units); |
887 } | 868 } |
888 } else { | 869 } else { |
889 *maximum = 0; | 870 *has_max = false; |
| 871 *maximum = max_value; |
890 } | 872 } |
891 } | 873 } |
892 | 874 |
893 bool expect_u8(const char* name, uint8_t expected) { | 875 bool expect_u8(const char* name, uint8_t expected) { |
894 const byte* pos = pc(); | 876 const byte* pos = pc(); |
895 uint8_t value = consume_u8(name); | 877 uint8_t value = consume_u8(name); |
896 if (value != expected) { | 878 if (value != expected) { |
897 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); | 879 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); |
898 return false; | 880 return false; |
899 } | 881 } |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 table.push_back(std::move(func_asm_offsets)); | 1194 table.push_back(std::move(func_asm_offsets)); |
1213 } | 1195 } |
1214 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1196 if (decoder.more()) decoder.error("unexpected additional bytes"); |
1215 | 1197 |
1216 return decoder.toResult(std::move(table)); | 1198 return decoder.toResult(std::move(table)); |
1217 } | 1199 } |
1218 | 1200 |
1219 } // namespace wasm | 1201 } // namespace wasm |
1220 } // namespace internal | 1202 } // namespace internal |
1221 } // namespace v8 | 1203 } // namespace v8 |
OLD | NEW |