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 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 619 } |
617 | 620 |
618 // ===== Remaining sections ============================================== | 621 // ===== Remaining sections ============================================== |
619 if (section_iter.more() && ok()) { | 622 if (section_iter.more() && ok()) { |
620 error(pc(), pc(), "unexpected section: %s", | 623 error(pc(), pc(), "unexpected section: %s", |
621 SectionName(section_iter.section_code())); | 624 SectionName(section_iter.section_code())); |
622 } | 625 } |
623 | 626 |
624 if (ok()) { | 627 if (ok()) { |
625 CalculateGlobalOffsets(module); | 628 CalculateGlobalOffsets(module); |
626 PreinitializeIndirectFunctionTables(module); | |
627 } | 629 } |
628 const WasmModule* finished_module = module; | 630 const WasmModule* finished_module = module; |
629 ModuleResult result = toResult(finished_module); | 631 ModuleResult result = toResult(finished_module); |
630 if (FLAG_dump_wasm_module) DumpModule(module, result); | 632 if (FLAG_dump_wasm_module) DumpModule(module, result); |
631 return result; | 633 return result; |
632 } | 634 } |
633 | 635 |
634 uint32_t SafeReserve(uint32_t count) { | 636 uint32_t SafeReserve(uint32_t count) { |
635 // Avoid OOM by only reserving up to a certain size. | 637 // Avoid OOM by only reserving up to a certain size. |
636 const uint32_t kMaxReserve = 20000; | 638 const uint32_t kMaxReserve = 20000; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 for (WasmGlobal& global : module->globals) { | 744 for (WasmGlobal& global : module->globals) { |
743 byte size = | 745 byte size = |
744 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); | 746 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); |
745 offset = (offset + size - 1) & ~(size - 1); // align | 747 offset = (offset + size - 1) & ~(size - 1); // align |
746 global.offset = offset; | 748 global.offset = offset; |
747 offset += size; | 749 offset += size; |
748 } | 750 } |
749 module->globals_size = offset; | 751 module->globals_size = offset; |
750 } | 752 } |
751 | 753 |
752 // TODO(titzer): this only works without overlapping initializations from | |
753 // global bases for entries | |
754 void PreinitializeIndirectFunctionTables(WasmModule* module) { | |
755 // Fill all tables with invalid entries first. | |
756 for (WasmIndirectFunctionTable& table : module->function_tables) { | |
757 table.values.resize(table.size); | |
758 for (size_t i = 0; i < table.size; i++) { | |
759 table.values[i] = kInvalidFunctionIndex; | |
760 } | |
761 } | |
762 for (WasmTableInit& init : module->table_inits) { | |
763 if (init.offset.kind != WasmInitExpr::kI32Const) continue; | |
764 if (init.table_index >= module->function_tables.size()) continue; | |
765 WasmIndirectFunctionTable& table = | |
766 module->function_tables[init.table_index]; | |
767 for (size_t i = 0; i < init.entries.size(); i++) { | |
768 size_t index = i + init.offset.val.i32_const; | |
769 if (index < table.values.size()) { | |
770 table.values[index] = init.entries[i]; | |
771 } | |
772 } | |
773 } | |
774 } | |
775 | |
776 // Verifies the body (code) of a given function. | 754 // Verifies the body (code) of a given function. |
777 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, | 755 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, |
778 WasmFunction* function) { | 756 WasmFunction* function) { |
779 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { | 757 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { |
780 OFStream os(stdout); | 758 OFStream os(stdout); |
781 os << "Verifying WASM function " << WasmFunctionName(function, menv) | 759 os << "Verifying WASM function " << WasmFunctionName(function, menv) |
782 << std::endl; | 760 << std::endl; |
783 } | 761 } |
784 FunctionBody body = {menv, function->sig, start_, | 762 FunctionBody body = {menv, function->sig, start_, |
785 start_ + function->code_start_offset, | 763 start_ + function->code_start_offset, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 static_cast<int>(vector.size())); | 837 static_cast<int>(vector.size())); |
860 *ptr = nullptr; | 838 *ptr = nullptr; |
861 return 0; | 839 return 0; |
862 } | 840 } |
863 *ptr = &vector[index]; | 841 *ptr = &vector[index]; |
864 return index; | 842 return index; |
865 } | 843 } |
866 | 844 |
867 void consume_resizable_limits(const char* name, const char* units, | 845 void consume_resizable_limits(const char* name, const char* units, |
868 uint32_t max_value, uint32_t* initial, | 846 uint32_t max_value, uint32_t* initial, |
869 uint32_t* maximum) { | 847 bool* has_max, uint32_t* maximum) { |
870 uint32_t flags = consume_u32v("resizable limits flags"); | 848 uint32_t flags = consume_u32v("resizable limits flags"); |
871 const byte* pos = pc(); | 849 const byte* pos = pc(); |
872 *initial = consume_u32v("initial size"); | 850 *initial = consume_u32v("initial size"); |
| 851 *has_max = false; |
873 if (*initial > max_value) { | 852 if (*initial > max_value) { |
874 error(pos, pos, | 853 error(pos, pos, |
875 "initial %s size (%u %s) is larger than maximum allowable (%u)", | 854 "initial %s size (%u %s) is larger than implementation limit (%u)", |
876 name, *initial, units, max_value); | 855 name, *initial, units, max_value); |
877 } | 856 } |
878 if (flags & 1) { | 857 if (flags & 1) { |
| 858 *has_max = true; |
879 pos = pc(); | 859 pos = pc(); |
880 *maximum = consume_u32v("maximum size"); | 860 *maximum = consume_u32v("maximum size"); |
881 if (*maximum > max_value) { | 861 if (*maximum > max_value) { |
882 error(pos, pos, | 862 error( |
883 "maximum %s size (%u %s) is larger than maximum allowable (%u)", | 863 pos, pos, |
884 name, *maximum, units, max_value); | 864 "maximum %s size (%u %s) is larger than implementation limit (%u)", |
| 865 name, *maximum, units, max_value); |
885 } | 866 } |
886 if (*maximum < *initial) { | 867 if (*maximum < *initial) { |
887 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", | 868 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", |
888 name, *maximum, units, *initial, units); | 869 name, *maximum, units, *initial, units); |
889 } | 870 } |
890 } else { | 871 } else { |
891 *maximum = 0; | 872 *has_max = false; |
| 873 *maximum = max_value; |
892 } | 874 } |
893 } | 875 } |
894 | 876 |
895 bool expect_u8(const char* name, uint8_t expected) { | 877 bool expect_u8(const char* name, uint8_t expected) { |
896 const byte* pos = pc(); | 878 const byte* pos = pc(); |
897 uint8_t value = consume_u8(name); | 879 uint8_t value = consume_u8(name); |
898 if (value != expected) { | 880 if (value != expected) { |
899 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); | 881 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); |
900 return false; | 882 return false; |
901 } | 883 } |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 table.push_back(std::move(func_asm_offsets)); | 1196 table.push_back(std::move(func_asm_offsets)); |
1215 } | 1197 } |
1216 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1198 if (decoder.more()) decoder.error("unexpected additional bytes"); |
1217 | 1199 |
1218 return decoder.toResult(std::move(table)); | 1200 return decoder.toResult(std::move(table)); |
1219 } | 1201 } |
1220 | 1202 |
1221 } // namespace wasm | 1203 } // namespace wasm |
1222 } // namespace internal | 1204 } // namespace internal |
1223 } // namespace v8 | 1205 } // namespace v8 |
OLD | NEW |