| 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 / 41: Element section for Table 0 exceeds available Table 0"); |
| } |
| |
| { |
| // Bad table index. |
| const builder = new Builder() |
| .Type().End() |
| .Function().End() |
| .Table() |
| .Table({element: "anyfunc", 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 30 / 47: Element section for Table 1 exceeds available Table 1"); |
| } |
| |
| { |
| // Overflow table maximum size. |
| const builder = new Builder() |
| .Type().End() |
| .Function().End() |
| .Table() |
| .Table({element: "anyfunc", 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: "anyfunc", 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: "anyfunc", 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 / 50: 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: "anyfunc", 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: "anyfunc", 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: "anyfunc", 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: "anyfunc", 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: "anyfunc", 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 / 72: Element init_expr must produce an i32"); |
| } |