Bug 1642940 - Consolidate and expand tests of memory/table limits. r=lth

There were some ad-hoc tests for this behavior that are now consolidated and
extended in 'limits.js'.

Differential Revision: https://phabricator.services.mozilla.com/D80141
This commit is contained in:
Ryan Hunt 2020-06-25 08:28:09 +00:00
Родитель e2cb431b65
Коммит a7d5673bc3
3 изменённых файлов: 228 добавлений и 33 удалений

Просмотреть файл

@ -119,18 +119,6 @@ wasmEvalText('(module (import "a" "" (func $foo (result f64))))', {a:{"":()=>{}}
wasmValidateText('(module (memory 0))');
wasmValidateText('(module (memory 1))');
wasmValidateText('(module (memory 16384))');
wasmFailValidateText('(module (memory 16385))', /initial memory size too big/);
wasmEvalText('(module (memory 0 65536))')
wasmFailValidateText('(module (memory 0 65537))', /maximum memory size too big/);
// May OOM, but must not crash:
try {
wasmEvalText('(module (memory 16384))');
} catch (e) {
assertEq(String(e).indexOf("out of memory") !== -1, true);
}
var buf = wasmEvalText('(module (memory 1) (export "memory" (memory 0)))').exports.memory.buffer;
assertEq(buf instanceof ArrayBuffer, true);

Просмотреть файл

@ -23,27 +23,6 @@ function assertSegmentFitError(f) {
}
}
// Memory size consistency and internal limits.
assertErrorMessage(() => new Memory({initial:2, maximum:1}), RangeError, /bad Memory maximum size/);
try {
new Memory({initial:16384});
} catch(e) {
assertEq(String(e).indexOf("out of memory") !== -1, true);
}
assertErrorMessage(() => new Memory({initial: 16385}), RangeError, /bad Memory initial size/);
new Memory({initial: 0, maximum: 65536});
assertErrorMessage(() => new Memory({initial: 0, maximum: 65537}), RangeError, /bad Memory maximum size/);
// Table size consistency and internal limits.
assertErrorMessage(() => new Table({initial:2, maximum:1, element:"funcref"}), RangeError, /bad Table maximum size/);
new Table({ initial: 10000000, element:"funcref" });
assertErrorMessage(() => new Table({initial:10000001, element:"funcref"}), RangeError, /bad Table initial size/);
new Table({ initial: 0, maximum: 10000000, element:"funcref" });
assertErrorMessage(() => new Table({initial:0, maximum: 10000001, element:"funcref"}), RangeError, /bad Table maximum size/);
const m1 = new Module(wasmTextToBinary('(module (import "foo" "bar" (func)) (import "baz" "quux" (func)))'));
assertErrorMessage(() => new Instance(m1), TypeError, /second argument must be an object/);
assertErrorMessage(() => new Instance(m1, {foo:null}), TypeError, /import object field 'foo' is not an Object/);

Просмотреть файл

@ -0,0 +1,228 @@
// Tests of limits of memory and table types
const PageSize = 65536;
const MemoryMaxValid = 65536;
const MemoryMaxRuntime = Math.floor(0x7fff_ffff / PageSize);
const TableMaxValid = 0xffff_ffff;
const TableMaxRuntime = 10_000_000;
// Test that a memory type is valid within a module
function testMemoryValidate(initial, maximum, shared) {
wasmValidateText(`(module
(memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
)`);
}
testMemoryValidate(0, undefined, false);
testMemoryValidate(1, undefined, false);
testMemoryValidate(0, 1, false);
testMemoryValidate(0, 1, true);
testMemoryValidate(1, 1, false);
testMemoryValidate(1, 1, true);
testMemoryValidate(MemoryMaxValid, undefined, false);
testMemoryValidate(MemoryMaxValid, MemoryMaxValid, false);
testMemoryValidate(MemoryMaxValid, MemoryMaxValid, true);
// Test that a memory type is not valid within a module
function testMemoryFailValidate(initial, maximum, shared, pattern) {
wasmFailValidateText(`(module
(memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
)`, pattern);
}
testMemoryFailValidate(2, 1, false, /size minimum must not be greater than maximum/);
testMemoryFailValidate(1, undefined, true, /maximum length required for shared memory/);
testMemoryFailValidate(MemoryMaxValid + 1, undefined, false, /initial memory size too big/);
testMemoryFailValidate(MemoryMaxValid, MemoryMaxValid + 1, false, /maximum memory size too big/);
testMemoryFailValidate(MemoryMaxValid, MemoryMaxValid + 1, true, /maximum memory size too big/);
// Test that a memory type is invalid for constructing a WebAssembly.Memory
function testMemoryFailConstruct(initial, maximum, shared, pattern) {
assertErrorMessage(() => new WebAssembly.Memory({
initial,
maximum,
shared
}), RangeError, pattern);
}
testMemoryFailConstruct(MemoryMaxValid + 1, undefined, false, /bad Memory initial size/);
testMemoryFailConstruct(0, MemoryMaxValid + 1, false, /bad Memory maximum size/);
testMemoryFailConstruct(MemoryMaxValid + 1, undefined, true, /bad Memory initial size/);
testMemoryFailConstruct(0, MemoryMaxValid + 1, true, /bad Memory maximum size/);
// Test that a memory type can be instantiated within a module or constructed
// with a WebAssembly.Memory
function testMemoryCreate(initial, maximum, shared) {
// May OOM, but must not fail to validate
try {
wasmEvalText(`(module
(memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
)`);
} catch (e) {
assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
}
try {
new WebAssembly.Memory({initial, maximum, shared});
} catch (e) {
assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
}
}
testMemoryCreate(0, undefined, false);
testMemoryCreate(1, undefined, false);
testMemoryCreate(0, 1, false);
testMemoryCreate(0, 1, true);
testMemoryCreate(1, 1, false);
testMemoryCreate(1, 1, true);
testMemoryCreate(MemoryMaxRuntime, undefined, false);
testMemoryCreate(MemoryMaxRuntime, MemoryMaxValid, false);
testMemoryCreate(MemoryMaxRuntime, MemoryMaxValid, true);
// Test that a memory type cannot be instantiated within a module or constructed
// with a WebAssembly.Memory
function testMemoryFailCreate(initial, maximum, shared, pattern) {
assertErrorMessage(() => wasmEvalText(`(module
(memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
)`), WebAssembly.RuntimeError, pattern);
assertErrorMessage(() => new WebAssembly.Memory({
initial,
maximum,
shared
}), WebAssembly.RuntimeError, pattern);
}
testMemoryFailCreate(MemoryMaxRuntime + 1, undefined, false, /too many memory pages/);
testMemoryFailCreate(MemoryMaxRuntime + 1, MemoryMaxValid, false, /too many memory pages/);
testMemoryFailCreate(MemoryMaxRuntime + 1, MemoryMaxValid, true, /too many memory pages/);
// Test that a memory type cannot be grown from initial to a target due to an
// implementation limit
function testMemoryFailGrow(initial, maximum, target, shared) {
let {run} = wasmEvalText(`(module
(memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
(func (export "run") (result i32)
i32.const ${target - initial}
memory.grow
)
)`).exports;
assertEq(run(), -1, 'failed to grow');
let mem = new WebAssembly.Memory({
initial,
maximum,
shared
});
assertErrorMessage(() => mem.grow(target - initial), RangeError, /failed to grow memory/);
}
testMemoryFailGrow(1, undefined, MemoryMaxRuntime + 1, false);
testMemoryFailGrow(1, MemoryMaxValid, MemoryMaxRuntime + 1, false);
testMemoryFailGrow(1, MemoryMaxValid, MemoryMaxRuntime + 1, true);
// Test that a table type is valid within a module
function testTableValidate(initial, maximum) {
wasmValidateText(`(module
(table ${initial} ${maximum || ''} externref)
)`);
}
testTableValidate(0, undefined);
testTableValidate(1, undefined);
testTableValidate(0, 1);
testTableValidate(1, 1);
testTableValidate(TableMaxValid, undefined);
testTableValidate(TableMaxValid, TableMaxValid);
// Test that a table type is not valid within a module
function testTableFailValidate(initial, maximum, pattern) {
wasmFailValidateText(`(module
(table ${initial} ${maximum || ''} externref)
)`, pattern);
}
testTableFailValidate(2, 1, /size minimum must not be greater than maximum/);
// The maximum valid table value is equivalent to the maximum encodable limit
// value, so we cannot test too large of a table limit in a module.
assertEq(TableMaxValid + 1 > 0xffffffff, true);
// Test that a table type is invalid for constructing a WebAssembly.Table
function testTableFailConstruct(initial, maximum, pattern) {
assertErrorMessage(() => new WebAssembly.Table({
initial,
maximum,
element: 'externref',
}), TypeError, pattern);
}
testTableFailConstruct(TableMaxValid + 1, undefined, /bad Table initial size/);
testTableFailConstruct(0, TableMaxValid + 1, /bad Table maximum size/);
// Test that a table type can be instantiated within a module or constructed
// with a WebAssembly.Table
function testTableCreate(initial, maximum) {
// May OOM, but must not fail to validate
try {
wasmEvalText(`(module
(table ${initial} ${maximum || ''} externref)
)`);
} catch (e) {
assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
}
try {
new WebAssembly.Table({
initial,
maximum,
element: 'externref',
});
} catch (e) {
assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
}
}
testTableCreate(0, undefined);
testTableCreate(1, undefined);
testTableCreate(0, 1);
testTableCreate(1, 1);
testTableCreate(TableMaxRuntime, undefined);
testTableCreate(TableMaxRuntime, TableMaxValid);
// Test that a table type cannot be instantiated within a module or constructed
// with a WebAssembly.Table
function testTableFailCreate(initial, maximum, pattern) {
assertErrorMessage(() => wasmEvalText(`(module
(table ${initial} ${maximum || ''} externref)
)`), WebAssembly.RuntimeError, pattern);
assertErrorMessage(() => new WebAssembly.Table({
initial,
maximum,
element: 'externref',
}), WebAssembly.RuntimeError, pattern);
}
testTableFailCreate(TableMaxRuntime + 1, undefined, /too many table elements/);
testTableFailCreate(TableMaxRuntime + 1, TableMaxValid, /too many table elements/);
// Test that a table type cannot be grown from initial to a target due to an
// implementation limit
function testTableFailGrow(initial, maximum, target) {
let {run} = wasmEvalText(`(module
(table ${initial} ${maximum || ''} externref)
(func (export "run") (result i32)
ref.null extern
i32.const ${target - initial}
table.grow
)
)`).exports;
assertEq(run(), -1, 'failed to grow');
let tab = new WebAssembly.Table({
initial,
maximum,
element: 'externref',
});
assertErrorMessage(() => tab.grow(target - initial), RangeError, /failed to grow table/);
}
testTableFailGrow(1, undefined, TableMaxRuntime + 1);
testTableFailGrow(1, TableMaxValid, TableMaxRuntime + 1);