blob: 7b80d509afb26bad2c7ccb6e38e52ecb252330a8 [file] [log] [blame]
import Builder from '../Builder.js';
import * as assert from '../assert.js';
{
// Bad element section b/c no Table section/import.
const builder = new Builder()
.Type().End()
.Function().End()
.Element()
.Element({tableIndex: 0, offset: 0, functionIndices: [0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 24: Element section for Table 0 exceeds available Table 0");
}
{
// Bad table index.
const builder = new Builder()
.Type().End()
.Function().End()
.Table()
.Table({element: "funcref", initial: 20})
.End()
.Element()
.Element({tableIndex: 1, offset: 0, functionIndices: [0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 31: Element section for Table 1 exceeds available Table 1");
}
{
// Overflow table maximum size.
const builder = new Builder()
.Type().End()
.Function().End()
.Table()
.Table({element: "funcref", initial: 20, maximum: 20})
.End()
.Element()
.Element({offset: 19, functionIndices: [0, 0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
const module = new WebAssembly.Module(builder.WebAssembly().get());
assert.throws(() => new WebAssembly.Instance(module), WebAssembly.LinkError, "Element is trying to set an out of bounds table index");
}
{
// Overflow table maximum size.
const builder = new Builder()
.Type().End()
.Function().End()
.Table()
.Table({element: "funcref", initial: 20, maximum: 20})
.End()
.Element()
.Element({offset: 20, functionIndices: [0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
const module = new WebAssembly.Module(builder.WebAssembly().get());
assert.throws(() => new WebAssembly.Instance(module), WebAssembly.LinkError, "Element is trying to set an out of bounds table index");
}
{
// Overflow function index space.
const builder = new Builder()
.Type().End()
.Function().End()
.Table()
.Table({element: "funcref", initial: 20, maximum: 20})
.End()
.Element()
.Element({offset: 0, functionIndices: [0, 0, 1]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 38: Element section's 0th element's 2th index is 1 which exceeds the function index space size of 1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')");
}
{
function badInstantiation(actualTable, errorType, msg) {
// Overflow function index space.
const builder = new Builder()
.Type().End()
.Import()
.Table("imp", "table", {element: "funcref", initial: 19}) // unspecified maximum.
.End()
.Function().End()
.Element()
.Element({offset: 19, functionIndices: [0, 0, 0, 0, 0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
assert.throws(() => new WebAssembly.Instance(module, {imp: {table: actualTable}}), errorType, msg);
}
for (let i = 19; i < 19 + 5; i++) {
const table = new WebAssembly.Table({element: "funcref", initial: i});
badInstantiation(table, WebAssembly.LinkError, "Element is trying to set an out of bounds table index (evaluating 'new WebAssembly.Instance(module, {imp: {table: actualTable}})')");
}
}
{
function makeModule() {
const builder = new Builder()
.Type().End()
.Import()
.Table("imp", "table", {element: "funcref", initial: 19}) // unspecified maximum.
.Global().I32("imp", "global", "immutable").End()
.End()
.Function().End()
.Element()
.Element({offset: {op: "get_global", initValue: 0}, functionIndices: [0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
const bin = builder.WebAssembly().get();
return new WebAssembly.Module(bin);
}
function test(i) {
const table = new WebAssembly.Table({element: "funcref", initial: 19});
const global = i;
const module = makeModule();
const instance = new WebAssembly.Instance(module, {imp: {table, global}});
for (let j = 0; j < 19; j++) {
if (j === i)
assert.eq(table.get(j)(i*2), i*2 + 42);
else
assert.throws(() => table.get(j)(i*2), TypeError, "table.get(j) is not a function. (In 'table.get(j)(i*2)', 'table.get(j)' is null)");
}
}
for (let i = 0; i < 19; i++)
test(i);
assert.throws(() => test(19), Error, "Element is trying to set an out of bounds table index");
}
{
function badModule() {
const builder = new Builder()
.Type().End()
.Import()
.Table("imp", "table", {element: "funcref", initial: 19}) // unspecified maximum.
.Global().F32("imp", "global", "immutable").End()
.End()
.Function().End()
.Element()
.Element({offset: {op: "get_global", initValue: 0}, functionIndices: [0]})
.End()
.Code()
.Function("foo", {params: ["i32"], ret: "i32"})
.GetLocal(0)
.I32Const(42)
.I32Add()
.Return()
.End()
.End();
const bin = builder.WebAssembly().get();
return new WebAssembly.Module(bin);
}
assert.throws(() => badModule(), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 58: Element init_expr must produce an i32");
}