2018-11-12 20:53:47 +00:00
|
|
|
// Copyright 2018 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.
|
|
|
|
|
2021-06-01 12:46:36 +00:00
|
|
|
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
2018-11-12 20:53:47 +00:00
|
|
|
|
|
|
|
(function TestPassiveDataSegment() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2018-11-12 20:53:47 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addMemory(1, 1, false);
|
|
|
|
builder.addPassiveDataSegment([0, 1, 2]);
|
|
|
|
builder.addPassiveDataSegment([3, 4]);
|
|
|
|
|
|
|
|
// Should not throw.
|
2018-12-08 00:23:10 +00:00
|
|
|
builder.instantiate();
|
2018-11-12 20:53:47 +00:00
|
|
|
})();
|
|
|
|
|
|
|
|
(function TestPassiveElementSegment() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2018-11-12 20:53:47 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addFunction('f', kSig_v_v).addBody([]);
|
2018-11-26 12:02:03 +00:00
|
|
|
builder.setTableBounds(1, 1);
|
2018-11-12 20:53:47 +00:00
|
|
|
builder.addPassiveElementSegment([0, 0, 0]);
|
|
|
|
builder.addPassiveElementSegment([0, 0]);
|
|
|
|
|
|
|
|
// Should not throw.
|
2018-12-08 00:23:10 +00:00
|
|
|
builder.instantiate();
|
|
|
|
})();
|
|
|
|
|
2018-12-12 02:18:54 +00:00
|
|
|
function getMemoryInit(mem, segment_data) {
|
|
|
|
const builder = new WasmModuleBuilder();
|
2021-05-05 07:14:19 +00:00
|
|
|
builder.addImportedMemory('', 'mem', 0);
|
2018-12-12 02:18:54 +00:00
|
|
|
builder.addPassiveDataSegment(segment_data);
|
|
|
|
builder.addFunction('init', kSig_v_iii)
|
|
|
|
.addBody([
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0, // Dest.
|
|
|
|
kExprLocalGet, 1, // Source.
|
|
|
|
kExprLocalGet, 2, // Size in bytes.
|
2018-12-12 02:18:54 +00:00
|
|
|
kNumericPrefix, kExprMemoryInit,
|
|
|
|
0, // Data segment index.
|
2019-01-31 01:50:44 +00:00
|
|
|
0, // Memory index.
|
2018-12-12 02:18:54 +00:00
|
|
|
])
|
|
|
|
.exportAs('init');
|
|
|
|
return builder.instantiate({'': {mem}}).exports.init;
|
|
|
|
}
|
|
|
|
|
2019-03-13 19:22:40 +00:00
|
|
|
(function TestMemoryInitOutOfBoundsGrow() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2018-12-12 02:18:54 +00:00
|
|
|
const mem = new WebAssembly.Memory({initial: 1});
|
|
|
|
// Create a data segment that has a length of kPageSize.
|
|
|
|
const memoryInit = getMemoryInit(mem, new Array(kPageSize));
|
|
|
|
|
|
|
|
mem.grow(1);
|
|
|
|
|
|
|
|
// Works properly after grow.
|
|
|
|
memoryInit(kPageSize, 0, 1000);
|
|
|
|
|
|
|
|
// Traps at new boundary.
|
|
|
|
assertTraps(
|
|
|
|
kTrapMemOutOfBounds, () => memoryInit(kPageSize + 1, 0, kPageSize));
|
|
|
|
})();
|
|
|
|
|
|
|
|
(function TestMemoryInitOnActiveSegment() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2018-12-12 02:18:54 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addMemory(1);
|
|
|
|
builder.addPassiveDataSegment([1, 2, 3]);
|
|
|
|
builder.addDataSegment(0, [4, 5, 6]);
|
2019-11-21 11:02:27 +00:00
|
|
|
builder.addFunction('init', kSig_v_i)
|
2018-12-12 02:18:54 +00:00
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 0, // Dest.
|
|
|
|
kExprI32Const, 0, // Source.
|
2019-11-21 11:02:27 +00:00
|
|
|
kExprLocalGet, 0, // Size in bytes.
|
2018-12-12 02:18:54 +00:00
|
|
|
kNumericPrefix, kExprMemoryInit,
|
|
|
|
1, // Data segment index.
|
2019-01-31 01:50:44 +00:00
|
|
|
0, // Memory index.
|
2018-12-12 02:18:54 +00:00
|
|
|
])
|
|
|
|
.exportAs('init');
|
|
|
|
|
|
|
|
// Instantiation succeeds, because using memory.init with an active segment
|
|
|
|
// is a trap, not a validation error.
|
|
|
|
const instance = builder.instantiate();
|
|
|
|
|
2019-12-02 17:47:12 +00:00
|
|
|
// Initialization succeeds, because source address and size are 0
|
|
|
|
// which is valid on a dropped segment.
|
2019-11-21 11:02:27 +00:00
|
|
|
instance.exports.init(0);
|
|
|
|
|
2019-12-02 17:47:12 +00:00
|
|
|
// Initialization fails, because the segment is implicitly dropped.
|
|
|
|
assertTraps(kTrapMemOutOfBounds, () => instance.exports.init(1));
|
2018-12-12 02:18:54 +00:00
|
|
|
})();
|
|
|
|
|
2019-01-31 18:45:51 +00:00
|
|
|
(function TestDataDropOnActiveSegment() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2018-12-12 02:18:54 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addMemory(1);
|
|
|
|
builder.addPassiveDataSegment([1, 2, 3]);
|
|
|
|
builder.addDataSegment(0, [4, 5, 6]);
|
|
|
|
builder.addFunction('drop', kSig_v_v)
|
|
|
|
.addBody([
|
2019-01-31 18:45:51 +00:00
|
|
|
kNumericPrefix, kExprDataDrop,
|
2018-12-12 02:18:54 +00:00
|
|
|
1, // Data segment index.
|
|
|
|
])
|
|
|
|
.exportAs('drop');
|
|
|
|
|
|
|
|
const instance = builder.instantiate();
|
2019-12-02 17:47:12 +00:00
|
|
|
// Drop on passive segment is equivalent to double drop which is allowed.
|
|
|
|
instance.exports.drop();
|
2018-12-12 02:18:54 +00:00
|
|
|
})();
|
|
|
|
|
2018-12-08 00:23:10 +00:00
|
|
|
function getMemoryCopy(mem) {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addImportedMemory("", "mem", 0);
|
|
|
|
builder.addFunction("copy", kSig_v_iii).addBody([
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0, // Dest.
|
|
|
|
kExprLocalGet, 1, // Source.
|
|
|
|
kExprLocalGet, 2, // Size in bytes.
|
2019-01-31 01:50:44 +00:00
|
|
|
kNumericPrefix, kExprMemoryCopy, 0, 0,
|
2018-12-08 00:23:10 +00:00
|
|
|
]).exportAs("copy");
|
|
|
|
return builder.instantiate({'': {mem}}).exports.copy;
|
|
|
|
}
|
|
|
|
|
2019-03-13 19:22:40 +00:00
|
|
|
(function TestMemoryCopyOutOfBoundsGrow() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2018-12-08 00:23:10 +00:00
|
|
|
const mem = new WebAssembly.Memory({initial: 1});
|
|
|
|
const memoryCopy = getMemoryCopy(mem);
|
|
|
|
|
|
|
|
mem.grow(1);
|
|
|
|
|
|
|
|
// Works properly after grow.
|
|
|
|
memoryCopy(0, kPageSize, 1000);
|
|
|
|
|
|
|
|
// Traps at new boundary.
|
|
|
|
assertTraps(
|
|
|
|
kTrapMemOutOfBounds, () => memoryCopy(0, kPageSize + 1, kPageSize));
|
|
|
|
})();
|
|
|
|
|
|
|
|
function getMemoryFill(mem) {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addImportedMemory("", "mem", 0);
|
|
|
|
builder.addFunction("fill", kSig_v_iii).addBody([
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0, // Dest.
|
|
|
|
kExprLocalGet, 1, // Byte value.
|
|
|
|
kExprLocalGet, 2, // Size.
|
2018-12-08 00:23:10 +00:00
|
|
|
kNumericPrefix, kExprMemoryFill, 0,
|
|
|
|
]).exportAs("fill");
|
|
|
|
return builder.instantiate({'': {mem}}).exports.fill;
|
|
|
|
}
|
|
|
|
|
2019-03-13 19:22:40 +00:00
|
|
|
(function TestMemoryFillOutOfBoundsGrow() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2019-03-05 19:35:07 +00:00
|
|
|
const mem = new WebAssembly.Memory({initial: 1});
|
|
|
|
const memoryFill = getMemoryFill(mem);
|
|
|
|
const v = 123;
|
|
|
|
|
2018-12-08 00:23:10 +00:00
|
|
|
mem.grow(1);
|
|
|
|
|
|
|
|
// Works properly after grow.
|
|
|
|
memoryFill(kPageSize, v, 1000);
|
|
|
|
|
|
|
|
// Traps at new boundary.
|
|
|
|
assertTraps(
|
|
|
|
kTrapMemOutOfBounds, () => memoryFill(kPageSize + 1, v, kPageSize));
|
2018-11-12 20:53:47 +00:00
|
|
|
})();
|
2019-01-14 13:18:44 +00:00
|
|
|
|
2019-01-31 18:45:51 +00:00
|
|
|
(function TestElemDropActive() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2019-01-14 16:49:07 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.setTableBounds(5, 5);
|
2022-06-20 14:37:49 +00:00
|
|
|
builder.addActiveElementSegment(0, wasmI32Const(0), [0, 0, 0]);
|
2019-01-14 16:49:07 +00:00
|
|
|
builder.addFunction('drop', kSig_v_v)
|
|
|
|
.addBody([
|
2019-01-31 18:45:51 +00:00
|
|
|
kNumericPrefix, kExprElemDrop,
|
2019-01-14 16:49:07 +00:00
|
|
|
0, // Element segment index.
|
|
|
|
])
|
|
|
|
.exportAs('drop');
|
|
|
|
|
|
|
|
const instance = builder.instantiate();
|
2019-12-02 17:47:12 +00:00
|
|
|
// Segment already got dropped after initialization and is therefore
|
|
|
|
// not active anymore.
|
|
|
|
instance.exports.drop();
|
2019-01-14 16:49:07 +00:00
|
|
|
})();
|
2019-04-16 22:14:05 +00:00
|
|
|
|
|
|
|
(function TestLazyDataSegmentBoundsCheck() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2019-04-16 22:14:05 +00:00
|
|
|
const memory = new WebAssembly.Memory({initial: 1});
|
|
|
|
const view = new Uint8Array(memory.buffer);
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addImportedMemory('m', 'memory', 1);
|
|
|
|
builder.addDataSegment(kPageSize - 1, [42, 42]);
|
|
|
|
builder.addDataSegment(0, [111, 111]);
|
|
|
|
|
|
|
|
assertEquals(0, view[kPageSize - 1]);
|
|
|
|
|
2019-12-02 17:47:12 +00:00
|
|
|
// Instantiation fails, memory remains unmodified.
|
2021-05-05 07:14:19 +00:00
|
|
|
assertThrows(
|
|
|
|
() => builder.instantiate({m: {memory}}), WebAssembly.RuntimeError);
|
2019-04-16 22:14:05 +00:00
|
|
|
|
2019-12-02 17:47:12 +00:00
|
|
|
assertEquals(0, view[kPageSize - 1]);
|
2019-04-16 22:14:05 +00:00
|
|
|
// The second segment is not initialized.
|
|
|
|
assertEquals(0, view[0]);
|
|
|
|
})();
|
|
|
|
|
|
|
|
(function TestLazyDataAndElementSegments() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2019-04-16 22:14:05 +00:00
|
|
|
const table = new WebAssembly.Table({initial: 1, element: 'anyfunc'});
|
|
|
|
const memory = new WebAssembly.Memory({initial: 1});
|
|
|
|
const view = new Uint8Array(memory.buffer);
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
|
|
|
|
builder.addImportedMemory('m', 'memory', 1);
|
|
|
|
builder.addImportedTable('m', 'table', 1);
|
|
|
|
const f = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 42]);
|
|
|
|
|
|
|
|
const tableIndex = 0;
|
2021-05-05 07:14:19 +00:00
|
|
|
builder.addActiveElementSegment(
|
|
|
|
tableIndex,
|
2022-06-20 14:37:49 +00:00
|
|
|
wasmI32Const(0),
|
2021-05-05 07:14:19 +00:00
|
|
|
[f.index, f.index]);
|
2019-04-16 22:14:05 +00:00
|
|
|
builder.addDataSegment(0, [42]);
|
|
|
|
|
|
|
|
// Instantiation fails, but still modifies the table. The memory is not
|
|
|
|
// modified, since data segments are initialized after element segments.
|
|
|
|
assertThrows(
|
2021-05-05 07:14:19 +00:00
|
|
|
() => builder.instantiate({m: {memory, table}}),
|
|
|
|
WebAssembly.RuntimeError);
|
2019-04-16 22:14:05 +00:00
|
|
|
|
|
|
|
assertEquals(0, view[0]);
|
|
|
|
})();
|
2020-03-26 14:00:44 +00:00
|
|
|
|
|
|
|
(function TestPassiveDataSegmentNoMemory() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2020-03-26 14:00:44 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addPassiveDataSegment([0, 1, 2]);
|
|
|
|
|
|
|
|
// Should not throw.
|
|
|
|
builder.instantiate();
|
|
|
|
})();
|
2020-03-26 14:15:09 +00:00
|
|
|
|
|
|
|
(function TestPassiveElementSegmentNoMemory() {
|
2022-11-10 11:33:44 +00:00
|
|
|
print(arguments.callee.name);
|
2020-03-26 14:15:09 +00:00
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addFunction('f', kSig_v_v).addBody([]);
|
|
|
|
builder.addPassiveElementSegment([0, 0, 0]);
|
|
|
|
|
|
|
|
// Should not throw.
|
|
|
|
builder.instantiate();
|
|
|
|
})();
|
2022-11-10 11:33:44 +00:00
|
|
|
|
|
|
|
(function TestIllegalNumericOpcode() {
|
|
|
|
// Regression test for https://crbug.com/1382816.
|
|
|
|
print(arguments.callee.name);
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
|
|
builder.addFunction('main', kSig_v_v).addBody([kNumericPrefix, 0x90, 0x0f]);
|
|
|
|
assertEquals(false, WebAssembly.validate(builder.toBuffer()));
|
|
|
|
assertThrows(
|
|
|
|
() => builder.toModule(), WebAssembly.CompileError,
|
|
|
|
/invalid numeric opcode: 0xfc790/);
|
|
|
|
})();
|