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 |
34 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { | 36 LocalType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { |
35 switch (expr.kind) { | 37 switch (expr.kind) { |
36 case WasmInitExpr::kNone: | 38 case WasmInitExpr::kNone: |
37 return kAstStmt; | 39 return kAstStmt; |
38 case WasmInitExpr::kGlobalIndex: | 40 case WasmInitExpr::kGlobalIndex: |
39 return expr.val.global_index < module->globals.size() | 41 return expr.val.global_index < module->globals.size() |
40 ? module->globals[expr.val.global_index].type | 42 ? module->globals[expr.val.global_index].type |
41 : kAstStmt; | 43 : kAstStmt; |
42 case WasmInitExpr::kI32Const: | 44 case WasmInitExpr::kI32Const: |
43 return kAstI32; | 45 return kAstI32; |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 true, // imported | 304 true, // imported |
303 false}); // exported | 305 false}); // exported |
304 WasmFunction* function = &module->functions.back(); | 306 WasmFunction* function = &module->functions.back(); |
305 function->sig_index = consume_sig_index(module, &function->sig); | 307 function->sig_index = consume_sig_index(module, &function->sig); |
306 break; | 308 break; |
307 } | 309 } |
308 case kExternalTable: { | 310 case kExternalTable: { |
309 // ===== Imported table ========================================== | 311 // ===== Imported table ========================================== |
310 import->index = | 312 import->index = |
311 static_cast<uint32_t>(module->function_tables.size()); | 313 static_cast<uint32_t>(module->function_tables.size()); |
312 module->function_tables.push_back({0, 0, false, | 314 module->function_tables.push_back( |
313 std::vector<int32_t>(), true, | 315 {0, 0, std::vector<int32_t>(), true, false, SignatureMap()}); |
314 false, SignatureMap()}); | |
315 expect_u8("element type", kWasmAnyFunctionTypeForm); | 316 expect_u8("element type", kWasmAnyFunctionTypeForm); |
316 WasmIndirectFunctionTable* table = &module->function_tables.back(); | 317 WasmIndirectFunctionTable* table = &module->function_tables.back(); |
317 consume_resizable_limits( | 318 consume_resizable_limits("element count", "elements", kMaxTableSize, |
318 "element count", "elements", WasmModule::kV8MaxTableSize, | 319 &table->size, &table->max_size); |
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 bool has_max = false; | 324 consume_resizable_limits( |
325 consume_resizable_limits("memory", "pages", WasmModule::kV8MaxPages, | 325 "memory", "pages", WasmModule::kMaxLegalPages, |
326 &module->min_mem_pages, &has_max, | 326 &module->min_mem_pages, &module->max_mem_pages); |
327 &module->max_mem_pages); | |
328 break; | 327 break; |
329 } | 328 } |
330 case kExternalGlobal: { | 329 case kExternalGlobal: { |
331 // ===== Imported global ========================================= | 330 // ===== Imported global ========================================= |
332 import->index = static_cast<uint32_t>(module->globals.size()); | 331 import->index = static_cast<uint32_t>(module->globals.size()); |
333 module->globals.push_back( | 332 module->globals.push_back( |
334 {kAstStmt, false, WasmInitExpr(), 0, true, false}); | 333 {kAstStmt, false, WasmInitExpr(), 0, true, false}); |
335 WasmGlobal* global = &module->globals.back(); | 334 WasmGlobal* global = &module->globals.back(); |
336 global->type = consume_value_type(); | 335 global->type = consume_value_type(); |
337 global->mutability = consume_u8("mutability") != 0; | 336 global->mutability = consume_u8("mutability") != 0; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 | 368 |
370 // ===== Table section =================================================== | 369 // ===== Table section =================================================== |
371 if (section_iter.section_code() == kTableSectionCode) { | 370 if (section_iter.section_code() == kTableSectionCode) { |
372 const byte* pos = pc_; | 371 const byte* pos = pc_; |
373 uint32_t table_count = consume_u32v("table count"); | 372 uint32_t table_count = consume_u32v("table count"); |
374 // Require at most one table for now. | 373 // Require at most one table for now. |
375 if (table_count > 1) { | 374 if (table_count > 1) { |
376 error(pos, pos, "invalid table count %d, maximum 1", table_count); | 375 error(pos, pos, "invalid table count %d, maximum 1", table_count); |
377 } | 376 } |
378 if (module->function_tables.size() < 1) { | 377 if (module->function_tables.size() < 1) { |
379 module->function_tables.push_back({0, 0, false, std::vector<int32_t>(), | 378 module->function_tables.push_back( |
380 false, false, SignatureMap()}); | 379 {0, 0, std::vector<int32_t>(), false, false, SignatureMap()}); |
381 } | 380 } |
382 | 381 |
383 for (uint32_t i = 0; ok() && i < table_count; i++) { | 382 for (uint32_t i = 0; ok() && i < table_count; i++) { |
384 WasmIndirectFunctionTable* table = &module->function_tables.back(); | 383 WasmIndirectFunctionTable* table = &module->function_tables.back(); |
385 expect_u8("table type", kWasmAnyFunctionTypeForm); | 384 expect_u8("table type", kWasmAnyFunctionTypeForm); |
386 consume_resizable_limits("table elements", "elements", | 385 consume_resizable_limits("table elements", "elements", kMaxUInt32, |
387 WasmModule::kV8MaxTableSize, &table->min_size, | 386 &table->size, &table->max_size); |
388 &table->has_max, &table->max_size); | |
389 } | 387 } |
390 section_iter.advance(); | 388 section_iter.advance(); |
391 } | 389 } |
392 | 390 |
393 // ===== Memory section ================================================== | 391 // ===== Memory section ================================================== |
394 if (section_iter.section_code() == kMemorySectionCode) { | 392 if (section_iter.section_code() == kMemorySectionCode) { |
395 const byte* pos = pc_; | 393 const byte* pos = pc_; |
396 uint32_t memory_count = consume_u32v("memory count"); | 394 uint32_t memory_count = consume_u32v("memory count"); |
397 // Require at most one memory for now. | 395 // Require at most one memory for now. |
398 if (memory_count > 1) { | 396 if (memory_count > 1) { |
399 error(pos, pos, "invalid memory count %d, maximum 1", memory_count); | 397 error(pos, pos, "invalid memory count %d, maximum 1", memory_count); |
400 } | 398 } |
401 | 399 |
402 for (uint32_t i = 0; ok() && i < memory_count; i++) { | 400 for (uint32_t i = 0; ok() && i < memory_count; i++) { |
403 bool has_max = false; | 401 consume_resizable_limits("memory", "pages", WasmModule::kMaxLegalPages, |
404 consume_resizable_limits("memory", "pages", WasmModule::kV8MaxPages, | 402 &module->min_mem_pages, |
405 &module->min_mem_pages, &has_max, | |
406 &module->max_mem_pages); | 403 &module->max_mem_pages); |
407 } | 404 } |
408 section_iter.advance(); | 405 section_iter.advance(); |
409 } | 406 } |
410 | 407 |
411 // ===== Global section ================================================== | 408 // ===== Global section ================================================== |
412 if (section_iter.section_code() == kGlobalSectionCode) { | 409 if (section_iter.section_code() == kGlobalSectionCode) { |
413 uint32_t globals_count = consume_u32v("globals count"); | 410 uint32_t globals_count = consume_u32v("globals count"); |
414 uint32_t imported_globals = static_cast<uint32_t>(module->globals.size()); | 411 uint32_t imported_globals = static_cast<uint32_t>(module->globals.size()); |
415 if (!IsWithinLimit(std::numeric_limits<int32_t>::max(), globals_count, | 412 if (!IsWithinLimit(std::numeric_limits<int32_t>::max(), globals_count, |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 } | 616 } |
620 | 617 |
621 // ===== Remaining sections ============================================== | 618 // ===== Remaining sections ============================================== |
622 if (section_iter.more() && ok()) { | 619 if (section_iter.more() && ok()) { |
623 error(pc(), pc(), "unexpected section: %s", | 620 error(pc(), pc(), "unexpected section: %s", |
624 SectionName(section_iter.section_code())); | 621 SectionName(section_iter.section_code())); |
625 } | 622 } |
626 | 623 |
627 if (ok()) { | 624 if (ok()) { |
628 CalculateGlobalOffsets(module); | 625 CalculateGlobalOffsets(module); |
| 626 PreinitializeIndirectFunctionTables(module); |
629 } | 627 } |
630 const WasmModule* finished_module = module; | 628 const WasmModule* finished_module = module; |
631 ModuleResult result = toResult(finished_module); | 629 ModuleResult result = toResult(finished_module); |
632 if (FLAG_dump_wasm_module) DumpModule(module, result); | 630 if (FLAG_dump_wasm_module) DumpModule(module, result); |
633 return result; | 631 return result; |
634 } | 632 } |
635 | 633 |
636 uint32_t SafeReserve(uint32_t count) { | 634 uint32_t SafeReserve(uint32_t count) { |
637 // Avoid OOM by only reserving up to a certain size. | 635 // Avoid OOM by only reserving up to a certain size. |
638 const uint32_t kMaxReserve = 20000; | 636 const uint32_t kMaxReserve = 20000; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 for (WasmGlobal& global : module->globals) { | 742 for (WasmGlobal& global : module->globals) { |
745 byte size = | 743 byte size = |
746 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); | 744 WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type)); |
747 offset = (offset + size - 1) & ~(size - 1); // align | 745 offset = (offset + size - 1) & ~(size - 1); // align |
748 global.offset = offset; | 746 global.offset = offset; |
749 offset += size; | 747 offset += size; |
750 } | 748 } |
751 module->globals_size = offset; | 749 module->globals_size = offset; |
752 } | 750 } |
753 | 751 |
| 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 |
754 // Verifies the body (code) of a given function. | 776 // Verifies the body (code) of a given function. |
755 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, | 777 void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv, |
756 WasmFunction* function) { | 778 WasmFunction* function) { |
757 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { | 779 if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) { |
758 OFStream os(stdout); | 780 OFStream os(stdout); |
759 os << "Verifying WASM function " << WasmFunctionName(function, menv) | 781 os << "Verifying WASM function " << WasmFunctionName(function, menv) |
760 << std::endl; | 782 << std::endl; |
761 } | 783 } |
762 FunctionBody body = {menv, function->sig, start_, | 784 FunctionBody body = {menv, function->sig, start_, |
763 start_ + function->code_start_offset, | 785 start_ + function->code_start_offset, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 static_cast<int>(vector.size())); | 859 static_cast<int>(vector.size())); |
838 *ptr = nullptr; | 860 *ptr = nullptr; |
839 return 0; | 861 return 0; |
840 } | 862 } |
841 *ptr = &vector[index]; | 863 *ptr = &vector[index]; |
842 return index; | 864 return index; |
843 } | 865 } |
844 | 866 |
845 void consume_resizable_limits(const char* name, const char* units, | 867 void consume_resizable_limits(const char* name, const char* units, |
846 uint32_t max_value, uint32_t* initial, | 868 uint32_t max_value, uint32_t* initial, |
847 bool* has_max, uint32_t* maximum) { | 869 uint32_t* maximum) { |
848 uint32_t flags = consume_u32v("resizable limits flags"); | 870 uint32_t flags = consume_u32v("resizable limits flags"); |
849 const byte* pos = pc(); | 871 const byte* pos = pc(); |
850 *initial = consume_u32v("initial size"); | 872 *initial = consume_u32v("initial size"); |
851 *has_max = false; | |
852 if (*initial > max_value) { | 873 if (*initial > max_value) { |
853 error(pos, pos, | 874 error(pos, pos, |
854 "initial %s size (%u %s) is larger than implementation limit (%u)", | 875 "initial %s size (%u %s) is larger than maximum allowable (%u)", |
855 name, *initial, units, max_value); | 876 name, *initial, units, max_value); |
856 } | 877 } |
857 if (flags & 1) { | 878 if (flags & 1) { |
858 *has_max = true; | |
859 pos = pc(); | 879 pos = pc(); |
860 *maximum = consume_u32v("maximum size"); | 880 *maximum = consume_u32v("maximum size"); |
861 if (*maximum > max_value) { | 881 if (*maximum > max_value) { |
862 error( | 882 error(pos, pos, |
863 pos, pos, | 883 "maximum %s size (%u %s) is larger than maximum allowable (%u)", |
864 "maximum %s size (%u %s) is larger than implementation limit (%u)", | 884 name, *maximum, units, max_value); |
865 name, *maximum, units, max_value); | |
866 } | 885 } |
867 if (*maximum < *initial) { | 886 if (*maximum < *initial) { |
868 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", | 887 error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", |
869 name, *maximum, units, *initial, units); | 888 name, *maximum, units, *initial, units); |
870 } | 889 } |
871 } else { | 890 } else { |
872 *has_max = false; | 891 *maximum = 0; |
873 *maximum = max_value; | |
874 } | 892 } |
875 } | 893 } |
876 | 894 |
877 bool expect_u8(const char* name, uint8_t expected) { | 895 bool expect_u8(const char* name, uint8_t expected) { |
878 const byte* pos = pc(); | 896 const byte* pos = pc(); |
879 uint8_t value = consume_u8(name); | 897 uint8_t value = consume_u8(name); |
880 if (value != expected) { | 898 if (value != expected) { |
881 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); | 899 error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); |
882 return false; | 900 return false; |
883 } | 901 } |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 table.push_back(std::move(func_asm_offsets)); | 1214 table.push_back(std::move(func_asm_offsets)); |
1197 } | 1215 } |
1198 if (decoder.more()) decoder.error("unexpected additional bytes"); | 1216 if (decoder.more()) decoder.error("unexpected additional bytes"); |
1199 | 1217 |
1200 return decoder.toResult(std::move(table)); | 1218 return decoder.toResult(std::move(table)); |
1201 } | 1219 } |
1202 | 1220 |
1203 } // namespace wasm | 1221 } // namespace wasm |
1204 } // namespace internal | 1222 } // namespace internal |
1205 } // namespace v8 | 1223 } // namespace v8 |
OLD | NEW |