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

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

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

Powered by Google App Engine
This is Rietveld 408576698