Skip to content
Permalink
Browse files

[wasm] Fix Memory.grow when shared with asm.js modules

If the buffer associated with WebAssembly.Memory is used as memory
for asm.js modules, throw a range error on Memory.Grow.

Bug: chromium:776677
Change-Id: Iebcd7797fa7724002dd8073d1dbaeb98f080d316
Reviewed-on: https://chromium-review.googlesource.com/731844
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Reviewed-by: Brad Nelson <bradnelson@chromium.org>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48837}
  • Loading branch information...
dtig authored and Commit Bot committed Oct 23, 2017
1 parent 5814125 commit 5f960dfc06a7c95af69e2b09f772b2280168469b
@@ -374,6 +374,7 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate,
ReportInstantiationFailure(script, position, "Requires heap buffer");
return MaybeHandle<Object>();
}
memory->set_is_growable(false);
size_t size = NumberToSize(memory->byte_length());
// TODO(mstarzinger): We currently only limit byte length of the buffer to
// be a multiple of 8, we should enforce the stricter spec limits here.
@@ -984,7 +984,7 @@ void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) { // NOLINT
if (was_neutered()) os << "\n - neutered";
if (is_shared()) os << "\n - shared";
if (has_guard_region()) os << "\n - has_guard_region";
if (is_wasm_buffer()) os << "\n - wasm_buffer";
if (is_growable()) os << "\n - growable";
JSObjectPrintBody(os, this, !was_neutered());
}

@@ -151,12 +151,10 @@ void JSArrayBuffer::set_has_guard_region(bool value) {
set_bit_field(HasGuardRegion::update(bit_field(), value));
}

bool JSArrayBuffer::is_wasm_buffer() {
return IsWasmBuffer::decode(bit_field());
}
bool JSArrayBuffer::is_growable() { return IsGrowable::decode(bit_field()); }

void JSArrayBuffer::set_is_wasm_buffer(bool value) {
set_bit_field(IsWasmBuffer::update(bit_field(), value));
void JSArrayBuffer::set_is_growable(bool value) {
set_bit_field(IsGrowable::update(bit_field(), value));
}

Object* JSArrayBufferView::byte_offset() const {
@@ -170,10 +170,8 @@ class JSArrayBuffer : public JSObject {
inline bool has_guard_region() const;
inline void set_has_guard_region(bool value);

// TODO(gdeepti): This flag is introduced to disable asm.js optimizations in
// js-typer-lowering.cc, remove when the asm.js case is fixed.
inline bool is_wasm_buffer();
inline void set_is_wasm_buffer(bool value);
inline bool is_growable();
inline void set_is_growable(bool value);

DECL_CAST(JSArrayBuffer)

@@ -233,7 +231,7 @@ class JSArrayBuffer : public JSObject {
class WasNeutered : public BitField<bool, 3, 1> {};
class IsShared : public BitField<bool, 4, 1> {};
class HasGuardRegion : public BitField<bool, 5, 1> {};
class IsWasmBuffer : public BitField<bool, 6, 1> {};
class IsGrowable : public BitField<bool, 6, 1> {};

private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer);
@@ -1793,7 +1793,6 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
// Set externally passed ArrayBuffer non neuterable.
memory->set_is_neuterable(false);
memory->set_is_wasm_buffer(true);

DCHECK_IMPLIES(trap_handler::UseTrapHandler(),
module_->is_asm_js() || memory->has_guard_region());
@@ -753,6 +753,10 @@ void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
max_size64 = i::FLAG_wasm_max_mem_pages;
}
i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer());
if (!old_buffer->is_growable()) {
thrower.RangeError("This memory cannot be grown");
return;
}
uint32_t old_size =
old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages;
int64_t new_size64 = old_size + delta_size;
@@ -67,7 +67,7 @@ Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* allocation_base,
allocation_length, backing_store, static_cast<int>(size),
shared);
buffer->set_is_neuterable(false);
buffer->set_is_wasm_buffer(true);
buffer->set_is_growable(true);
buffer->set_has_guard_region(enable_guard_regions);
return buffer;
}
@@ -322,6 +322,7 @@ namespace {
Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
Handle<JSArrayBuffer> old_buffer,
uint32_t pages, uint32_t maximum_pages) {
if (!old_buffer->is_growable()) return Handle<JSArrayBuffer>::null();
Address old_mem_start = nullptr;
uint32_t old_size = 0;
if (!old_buffer.is_null()) {
@@ -466,6 +467,7 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
Handle<WasmMemoryObject> memory_object,
uint32_t pages) {
Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer());
if (!old_buffer->is_growable()) return -1;
uint32_t old_size = 0;
CHECK(old_buffer->byte_length()->ToUint32(&old_size));
DCHECK_EQ(0, old_size % WasmModule::kPageSize);
@@ -0,0 +1,30 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

function module(stdlib,foreign,buffer) {
"use asm";
var fl = new stdlib.Uint32Array(buffer);
function f1(x) {
x = x | 0;
fl[0] = x;
fl[0x10000] = x;
fl[0x100000] = x;
}
return f1;
}

var global = {Uint32Array:Uint32Array};
var env = {};
memory = new WebAssembly.Memory({initial:200});
var buffer = memory.buffer;
evil_f = module(global,env,buffer);

zz = {};
zz.toString = function() {
Array.prototype.slice.call([]);
return 0xffffffff;
}
evil_f(3);
assertThrows(() => memory.grow(1), RangeError);
evil_f(zz);

0 comments on commit 5f960df

Please sign in to comment.
You can’t perform that action at this time.