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

Unified Diff: src/wasm/wasm-module.cc

Issue 2649553002: [wasm] Check segment bounds beforehand (Closed)
Patch Set: Rebase Created 3 years, 11 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/wasm/wasm-js.cc ('k') | test/cctest/wasm/test-run-wasm-module.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/wasm-module.cc
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc
index a36a9685011f9c957c806ab3a6d846f19f27b025..646b6dc797d75d0f54806e20eeae61fcbfdeaaa0 100644
--- a/src/wasm/wasm-module.cc
+++ b/src/wasm/wasm-module.cc
@@ -1274,6 +1274,11 @@ class WasmInstanceBuilder {
InitGlobals();
//--------------------------------------------------------------------------
+ // Set up the indirect function tables for the new instance.
+ //--------------------------------------------------------------------------
+ if (function_table_count > 0) InitializeTables(code_table, instance);
+
+ //--------------------------------------------------------------------------
// Set up the memory for the new instance.
//--------------------------------------------------------------------------
MaybeHandle<JSArrayBuffer> old_memory;
@@ -1292,12 +1297,43 @@ class WasmInstanceBuilder {
if (memory_.is_null()) return nothing; // failed to allocate memory
}
+ //--------------------------------------------------------------------------
+ // Check that indirect function table segments are within bounds.
+ //--------------------------------------------------------------------------
+ for (WasmTableInit& table_init : module_->table_inits) {
+ DCHECK(table_init.table_index < table_instances_.size());
+ uint32_t base = EvalUint32InitExpr(table_init.offset);
+ uint32_t table_size =
+ table_instances_[table_init.table_index].function_table->length();
+ if (!in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
+ table_size)) {
+ thrower_->LinkError("table initializer is out of bounds");
+ return nothing;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Check that memory segments are within bounds.
+ //--------------------------------------------------------------------------
+ for (WasmDataSegment& seg : module_->data_segments) {
+ uint32_t base = EvalUint32InitExpr(seg.dest_addr);
+ uint32_t mem_size = memory_.is_null()
+ ? 0 : static_cast<uint32_t>(memory_->byte_length()->Number());
+ if (!in_bounds(base, seg.source_size, mem_size)) {
+ thrower_->LinkError("data segment is out of bounds");
+ return nothing;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // Initialize memory.
+ //--------------------------------------------------------------------------
if (!memory_.is_null()) {
instance->set_memory_buffer(*memory_);
Address mem_start = static_cast<Address>(memory_->backing_store());
uint32_t mem_size =
static_cast<uint32_t>(memory_->byte_length()->Number());
- if (!LoadDataSegments(mem_start, mem_size)) return nothing;
+ LoadDataSegments(mem_start, mem_size);
uint32_t old_mem_size = compiled_module_->mem_size();
Address old_mem_start =
@@ -1308,8 +1344,6 @@ class WasmInstanceBuilder {
RelocateMemoryReferencesInCode(code_table, old_mem_start, mem_start,
old_mem_size, mem_size);
compiled_module_->set_memory(memory_);
- } else {
- if (!LoadDataSegments(nullptr, 0)) return nothing;
}
//--------------------------------------------------------------------------
@@ -1343,9 +1377,9 @@ class WasmInstanceBuilder {
}
//--------------------------------------------------------------------------
- // Set up the indirect function tables for the new instance.
+ // Initialize the indirect function tables.
//--------------------------------------------------------------------------
- if (function_table_count > 0) InitializeTables(code_table, instance);
+ if (function_table_count > 0) LoadTableSegments(code_table, instance);
// Patch new call sites and the context.
PatchDirectCallsAndContext(code_table, compiled_module_, module_,
@@ -1548,8 +1582,12 @@ class WasmInstanceBuilder {
}
}
+ bool in_bounds(uint32_t offset, uint32_t size, uint32_t upper) {
+ return offset + size <= upper && offset + size >= offset;
+ }
+
// Load data segments into the memory.
- bool LoadDataSegments(Address mem_addr, size_t mem_size) {
+ void LoadDataSegments(Address mem_addr, size_t mem_size) {
Handle<SeqOneByteString> module_bytes(compiled_module_->module_bytes(),
isolate_);
for (const WasmDataSegment& segment : module_->data_segments) {
@@ -1557,19 +1595,13 @@ class WasmInstanceBuilder {
// Segments of size == 0 are just nops.
if (source_size == 0) continue;
uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr);
- if (dest_offset + source_size > mem_size ||
- dest_offset + source_size < dest_offset) {
- thrower_->LinkError("data segment (start = %" PRIu32 ", size = %" PRIu32
- ") does not fit into memory (size = %" PRIuS ")",
- dest_offset, source_size, mem_size);
- return false;
- }
+ DCHECK(in_bounds(dest_offset, source_size,
+ static_cast<uint32_t>(mem_size)));
byte* dest = mem_addr + dest_offset;
const byte* src = reinterpret_cast<const byte*>(
module_bytes->GetCharsAddress() + segment.source_offset);
memcpy(dest, src, source_size);
}
- return true;
}
void WriteGlobalValue(WasmGlobal& global, Handle<Object> value) {
@@ -2033,10 +2065,6 @@ class WasmInstanceBuilder {
void InitializeTables(Handle<FixedArray> code_table,
Handle<WasmInstanceObject> instance) {
- Handle<FixedArray> old_function_tables =
- compiled_module_->function_tables();
- Handle<FixedArray> old_signature_tables =
- compiled_module_->signature_tables();
int function_table_count =
static_cast<int>(module_->function_tables.size());
Handle<FixedArray> new_function_tables =
@@ -2066,6 +2094,36 @@ class WasmInstanceBuilder {
*table_instance.function_table);
new_signature_tables->set(static_cast<int>(index),
*table_instance.signature_table);
+ }
+
+ // Patch all code that has references to the old indirect tables.
+ Handle<FixedArray> old_function_tables =
+ compiled_module_->function_tables();
+ Handle<FixedArray> old_signature_tables =
+ compiled_module_->signature_tables();
+ for (int i = 0; i < code_table->length(); ++i) {
+ if (!code_table->get(i)->IsCode()) continue;
+ Handle<Code> code(Code::cast(code_table->get(i)), isolate_);
+ for (int j = 0; j < function_table_count; ++j) {
+ ReplaceReferenceInCode(
+ code, Handle<Object>(old_function_tables->get(j), isolate_),
+ Handle<Object>(new_function_tables->get(j), isolate_));
+ ReplaceReferenceInCode(
+ code, Handle<Object>(old_signature_tables->get(j), isolate_),
+ Handle<Object>(new_signature_tables->get(j), isolate_));
+ }
+ }
+ compiled_module_->set_function_tables(new_function_tables);
+ compiled_module_->set_signature_tables(new_signature_tables);
+ }
+
+ void LoadTableSegments(Handle<FixedArray> code_table,
+ Handle<WasmInstanceObject> instance) {
+ int function_table_count =
+ static_cast<int>(module_->function_tables.size());
+ for (int index = 0; index < function_table_count; ++index) {
+ WasmIndirectFunctionTable& table = module_->function_tables[index];
+ TableInstance& table_instance = table_instances_[index];
Handle<FixedArray> all_dispatch_tables;
if (!table_instance.table_object.is_null()) {
@@ -2080,12 +2138,8 @@ class WasmInstanceBuilder {
// since initializations are not sorted by table index.
for (auto table_init : module_->table_inits) {
uint32_t base = EvalUint32InitExpr(table_init.offset);
- if (base > static_cast<uint32_t>(table_size) ||
- (base + table_init.entries.size() >
- static_cast<uint32_t>(table_size))) {
- thrower_->LinkError("table initializer is out of bounds");
- continue;
- }
+ DCHECK(in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
+ table_instance.function_table->length()));
for (int i = 0; i < static_cast<int>(table_init.entries.size()); ++i) {
uint32_t func_index = table_init.entries[i];
WasmFunction* function = &module_->functions[func_index];
@@ -2148,21 +2202,6 @@ class WasmInstanceBuilder {
table_instance.function_table, table_instance.signature_table);
}
}
- // Patch all code that has references to the old indirect tables.
- for (int i = 0; i < code_table->length(); ++i) {
- if (!code_table->get(i)->IsCode()) continue;
- Handle<Code> code(Code::cast(code_table->get(i)), isolate_);
- for (int j = 0; j < function_table_count; ++j) {
- ReplaceReferenceInCode(
- code, Handle<Object>(old_function_tables->get(j), isolate_),
- Handle<Object>(new_function_tables->get(j), isolate_));
- ReplaceReferenceInCode(
- code, Handle<Object>(old_signature_tables->get(j), isolate_),
- Handle<Object>(new_signature_tables->get(j), isolate_));
- }
- }
- compiled_module_->set_function_tables(new_function_tables);
- compiled_module_->set_signature_tables(new_signature_tables);
}
};
« no previous file with comments | « src/wasm/wasm-js.cc ('k') | test/cctest/wasm/test-run-wasm-module.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698