Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(386)

Side by Side Diff: src/wasm/module-decoder.cc

Issue 2454503005: [wasm] Support for restricted table imports. (Closed)
Patch Set: Fix GC stress issue; tables weren't being reset correctly Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/wasm-compiler.cc ('k') | src/wasm/wasm-interpreter.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.cc ('k') | src/wasm/wasm-interpreter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698