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

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

Issue 2636173002: [wasm] Enforce memory and table limits during instantiation. (Closed)
Patch Set: [wasm] Enforce memory and table limits during instantiation. 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 unified diff | Download patch
« no previous file with comments | « src/wasm/wasm-module.h ('k') | src/wasm/wasm-objects.h » ('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 <memory> 5 #include <memory>
6 6
7 #include "src/assembler-inl.h" 7 #include "src/assembler-inl.h"
8 #include "src/base/adapters.h" 8 #include "src/base/adapters.h"
9 #include "src/base/atomic-utils.h" 9 #include "src/base/atomic-utils.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 1651 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 module_name, import_name); 1662 module_name, import_name);
1663 return -1; 1663 return -1;
1664 } 1664 }
1665 WasmIndirectFunctionTable& table = 1665 WasmIndirectFunctionTable& table =
1666 module_->function_tables[num_imported_tables]; 1666 module_->function_tables[num_imported_tables];
1667 TableInstance& table_instance = table_instances_[num_imported_tables]; 1667 TableInstance& table_instance = table_instances_[num_imported_tables];
1668 table_instance.table_object = Handle<WasmTableObject>::cast(value); 1668 table_instance.table_object = Handle<WasmTableObject>::cast(value);
1669 table_instance.js_wrappers = Handle<FixedArray>( 1669 table_instance.js_wrappers = Handle<FixedArray>(
1670 table_instance.table_object->functions(), isolate_); 1670 table_instance.table_object->functions(), isolate_);
1671 1671
1672 // TODO(titzer): import table size must match exactly for now. 1672 int imported_cur_size = table_instance.js_wrappers->length();
1673 int table_size = table_instance.js_wrappers->length(); 1673 if (imported_cur_size < static_cast<int>(table.min_size)) {
1674 if (table_size != static_cast<int>(table.min_size)) {
1675 thrower_->LinkError( 1674 thrower_->LinkError(
1676 "table import %d is wrong size (%d), expected %u", index, 1675 "table import %d is smaller than minimum %d, got %u", index,
1677 table_size, table.min_size); 1676 table.min_size, imported_cur_size);
1678 return -1; 1677 return -1;
1679 } 1678 }
1680 1679
1680 if (table.has_max) {
1681 int64_t imported_max_size =
1682 table_instance.table_object->maximum_length();
1683 if (imported_max_size < 0) {
1684 thrower_->LinkError(
1685 "table import %d has no maximum length, expected %d", index,
1686 table.max_size);
1687 return -1;
1688 }
1689 if (imported_max_size > table.max_size) {
1690 thrower_->LinkError(
1691 "table import %d has maximum larger than maximum %d, "
1692 "got %" PRIx64,
1693 index, table.max_size, imported_max_size);
1694 return -1;
1695 }
1696 }
1697
1681 // Allocate a new dispatch table and signature table. 1698 // Allocate a new dispatch table and signature table.
1699 int table_size = imported_cur_size;
1682 table_instance.function_table = 1700 table_instance.function_table =
1683 isolate_->factory()->NewFixedArray(table_size); 1701 isolate_->factory()->NewFixedArray(table_size);
1684 table_instance.signature_table = 1702 table_instance.signature_table =
1685 isolate_->factory()->NewFixedArray(table_size); 1703 isolate_->factory()->NewFixedArray(table_size);
1686 for (int i = 0; i < table_size; ++i) { 1704 for (int i = 0; i < table_size; ++i) {
1687 table_instance.signature_table->set(i, 1705 table_instance.signature_table->set(i,
1688 Smi::FromInt(kInvalidSigIndex)); 1706 Smi::FromInt(kInvalidSigIndex));
1689 } 1707 }
1690 // Initialize the dispatch table with the (foreign) JS functions 1708 // Initialize the dispatch table with the (foreign) JS functions
1691 // that are already in the table. 1709 // that are already in the table.
(...skipping 21 matching lines...) Expand all
1713 DCHECK(!instance->has_memory_object()); 1731 DCHECK(!instance->has_memory_object());
1714 if (!WasmJs::IsWasmMemoryObject(isolate_, value)) { 1732 if (!WasmJs::IsWasmMemoryObject(isolate_, value)) {
1715 ReportLinkError("memory import must be a WebAssembly.Memory object", 1733 ReportLinkError("memory import must be a WebAssembly.Memory object",
1716 index, module_name, import_name); 1734 index, module_name, import_name);
1717 return -1; 1735 return -1;
1718 } 1736 }
1719 auto memory = Handle<WasmMemoryObject>::cast(value); 1737 auto memory = Handle<WasmMemoryObject>::cast(value);
1720 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory)); 1738 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory));
1721 instance->set_memory_object(*memory); 1739 instance->set_memory_object(*memory);
1722 memory_ = Handle<JSArrayBuffer>(memory->buffer(), isolate_); 1740 memory_ = Handle<JSArrayBuffer>(memory->buffer(), isolate_);
1741 uint32_t imported_cur_pages = static_cast<uint32_t>(
1742 memory_->byte_length()->Number() / WasmModule::kPageSize);
1743 if (imported_cur_pages < module_->min_mem_pages) {
1744 thrower_->LinkError(
1745 "memory import %d is smaller than maximum %u, got %u", index,
1746 module_->min_mem_pages, imported_cur_pages);
1747 }
1748 int32_t imported_max_pages = memory->maximum_pages();
1749 if (module_->has_max_mem) {
1750 if (imported_max_pages < 0) {
1751 thrower_->LinkError(
1752 "memory import %d has no maximum limit, expected at most %u",
1753 index, imported_max_pages);
1754 return -1;
1755 }
1756 if (static_cast<uint32_t>(imported_max_pages) >
1757 module_->max_mem_pages) {
1758 thrower_->LinkError(
1759 "memory import %d has larger maximum than maximum %u, got %d",
1760 index, module_->max_mem_pages, imported_max_pages);
1761 return -1;
1762 }
1763 }
1723 break; 1764 break;
1724 } 1765 }
1725 case kExternalGlobal: { 1766 case kExternalGlobal: {
1726 // Global imports are converted to numbers and written into the 1767 // Global imports are converted to numbers and written into the
1727 // {globals_} array buffer. 1768 // {globals_} array buffer.
1728 if (!value->IsNumber()) { 1769 if (!value->IsNumber()) {
1729 ReportLinkError("global import must be a number", index, 1770 ReportLinkError("global import must be a number", index,
1730 module_name, import_name); 1771 module_name, import_name);
1731 return -1; 1772 return -1;
1732 } 1773 }
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = 2246 MaybeHandle<JSArrayBuffer> maybe_mem_buffer =
2206 GetInstanceMemory(isolate, instance); 2247 GetInstanceMemory(isolate, instance);
2207 Handle<JSArrayBuffer> buffer; 2248 Handle<JSArrayBuffer> buffer;
2208 if (!maybe_mem_buffer.ToHandle(&buffer)) { 2249 if (!maybe_mem_buffer.ToHandle(&buffer)) {
2209 return 0; 2250 return 0;
2210 } else { 2251 } else {
2211 return buffer->byte_length()->Number() / WasmModule::kPageSize; 2252 return buffer->byte_length()->Number() / WasmModule::kPageSize;
2212 } 2253 }
2213 } 2254 }
2214 2255
2215 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, 2256 uint32_t GetMaxInstanceMemoryPages(Isolate* isolate,
2216 Handle<WasmInstanceObject> instance) { 2257 Handle<WasmInstanceObject> instance) {
2217 if (instance->has_memory_object()) { 2258 if (instance->has_memory_object()) {
2218 Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate); 2259 Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate);
2219 2260 if (memory_object->has_maximum_pages()) {
2220 int maximum = memory_object->maximum_pages(); 2261 uint32_t maximum = static_cast<uint32_t>(memory_object->maximum_pages());
2221 if (maximum > 0) return static_cast<uint32_t>(maximum); 2262 if (maximum < kV8MaxWasmMemoryPages) return maximum;
2263 }
2222 } 2264 }
2223 uint32_t compiled_max_pages = instance->compiled_module()->max_mem_pages(); 2265 uint32_t compiled_max_pages = instance->compiled_module()->max_mem_pages();
2224 isolate->counters()->wasm_max_mem_pages_count()->AddSample( 2266 isolate->counters()->wasm_max_mem_pages_count()->AddSample(
2225 compiled_max_pages); 2267 compiled_max_pages);
2226 if (compiled_max_pages != 0) return compiled_max_pages; 2268 if (compiled_max_pages != 0) return compiled_max_pages;
2227 return kV8MaxWasmMemoryPages; 2269 return kV8MaxWasmMemoryPages;
2228 } 2270 }
2229 2271
2230 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate, 2272 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
2231 MaybeHandle<JSArrayBuffer> buffer, 2273 MaybeHandle<JSArrayBuffer> buffer,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 uint32_t pages) { 2329 uint32_t pages) {
2288 DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver)); 2330 DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver));
2289 Handle<WasmMemoryObject> memory_object = 2331 Handle<WasmMemoryObject> memory_object =
2290 handle(WasmMemoryObject::cast(*receiver)); 2332 handle(WasmMemoryObject::cast(*receiver));
2291 Handle<WasmInstanceWrapper> instance_wrapper(memory_object->instances_link()); 2333 Handle<WasmInstanceWrapper> instance_wrapper(memory_object->instances_link());
2292 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); 2334 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
2293 DCHECK(instance_wrapper->has_instance()); 2335 DCHECK(instance_wrapper->has_instance());
2294 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); 2336 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
2295 DCHECK(IsWasmInstance(*instance)); 2337 DCHECK(IsWasmInstance(*instance));
2296 if (pages == 0) return GetInstanceMemorySize(isolate, instance); 2338 if (pages == 0) return GetInstanceMemorySize(isolate, instance);
2297 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); 2339 uint32_t max_pages = GetMaxInstanceMemoryPages(isolate, instance);
2298 2340
2299 // Grow memory object buffer and update instances associated with it. 2341 // Grow memory object buffer and update instances associated with it.
2300 MaybeHandle<JSArrayBuffer> memory_buffer = handle(memory_object->buffer()); 2342 MaybeHandle<JSArrayBuffer> memory_buffer = handle(memory_object->buffer());
2301 Handle<JSArrayBuffer> old_buffer; 2343 Handle<JSArrayBuffer> old_buffer;
2302 uint32_t old_size = 0; 2344 uint32_t old_size = 0;
2303 Address old_mem_start = nullptr; 2345 Address old_mem_start = nullptr;
2304 if (memory_buffer.ToHandle(&old_buffer) && 2346 if (memory_buffer.ToHandle(&old_buffer) &&
2305 old_buffer->backing_store() != nullptr) { 2347 old_buffer->backing_store() != nullptr) {
2306 old_size = old_buffer->byte_length()->Number(); 2348 old_size = old_buffer->byte_length()->Number();
2307 old_mem_start = static_cast<Address>(old_buffer->backing_store()); 2349 old_mem_start = static_cast<Address>(old_buffer->backing_store());
(...skipping 27 matching lines...) Expand all
2335 MaybeHandle<JSArrayBuffer> instance_buffer = 2377 MaybeHandle<JSArrayBuffer> instance_buffer =
2336 GetInstanceMemory(isolate, instance); 2378 GetInstanceMemory(isolate, instance);
2337 Handle<JSArrayBuffer> old_buffer; 2379 Handle<JSArrayBuffer> old_buffer;
2338 uint32_t old_size = 0; 2380 uint32_t old_size = 0;
2339 Address old_mem_start = nullptr; 2381 Address old_mem_start = nullptr;
2340 if (instance_buffer.ToHandle(&old_buffer) && 2382 if (instance_buffer.ToHandle(&old_buffer) &&
2341 old_buffer->backing_store() != nullptr) { 2383 old_buffer->backing_store() != nullptr) {
2342 old_size = old_buffer->byte_length()->Number(); 2384 old_size = old_buffer->byte_length()->Number();
2343 old_mem_start = static_cast<Address>(old_buffer->backing_store()); 2385 old_mem_start = static_cast<Address>(old_buffer->backing_store());
2344 } 2386 }
2345 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance_obj); 2387 uint32_t max_pages = GetMaxInstanceMemoryPages(isolate, instance_obj);
2346 Handle<JSArrayBuffer> buffer = 2388 Handle<JSArrayBuffer> buffer =
2347 GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages); 2389 GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages);
2348 if (buffer.is_null()) return -1; 2390 if (buffer.is_null()) return -1;
2349 SetInstanceMemory(instance, *buffer); 2391 SetInstanceMemory(instance, *buffer);
2350 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); 2392 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
2351 DCHECK(old_size % WasmModule::kPageSize == 0); 2393 DCHECK(old_size % WasmModule::kPageSize == 0);
2352 return (old_size / WasmModule::kPageSize); 2394 return (old_size / WasmModule::kPageSize);
2353 } else { 2395 } else {
2354 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()), 2396 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()),
2355 pages); 2397 pages);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2564 2606
2565 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), 2607 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(),
2566 NONE); 2608 NONE);
2567 JSObject::AddProperty(entry, kind_string, export_kind, NONE); 2609 JSObject::AddProperty(entry, kind_string, export_kind, NONE);
2568 2610
2569 storage->set(index, *entry); 2611 storage->set(index, *entry);
2570 } 2612 }
2571 2613
2572 return array_object; 2614 return array_object;
2573 } 2615 }
OLDNEW
« no previous file with comments | « src/wasm/wasm-module.h ('k') | src/wasm/wasm-objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698