Commit f6296b34 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[asm.js] Fix heap buffer checking during instantiation.

This makes sure that asm.js modules can only be instantiated with a
valid {ArrayBuffer} as the underlying heap buffer for all cases where
accepting anything else would be observably different from JavaScript
proper.

R=clemensh@chromium.org
TEST=mjsunit/asm/asm-memory
BUG=chromium:715505,chromium:715748

Change-Id: I355686200151c5667bf836824de922d657a8d943
Reviewed-on: https://chromium-review.googlesource.com/488521
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44938}
parent d9b8e463
......@@ -63,7 +63,8 @@ Handle<Object> StdlibMathMember(Isolate* isolate, Handle<JSReceiver> stdlib,
}
bool IsStdlibMemberValid(Isolate* isolate, Handle<JSReceiver> stdlib,
wasm::AsmTyper::StandardMember member) {
wasm::AsmTyper::StandardMember member,
bool* is_typed_array) {
switch (member) {
case wasm::AsmTyper::StandardMember::kNone:
case wasm::AsmTyper::StandardMember::kModule:
......@@ -125,6 +126,7 @@ bool IsStdlibMemberValid(Isolate* isolate, Handle<JSReceiver> stdlib,
#undef STDLIB_MATH_CONST
#define STDLIB_ARRAY_TYPE(fname, FName) \
case wasm::AsmTyper::StandardMember::k##FName: { \
*is_typed_array = true; \
if (stdlib.is_null()) { \
return false; \
} \
......@@ -297,11 +299,13 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate,
FixedArray::cast(wasm_data->get(kWasmDataForeignGlobals)));
// Check that all used stdlib members are valid.
bool stdlib_use_of_typed_array_present = false;
for (int i = 0; i < stdlib_uses->length(); ++i) {
int member_id = Smi::cast(stdlib_uses->get(i))->value();
wasm::AsmTyper::StandardMember member =
static_cast<wasm::AsmTyper::StandardMember>(member_id);
if (!IsStdlibMemberValid(isolate, stdlib, member)) {
if (!IsStdlibMemberValid(isolate, stdlib, member,
&stdlib_use_of_typed_array_present)) {
return MaybeHandle<Object>();
}
}
......@@ -316,6 +320,17 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate,
foreign, NONE);
}
// Check that a valid heap buffer is provided if required.
if (stdlib_use_of_typed_array_present) {
if (memory.is_null()) return MaybeHandle<Object>();
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.
if (size % FixedTypedArrayBase::kMaxElementSize != 0) {
return MaybeHandle<Object>();
}
}
wasm::ErrorThrower thrower(isolate, "Asm.js -> WebAssembly instantiation");
MaybeHandle<Object> maybe_module_object =
wasm::SyncInstantiate(isolate, &thrower, module, ffi_object, memory);
......
// 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.
// Flags: --allow-natives-syntax
(function TestUnalignedMemory() {
// Test that a buffer whose length is not a multiple of the element size of a
// heap view throws the proper {RangeError} during instantiation.
function Module(stdlib, foreign, heap) {
"use asm";
var a = new stdlib.Int32Array(heap);
function f() {}
return { f:f };
}
assertThrows(() => Module(this, {}, new ArrayBuffer(2)), RangeError);
assertThrows(() => Module(this, {}, new ArrayBuffer(10)), RangeError);
assertDoesNotThrow(() => Module(this, {}, new ArrayBuffer(4)));
assertDoesNotThrow(() => Module(this, {}, new ArrayBuffer(16)));
assertFalse(%IsAsmWasmCode(Module));
})();
(function TestMissingMemory() {
// Test that a buffer is required for instantiation of modules containing any
// heap views. JavaScript needs to create individual buffers for each view.
function Module(stdlib, foreign, heap) {
"use asm";
var a = new stdlib.Int16Array(heap);
var b = new stdlib.Int32Array(heap);
function f() {
a[0] = 0x1234;
return b[0] | 0;
}
return { f:f };
}
var m = Module(this, {}, undefined);
assertFalse(%IsAsmWasmCode(Module));
assertEquals(0, m.f());
})();
(function TestNonBufferMemory() {
// Test that a buffer has to be an instance of {ArrayBuffer} in order to be
// valid. JavaScript will also accept any other array-like object.
function Module(stdlib, foreign, heap) {
"use asm";
var a = new stdlib.Int32Array(heap);
function f() {
return a[0] | 0;
}
return { f:f };
}
var m = Module(this, {}, [ 23, 42 ]);
assertFalse(%IsAsmWasmCode(Module));
assertEquals(23, m.f());
})();
......@@ -549,7 +549,6 @@ function TestHeapAccessIntTypes() {
assertValidAsm(module_decl);
assertEquals(7, module.caller());
assertEquals(7, memory_view[2]);
assertEquals(7, module_decl(stdlib).caller());
assertValidAsm(module_decl);
}
}
......@@ -1227,8 +1226,9 @@ TestForeignVariables();
return {load: load, iload: iload, store: store, storeb: storeb};
}
var memory = new ArrayBuffer(1024);
var module_decl = eval('(' + TestByteHeapAccessCompat.toString() + ')');
var m = module_decl(stdlib);
var m = module_decl(stdlib, null, memory);
assertValidAsm(module_decl);
m.store(0, 20);
m.store(4, 21);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment