summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/passive-segs-nonboundary.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/jit-test/tests/wasm/passive-segs-nonboundary.js
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/wasm/passive-segs-nonboundary.js')
-rw-r--r--js/src/jit-test/tests/wasm/passive-segs-nonboundary.js1188
1 files changed, 1188 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/passive-segs-nonboundary.js b/js/src/jit-test/tests/wasm/passive-segs-nonboundary.js
new file mode 100644
index 0000000000..6753355e1e
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/passive-segs-nonboundary.js
@@ -0,0 +1,1188 @@
+load(libdir + "wasm-binary.js");
+
+const v2vSig = {args:[], ret:VoidCode};
+const v2vSigSection = sigSection([v2vSig]);
+
+const Module = WebAssembly.Module;
+const Instance = WebAssembly.Instance;
+
+// Some non-boundary tests for {table,memory}.{init,drop,copy}. The table
+// case is more complex and appears first. The memory case is a simplified
+// version of it.
+
+// This module exports 5 functions ..
+let tab_expmod_t =
+ `(module
+ (func (export "ef0") (result i32) (i32.const 0))
+ (func (export "ef1") (result i32) (i32.const 1))
+ (func (export "ef2") (result i32) (i32.const 2))
+ (func (export "ef3") (result i32) (i32.const 3))
+ (func (export "ef4") (result i32) (i32.const 4))
+ )`;
+
+// .. and this one imports those 5 functions. It adds 5 of its own, creates a
+// 30 element table using both active and passive initialisers, with a mixture
+// of the imported and local functions. |setup| and |check| are exported.
+// |setup| uses the supplied |insn| to modify the table somehow. |check| will
+// indirect-call the table entry number specified as a parameter. That will
+// either return a value 0 to 9 indicating the function called, or will throw an
+// exception if the table entry is empty.
+function gen_tab_impmod_t(insn)
+{
+ let t =
+ `(module
+ ;; -------- Types --------
+ (type (func (result i32))) ;; type #0
+ ;; -------- Imports --------
+ (import "a" "if0" (func (result i32))) ;; index 0
+ (import "a" "if1" (func (result i32)))
+ (import "a" "if2" (func (result i32)))
+ (import "a" "if3" (func (result i32)))
+ (import "a" "if4" (func (result i32))) ;; index 4
+ ;; -------- Tables --------
+ (table 30 30 funcref)
+ ;; -------- Table initialisers --------
+ (elem (i32.const 2) 3 1 4 1)
+ (elem func 2 7 1 8)
+ (elem (i32.const 12) 7 5 2 3 6)
+ (elem func 5 9 2 7 6)
+ ;; -------- Functions --------
+ (func (result i32) (i32.const 5)) ;; index 5
+ (func (result i32) (i32.const 6))
+ (func (result i32) (i32.const 7))
+ (func (result i32) (i32.const 8))
+ (func (result i32) (i32.const 9)) ;; index 9
+
+ (func (export "setup")
+ ${insn})
+ (func (export "check") (param i32) (result i32)
+ ;; call the selected table entry, which will either return a value,
+ ;; or will cause an exception.
+ local.get 0 ;; callIx
+ call_indirect (type 0) ;; and its return value is our return value.
+ )
+ )`;
+ return t;
+};
+
+// This is the test driver. It constructs the abovementioned module, using
+// the given |instruction| to modify the table, and then probes the table
+// by making indirect calls, one for each element of |expected_result_vector|.
+// The results are compared to those in the vector.
+
+function tab_test(instruction, expected_result_vector)
+{
+ let tab_expmod_b = wasmTextToBinary(tab_expmod_t);
+ let tab_expmod_i = new Instance(new Module(tab_expmod_b));
+
+ let tab_impmod_t = gen_tab_impmod_t(instruction);
+ let tab_impmod_b = wasmTextToBinary(tab_impmod_t);
+
+ let inst = new Instance(new Module(tab_impmod_b),
+ {a:{if0:tab_expmod_i.exports.ef0,
+ if1:tab_expmod_i.exports.ef1,
+ if2:tab_expmod_i.exports.ef2,
+ if3:tab_expmod_i.exports.ef3,
+ if4:tab_expmod_i.exports.ef4
+ }});
+ inst.exports.setup();
+
+ for (let i = 0; i < expected_result_vector.length; i++) {
+ let expected = expected_result_vector[i];
+ let actual = undefined;
+ try {
+ actual = inst.exports.check(i);
+ assertEq(actual !== null, true);
+ } catch (e) {
+ if (!(e instanceof Error &&
+ e.message.match(/indirect call to null/)))
+ throw e;
+ // actual remains undefined
+ }
+ assertEq(actual, expected,
+ "tab_test fail: insn = '" + instruction + "', index = " +
+ i + ", expected = " + expected + ", actual = " + actual);
+ }
+}
+
+// Using 'e' for empty (undefined) spaces in the table, to make it easier
+// to count through the vector entries when debugging.
+let e = undefined;
+
+// This just gives the initial state of the table, with its active
+// initialisers applied
+tab_test("nop",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy non-null over non-null
+tab_test("(table.copy (i32.const 13) (i32.const 2) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,3,1, 4,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy non-null over null
+tab_test("(table.copy (i32.const 25) (i32.const 15) (i32.const 2))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, 3,6,e,e,e]);
+
+// Copy null over non-null
+tab_test("(table.copy (i32.const 13) (i32.const 25) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,e,e, e,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy null over null
+tab_test("(table.copy (i32.const 20) (i32.const 22) (i32.const 4))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy null and non-null entries, non overlapping
+tab_test("(table.copy (i32.const 25) (i32.const 1) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,3,1,e,e]);
+
+// Copy null and non-null entries, overlapping, backwards
+tab_test("(table.copy (i32.const 10) (i32.const 12) (i32.const 7))",
+ [e,e,3,1,4, 1,e,e,e,e, 7,5,2,3,6, e,e,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy null and non-null entries, overlapping, forwards
+tab_test("(table.copy (i32.const 12) (i32.const 10) (i32.const 7))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,e,e,7, 5,2,3,6,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Passive init that overwrites all-null entries
+tab_test("(table.init 1 (i32.const 7) (i32.const 0) (i32.const 4))",
+ [e,e,3,1,4, 1,e,2,7,1, 8,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Passive init that overwrites existing active-init-created entries
+tab_test("(table.init 3 (i32.const 15) (i32.const 1) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 9,2,7,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Perform active and passive initialisation and then multiple copies
+tab_test("(table.init 1 (i32.const 7) (i32.const 0) (i32.const 4)) \n" +
+ "elem.drop 1 \n" +
+ "(table.init 3 (i32.const 15) (i32.const 1) (i32.const 3)) \n" +
+ "elem.drop 3 \n" +
+ "(table.copy (i32.const 20) (i32.const 15) (i32.const 5)) \n" +
+ "(table.copy (i32.const 21) (i32.const 29) (i32.const 1)) \n" +
+ "(table.copy (i32.const 24) (i32.const 10) (i32.const 1)) \n" +
+ "(table.copy (i32.const 13) (i32.const 11) (i32.const 4)) \n" +
+ "(table.copy (i32.const 19) (i32.const 20) (i32.const 5))",
+ [e,e,3,1,4, 1,e,2,7,1, 8,e,7,e,7, 5,2,7,e,9, e,7,e,8,8, e,e,e,e,e]);
+
+// And now a simplified version of the above, for memory.{init,drop,copy}.
+
+function gen_mem_mod_t(insn)
+{
+ let t =
+ `(module
+ ;; -------- Memories --------
+ (memory (export "memory0") 1 1)
+ ;; -------- Memory initialisers --------
+ (data (i32.const 2) "\\03\\01\\04\\01")
+ (data "\\02\\07\\01\\08")
+ (data (i32.const 12) "\\07\\05\\02\\03\\06")
+ (data "\\05\\09\\02\\07\\06")
+
+ (func (export "testfn")
+ ${insn}
+ ;; There's no return value. The JS driver can just pull out the
+ ;; final memory and examine it.
+ )
+ )`;
+ return t;
+};
+
+function mem_test(instruction, expected_result_vector)
+{
+ let mem_mod_t = gen_mem_mod_t(instruction);
+ let mem_mod_b = wasmTextToBinary(mem_mod_t);
+
+ let inst = new Instance(new Module(mem_mod_b));
+ inst.exports.testfn();
+ let buf = new Uint8Array(inst.exports.memory0.buffer);
+
+ for (let i = 0; i < expected_result_vector.length; i++) {
+ let expected = expected_result_vector[i];
+ let actual = buf[i];
+ assertEq(actual, expected,
+ "mem_test fail: insn = '" + instruction + "', index = " +
+ i + ", expected = " + expected + ", actual = " + actual);
+ }
+}
+
+e = 0;
+
+// This just gives the initial state of the memory, with its active
+// initialisers applied.
+mem_test("nop",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy non-zero over non-zero
+mem_test("(memory.copy (i32.const 13) (i32.const 2) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,3,1, 4,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy non-zero over zero
+mem_test("(memory.copy (i32.const 25) (i32.const 15) (i32.const 2))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, 3,6,e,e,e]);
+
+// Copy zero over non-zero
+mem_test("(memory.copy (i32.const 13) (i32.const 25) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,e,e, e,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy zero over zero
+mem_test("(memory.copy (i32.const 20) (i32.const 22) (i32.const 4))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy zero and non-zero entries, non overlapping
+mem_test("(memory.copy (i32.const 25) (i32.const 1) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,3,1,e,e]);
+
+// Copy zero and non-zero entries, overlapping, backwards
+mem_test("(memory.copy (i32.const 10) (i32.const 12) (i32.const 7))",
+ [e,e,3,1,4, 1,e,e,e,e, 7,5,2,3,6, e,e,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Copy zero and non-zero entries, overlapping, forwards
+mem_test("(memory.copy (i32.const 12) (i32.const 10) (i32.const 7))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,e,e,7, 5,2,3,6,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Passive init that overwrites all-zero entries
+mem_test("(memory.init 1 (i32.const 7) (i32.const 0) (i32.const 4))",
+ [e,e,3,1,4, 1,e,2,7,1, 8,e,7,5,2, 3,6,e,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Passive init that overwrites existing active-init-created entries
+mem_test("(memory.init 3 (i32.const 15) (i32.const 1) (i32.const 3))",
+ [e,e,3,1,4, 1,e,e,e,e, e,e,7,5,2, 9,2,7,e,e, e,e,e,e,e, e,e,e,e,e]);
+
+// Perform active and passive initialisation and then multiple copies
+mem_test("(memory.init 1 (i32.const 7) (i32.const 0) (i32.const 4)) \n" +
+ "data.drop 1 \n" +
+ "(memory.init 3 (i32.const 15) (i32.const 1) (i32.const 3)) \n" +
+ "data.drop 3 \n" +
+ "(memory.copy (i32.const 20) (i32.const 15) (i32.const 5)) \n" +
+ "(memory.copy (i32.const 21) (i32.const 29) (i32.const 1)) \n" +
+ "(memory.copy (i32.const 24) (i32.const 10) (i32.const 1)) \n" +
+ "(memory.copy (i32.const 13) (i32.const 11) (i32.const 4)) \n" +
+ "(memory.copy (i32.const 19) (i32.const 20) (i32.const 5))",
+ [e,e,3,1,4, 1,e,2,7,1, 8,e,7,e,7, 5,2,7,e,9, e,7,e,8,8, e,e,e,e,e]);
+
+function checkDataCount(count, err) {
+ let binary = moduleWithSections(
+ [v2vSigSection,
+ dataCountSection(count),
+ dataSection([
+ {offset: 0, elems: []},
+ {offset: 0, elems: []},
+ ])
+ ]);
+ assertErrorMessage(() => new WebAssembly.Module(binary),
+ WebAssembly.CompileError,
+ err);
+}
+
+// DataCount section is present but value is too low for the number of data segments
+checkDataCount(1, /number of data segments does not match declared count/);
+// DataCount section is present but value is too high for the number of data segments
+checkDataCount(3, /number of data segments does not match declared count/);
+
+// DataCount section is not present but memory.init or data.drop uses it
+function checkNoDataCount(body, err) {
+ let binary = moduleWithSections(
+ [v2vSigSection,
+ declSection([0]),
+ memorySection(1),
+ bodySection(
+ [funcBody({locals:[], body})])]);
+ assertErrorMessage(() => new WebAssembly.Module(binary),
+ WebAssembly.CompileError,
+ err);
+}
+
+checkNoDataCount([I32ConstCode, 0,
+ I32ConstCode, 0,
+ I32ConstCode, 0,
+ MiscPrefix, MemoryInitCode, 0, 0],
+ /(memory.init requires a DataCount section)|(unknown data segment)/);
+
+checkNoDataCount([MiscPrefix, DataDropCode, 0],
+ /(data.drop requires a DataCount section)|(unknown data segment)/);
+
+//---------------------------------------------------------------------//
+//---------------------------------------------------------------------//
+// Some further tests for memory.copy and memory.fill. First, validation
+// tests.
+
+// Prefixed opcodes
+
+function checkMiscPrefixed(opcode, expect_failure) {
+ let binary = moduleWithSections(
+ [v2vSigSection, declSection([0]), memorySection(1),
+ bodySection(
+ [funcBody(
+ {locals:[],
+ body:[I32ConstCode, 0x0,
+ I32ConstCode, 0x0,
+ I32ConstCode, 0x0,
+ MiscPrefix, ...opcode]})])]);
+ if (expect_failure) {
+ assertErrorMessage(() => new WebAssembly.Module(binary),
+ WebAssembly.CompileError, /(unrecognized opcode)|(Unknown.*subopcode)/);
+ } else {
+ assertEq(WebAssembly.validate(binary), true);
+ }
+}
+
+//-----------------------------------------------------------
+// Verification cases for memory.copy/fill opcode encodings
+
+checkMiscPrefixed([MemoryCopyCode, 0x00, 0x00], false); // memory.copy src=0 dest=0
+checkMiscPrefixed([MemoryFillCode, 0x00], false); // memory.fill mem=0
+checkMiscPrefixed([0x13], true); // table.size+1, which is currently unassigned
+
+//-----------------------------------------------------------
+// Verification cases for memory.copy/fill arguments
+
+// Invalid argument types
+{
+ const tys = ['i32', 'f32', 'i64', 'f64'];
+ const ops = ['copy', 'fill'];
+ for (let ty1 of tys) {
+ for (let ty2 of tys) {
+ for (let ty3 of tys) {
+ for (let op of ops) {
+ if (ty1 == 'i32' && ty2 == 'i32' && ty3 == 'i32')
+ continue; // this is the only valid case
+ let text =
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.${op} (${ty1}.const 10) (${ty2}.const 20) (${ty3}.const 30))
+ )
+ )`;
+ assertErrorMessage(() => wasmEvalText(text),
+ WebAssembly.CompileError, /type mismatch/);
+ }}}}
+}
+
+// Not enough, or too many, args
+{
+ for (let op of ['copy', 'fill']) {
+ let text1 =
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (i32.const 10)
+ (i32.const 20)
+ memory.${op}
+ )
+ )`;
+ assertErrorMessage(() => wasmEvalText(text1),
+ WebAssembly.CompileError,
+ /(popping value from empty stack)|(expected i32 but nothing on stack)/);
+ let text2 =
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (i32.const 10)
+ (i32.const 20)
+ (i32.const 30)
+ (i32.const 40)
+ memory.${op}
+ )
+ )`;
+ assertErrorMessage(() => wasmEvalText(text2),
+ WebAssembly.CompileError,
+ /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/);
+ }
+}
+
+// Module doesn't have a memory
+{
+ for (let op of ['copy', 'fill']) {
+ let text =
+ `(module
+ (func (export "testfn")
+ (memory.${op} (i32.const 10) (i32.const 20) (i32.const 30))
+ )
+ )`;
+ assertErrorMessage(() => wasmEvalText(text),
+ WebAssembly.CompileError,
+ /(can't touch memory without memory)|(unknown memory)/);
+ }
+}
+
+//---------------------------------------------------------------------//
+//---------------------------------------------------------------------//
+// Run tests
+
+//-----------------------------------------------------------
+// Test helpers
+function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
+{
+ for (let i = minIx; i < maxIxPlusOne; i++) {
+ assertEq(arr[i], expectedValue);
+ }
+}
+
+//-----------------------------------------------------------
+// Test cases for memory.fill
+
+// Range valid
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0xFF00) (i32.const 0x55) (i32.const 256))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0x00000, 0x0FF00, 0x00);
+ checkRange(b, 0x0FF00, 0x10000, 0x55);
+}
+
+// Range invalid
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0xFF00) (i32.const 0x55) (i32.const 257))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Wraparound the end of 32-bit offset space
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0xFFFFFF00) (i32.const 0x55) (i32.const 257))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Zero len with offset in-bounds is a no-op
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0x12) (i32.const 0x55) (i32.const 0))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0x00000, 0x10000, 0x00);
+}
+
+// Zero len with offset out-of-bounds is OK
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0x10000) (i32.const 0x55) (i32.const 0))
+ )
+ )`
+ );
+ inst.exports.testfn();
+}
+
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0x10001) (i32.const 0x55) (i32.const 0))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Very large range
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0x1) (i32.const 0xAA) (i32.const 0xFFFE))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0x00000, 0x00001, 0x00);
+ checkRange(b, 0x00001, 0x0FFFF, 0xAA);
+ checkRange(b, 0x0FFFF, 0x10000, 0x00);
+}
+
+// Sequencing
+{
+ let i = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn") (result i32)
+ (memory.fill (i32.const 0x12) (i32.const 0x55) (i32.const 10))
+ (memory.fill (i32.const 0x15) (i32.const 0xAA) (i32.const 4))
+ i32.const 99
+ )
+ )`
+ );
+ i.exports.testfn();
+ let b = new Uint8Array(i.exports.memory.buffer);
+ checkRange(b, 0x0, 0x12+0, 0x00);
+ checkRange(b, 0x12+0, 0x12+3, 0x55);
+ checkRange(b, 0x12+3, 0x12+7, 0xAA);
+ checkRange(b, 0x12+7, 0x12+10, 0x55);
+ checkRange(b, 0x12+10, 0x10000, 0x00);
+}
+
+
+//-----------------------------------------------------------
+// Test cases for memory.copy
+
+// Both ranges valid. Copy 5 bytes backwards by 1 (overlapping).
+// result = 0x00--(09) 0x55--(11) 0x00--(pagesize-20)
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 10) (i32.const 0x55) (i32.const 10))
+ (memory.copy (i32.const 9) (i32.const 10) (i32.const 5))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0, 0+9, 0x00);
+ checkRange(b, 9, 9+11, 0x55);
+ checkRange(b, 9+11, 0x10000, 0x00);
+}
+
+// Both ranges valid. Copy 5 bytes forwards by 1 (overlapping).
+// result = 0x00--(10) 0x55--(11) 0x00--(pagesize-19)
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 10) (i32.const 0x55) (i32.const 10))
+ (memory.copy (i32.const 16) (i32.const 15) (i32.const 5))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0, 0+10, 0x00);
+ checkRange(b, 10, 10+11, 0x55);
+ checkRange(b, 10+11, 0x10000, 0x00);
+}
+
+// Destination range invalid
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0xFF00) (i32.const 0x8000) (i32.const 257))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Destination wraparound the end of 32-bit offset space
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0xFFFFFF00) (i32.const 0x4000) (i32.const 257))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Source range invalid
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0x8000) (i32.const 0xFF00) (i32.const 257))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Source wraparound the end of 32-bit offset space
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0x4000) (i32.const 0xFFFFFF00) (i32.const 257))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Zero len with both offsets in-bounds is a no-op
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 0x0000) (i32.const 0x55) (i32.const 0x8000))
+ (memory.fill (i32.const 0x8000) (i32.const 0xAA) (i32.const 0x8000))
+ (memory.copy (i32.const 0x9000) (i32.const 0x7000) (i32.const 0))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0x00000, 0x08000, 0x55);
+ checkRange(b, 0x08000, 0x10000, 0xAA);
+}
+
+// Zero len with dest offset out-of-bounds at the edge of memory
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0x10000) (i32.const 0x7000) (i32.const 0))
+ )
+ )`
+ );
+ inst.exports.testfn();
+}
+
+// Ditto, but one element further out
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0x10001) (i32.const 0x7000) (i32.const 0))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// Zero len with src offset out-of-bounds at the edge of memory
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0x9000) (i32.const 0x10000) (i32.const 0))
+ )
+ )`
+ );
+ inst.exports.testfn();
+}
+
+// Ditto, but one element further out
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.copy (i32.const 0x9000) (i32.const 0x10001) (i32.const 0))
+ )
+ )`
+ );
+ assertErrorMessage(() => inst.exports.testfn(),
+ WebAssembly.RuntimeError, /index out of bounds/);
+}
+
+// 100 random fills followed by 100 random copies, in a single-page buffer,
+// followed by verification of the (now heavily mashed-around) buffer.
+{
+ let inst = wasmEvalText(
+ `(module
+ (memory (export "memory") 1 1)
+ (func (export "testfn")
+ (memory.fill (i32.const 17767) (i32.const 1) (i32.const 1344))
+ (memory.fill (i32.const 39017) (i32.const 2) (i32.const 1055))
+ (memory.fill (i32.const 56401) (i32.const 3) (i32.const 988))
+ (memory.fill (i32.const 37962) (i32.const 4) (i32.const 322))
+ (memory.fill (i32.const 7977) (i32.const 5) (i32.const 1994))
+ (memory.fill (i32.const 22714) (i32.const 6) (i32.const 3036))
+ (memory.fill (i32.const 16882) (i32.const 7) (i32.const 2372))
+ (memory.fill (i32.const 43491) (i32.const 8) (i32.const 835))
+ (memory.fill (i32.const 124) (i32.const 9) (i32.const 1393))
+ (memory.fill (i32.const 2132) (i32.const 10) (i32.const 2758))
+ (memory.fill (i32.const 8987) (i32.const 11) (i32.const 3098))
+ (memory.fill (i32.const 52711) (i32.const 12) (i32.const 741))
+ (memory.fill (i32.const 3958) (i32.const 13) (i32.const 2823))
+ (memory.fill (i32.const 49715) (i32.const 14) (i32.const 1280))
+ (memory.fill (i32.const 50377) (i32.const 15) (i32.const 1466))
+ (memory.fill (i32.const 20493) (i32.const 16) (i32.const 3158))
+ (memory.fill (i32.const 47665) (i32.const 17) (i32.const 544))
+ (memory.fill (i32.const 12451) (i32.const 18) (i32.const 2669))
+ (memory.fill (i32.const 24869) (i32.const 19) (i32.const 2651))
+ (memory.fill (i32.const 45317) (i32.const 20) (i32.const 1570))
+ (memory.fill (i32.const 43096) (i32.const 21) (i32.const 1691))
+ (memory.fill (i32.const 33886) (i32.const 22) (i32.const 646))
+ (memory.fill (i32.const 48555) (i32.const 23) (i32.const 1858))
+ (memory.fill (i32.const 53453) (i32.const 24) (i32.const 2657))
+ (memory.fill (i32.const 30363) (i32.const 25) (i32.const 981))
+ (memory.fill (i32.const 9300) (i32.const 26) (i32.const 1807))
+ (memory.fill (i32.const 50190) (i32.const 27) (i32.const 487))
+ (memory.fill (i32.const 62753) (i32.const 28) (i32.const 530))
+ (memory.fill (i32.const 36316) (i32.const 29) (i32.const 943))
+ (memory.fill (i32.const 6768) (i32.const 30) (i32.const 381))
+ (memory.fill (i32.const 51262) (i32.const 31) (i32.const 3089))
+ (memory.fill (i32.const 49729) (i32.const 32) (i32.const 658))
+ (memory.fill (i32.const 44540) (i32.const 33) (i32.const 1702))
+ (memory.fill (i32.const 33342) (i32.const 34) (i32.const 1092))
+ (memory.fill (i32.const 50814) (i32.const 35) (i32.const 1410))
+ (memory.fill (i32.const 47594) (i32.const 36) (i32.const 2204))
+ (memory.fill (i32.const 54123) (i32.const 37) (i32.const 2394))
+ (memory.fill (i32.const 55183) (i32.const 38) (i32.const 250))
+ (memory.fill (i32.const 22620) (i32.const 39) (i32.const 2097))
+ (memory.fill (i32.const 17132) (i32.const 40) (i32.const 3264))
+ (memory.fill (i32.const 54331) (i32.const 41) (i32.const 3299))
+ (memory.fill (i32.const 39474) (i32.const 42) (i32.const 2796))
+ (memory.fill (i32.const 36156) (i32.const 43) (i32.const 2070))
+ (memory.fill (i32.const 35308) (i32.const 44) (i32.const 2763))
+ (memory.fill (i32.const 32731) (i32.const 45) (i32.const 312))
+ (memory.fill (i32.const 63746) (i32.const 46) (i32.const 192))
+ (memory.fill (i32.const 30974) (i32.const 47) (i32.const 596))
+ (memory.fill (i32.const 16635) (i32.const 48) (i32.const 501))
+ (memory.fill (i32.const 57002) (i32.const 49) (i32.const 686))
+ (memory.fill (i32.const 34299) (i32.const 50) (i32.const 385))
+ (memory.fill (i32.const 60881) (i32.const 51) (i32.const 903))
+ (memory.fill (i32.const 61445) (i32.const 52) (i32.const 2390))
+ (memory.fill (i32.const 46972) (i32.const 53) (i32.const 1441))
+ (memory.fill (i32.const 25973) (i32.const 54) (i32.const 3162))
+ (memory.fill (i32.const 5566) (i32.const 55) (i32.const 2135))
+ (memory.fill (i32.const 35977) (i32.const 56) (i32.const 519))
+ (memory.fill (i32.const 44892) (i32.const 57) (i32.const 3280))
+ (memory.fill (i32.const 46760) (i32.const 58) (i32.const 1678))
+ (memory.fill (i32.const 46607) (i32.const 59) (i32.const 3168))
+ (memory.fill (i32.const 22449) (i32.const 60) (i32.const 1441))
+ (memory.fill (i32.const 58609) (i32.const 61) (i32.const 663))
+ (memory.fill (i32.const 32261) (i32.const 62) (i32.const 1671))
+ (memory.fill (i32.const 3063) (i32.const 63) (i32.const 721))
+ (memory.fill (i32.const 34025) (i32.const 64) (i32.const 84))
+ (memory.fill (i32.const 33338) (i32.const 65) (i32.const 2029))
+ (memory.fill (i32.const 36810) (i32.const 66) (i32.const 29))
+ (memory.fill (i32.const 19147) (i32.const 67) (i32.const 3034))
+ (memory.fill (i32.const 12616) (i32.const 68) (i32.const 1043))
+ (memory.fill (i32.const 18276) (i32.const 69) (i32.const 3324))
+ (memory.fill (i32.const 4639) (i32.const 70) (i32.const 1091))
+ (memory.fill (i32.const 16158) (i32.const 71) (i32.const 1997))
+ (memory.fill (i32.const 18204) (i32.const 72) (i32.const 2259))
+ (memory.fill (i32.const 50532) (i32.const 73) (i32.const 3189))
+ (memory.fill (i32.const 11028) (i32.const 74) (i32.const 1968))
+ (memory.fill (i32.const 15962) (i32.const 75) (i32.const 1455))
+ (memory.fill (i32.const 45406) (i32.const 76) (i32.const 1177))
+ (memory.fill (i32.const 54137) (i32.const 77) (i32.const 1568))
+ (memory.fill (i32.const 33083) (i32.const 78) (i32.const 1642))
+ (memory.fill (i32.const 61028) (i32.const 79) (i32.const 3284))
+ (memory.fill (i32.const 51729) (i32.const 80) (i32.const 223))
+ (memory.fill (i32.const 4361) (i32.const 81) (i32.const 2171))
+ (memory.fill (i32.const 57514) (i32.const 82) (i32.const 1322))
+ (memory.fill (i32.const 55724) (i32.const 83) (i32.const 2648))
+ (memory.fill (i32.const 24091) (i32.const 84) (i32.const 1045))
+ (memory.fill (i32.const 43183) (i32.const 85) (i32.const 3097))
+ (memory.fill (i32.const 32307) (i32.const 86) (i32.const 2796))
+ (memory.fill (i32.const 3811) (i32.const 87) (i32.const 2010))
+ (memory.fill (i32.const 54856) (i32.const 88) (i32.const 0))
+ (memory.fill (i32.const 49941) (i32.const 89) (i32.const 2069))
+ (memory.fill (i32.const 20411) (i32.const 90) (i32.const 2896))
+ (memory.fill (i32.const 33826) (i32.const 91) (i32.const 192))
+ (memory.fill (i32.const 9402) (i32.const 92) (i32.const 2195))
+ (memory.fill (i32.const 12413) (i32.const 93) (i32.const 24))
+ (memory.fill (i32.const 14091) (i32.const 94) (i32.const 577))
+ (memory.fill (i32.const 44058) (i32.const 95) (i32.const 2089))
+ (memory.fill (i32.const 36735) (i32.const 96) (i32.const 3436))
+ (memory.fill (i32.const 23288) (i32.const 97) (i32.const 2765))
+ (memory.fill (i32.const 6392) (i32.const 98) (i32.const 830))
+ (memory.fill (i32.const 33307) (i32.const 99) (i32.const 1938))
+ (memory.fill (i32.const 21941) (i32.const 100) (i32.const 2750))
+ (memory.copy (i32.const 59214) (i32.const 54248) (i32.const 2098))
+ (memory.copy (i32.const 63026) (i32.const 39224) (i32.const 230))
+ (memory.copy (i32.const 51833) (i32.const 23629) (i32.const 2300))
+ (memory.copy (i32.const 6708) (i32.const 23996) (i32.const 639))
+ (memory.copy (i32.const 6990) (i32.const 33399) (i32.const 1097))
+ (memory.copy (i32.const 19403) (i32.const 10348) (i32.const 3197))
+ (memory.copy (i32.const 27308) (i32.const 54406) (i32.const 100))
+ (memory.copy (i32.const 27221) (i32.const 43682) (i32.const 1717))
+ (memory.copy (i32.const 60528) (i32.const 8629) (i32.const 119))
+ (memory.copy (i32.const 5947) (i32.const 2308) (i32.const 658))
+ (memory.copy (i32.const 4787) (i32.const 51631) (i32.const 2269))
+ (memory.copy (i32.const 12617) (i32.const 19197) (i32.const 833))
+ (memory.copy (i32.const 11854) (i32.const 46505) (i32.const 3300))
+ (memory.copy (i32.const 11376) (i32.const 45012) (i32.const 2281))
+ (memory.copy (i32.const 34186) (i32.const 6697) (i32.const 2572))
+ (memory.copy (i32.const 4936) (i32.const 1690) (i32.const 1328))
+ (memory.copy (i32.const 63164) (i32.const 7637) (i32.const 1670))
+ (memory.copy (i32.const 44568) (i32.const 18344) (i32.const 33))
+ (memory.copy (i32.const 43918) (i32.const 22348) (i32.const 1427))
+ (memory.copy (i32.const 46637) (i32.const 49819) (i32.const 1434))
+ (memory.copy (i32.const 63684) (i32.const 8755) (i32.const 834))
+ (memory.copy (i32.const 33485) (i32.const 20131) (i32.const 3317))
+ (memory.copy (i32.const 40575) (i32.const 54317) (i32.const 3201))
+ (memory.copy (i32.const 25812) (i32.const 59254) (i32.const 2452))
+ (memory.copy (i32.const 19678) (i32.const 56882) (i32.const 346))
+ (memory.copy (i32.const 15852) (i32.const 35914) (i32.const 2430))
+ (memory.copy (i32.const 11824) (i32.const 35574) (i32.const 300))
+ (memory.copy (i32.const 59427) (i32.const 13957) (i32.const 3153))
+ (memory.copy (i32.const 34299) (i32.const 60594) (i32.const 1281))
+ (memory.copy (i32.const 8964) (i32.const 12276) (i32.const 943))
+ (memory.copy (i32.const 2827) (i32.const 10425) (i32.const 1887))
+ (memory.copy (i32.const 43194) (i32.const 43910) (i32.const 738))
+ (memory.copy (i32.const 63038) (i32.const 18949) (i32.const 122))
+ (memory.copy (i32.const 24044) (i32.const 44761) (i32.const 1755))
+ (memory.copy (i32.const 22608) (i32.const 14755) (i32.const 702))
+ (memory.copy (i32.const 11284) (i32.const 26579) (i32.const 1830))
+ (memory.copy (i32.const 23092) (i32.const 20471) (i32.const 1064))
+ (memory.copy (i32.const 57248) (i32.const 54770) (i32.const 2631))
+ (memory.copy (i32.const 25492) (i32.const 1025) (i32.const 3113))
+ (memory.copy (i32.const 49588) (i32.const 44220) (i32.const 975))
+ (memory.copy (i32.const 28280) (i32.const 41722) (i32.const 2336))
+ (memory.copy (i32.const 61289) (i32.const 230) (i32.const 2872))
+ (memory.copy (i32.const 22480) (i32.const 52506) (i32.const 2197))
+ (memory.copy (i32.const 40553) (i32.const 9578) (i32.const 1958))
+ (memory.copy (i32.const 29004) (i32.const 20862) (i32.const 2186))
+ (memory.copy (i32.const 53029) (i32.const 43955) (i32.const 1037))
+ (memory.copy (i32.const 25476) (i32.const 35667) (i32.const 1650))
+ (memory.copy (i32.const 58516) (i32.const 45819) (i32.const 1986))
+ (memory.copy (i32.const 38297) (i32.const 5776) (i32.const 1955))
+ (memory.copy (i32.const 28503) (i32.const 55364) (i32.const 2368))
+ (memory.copy (i32.const 62619) (i32.const 18108) (i32.const 1356))
+ (memory.copy (i32.const 50149) (i32.const 13861) (i32.const 382))
+ (memory.copy (i32.const 16904) (i32.const 36341) (i32.const 1900))
+ (memory.copy (i32.const 48098) (i32.const 11358) (i32.const 2807))
+ (memory.copy (i32.const 28512) (i32.const 40362) (i32.const 323))
+ (memory.copy (i32.const 35506) (i32.const 27856) (i32.const 1670))
+ (memory.copy (i32.const 62970) (i32.const 53332) (i32.const 1341))
+ (memory.copy (i32.const 14133) (i32.const 46312) (i32.const 644))
+ (memory.copy (i32.const 29030) (i32.const 19074) (i32.const 496))
+ (memory.copy (i32.const 44952) (i32.const 47577) (i32.const 2784))
+ (memory.copy (i32.const 39559) (i32.const 44661) (i32.const 1350))
+ (memory.copy (i32.const 10352) (i32.const 29274) (i32.const 1475))
+ (memory.copy (i32.const 46911) (i32.const 46178) (i32.const 1467))
+ (memory.copy (i32.const 4905) (i32.const 28740) (i32.const 1895))
+ (memory.copy (i32.const 38012) (i32.const 57253) (i32.const 1751))
+ (memory.copy (i32.const 26446) (i32.const 27223) (i32.const 1127))
+ (memory.copy (i32.const 58835) (i32.const 24657) (i32.const 1063))
+ (memory.copy (i32.const 61356) (i32.const 38790) (i32.const 766))
+ (memory.copy (i32.const 44160) (i32.const 2284) (i32.const 1520))
+ (memory.copy (i32.const 32740) (i32.const 47237) (i32.const 3014))
+ (memory.copy (i32.const 11148) (i32.const 21260) (i32.const 1011))
+ (memory.copy (i32.const 7665) (i32.const 31612) (i32.const 3034))
+ (memory.copy (i32.const 18044) (i32.const 12987) (i32.const 3320))
+ (memory.copy (i32.const 57306) (i32.const 55905) (i32.const 308))
+ (memory.copy (i32.const 24675) (i32.const 16815) (i32.const 1155))
+ (memory.copy (i32.const 19900) (i32.const 10115) (i32.const 722))
+ (memory.copy (i32.const 2921) (i32.const 5935) (i32.const 2370))
+ (memory.copy (i32.const 32255) (i32.const 50095) (i32.const 2926))
+ (memory.copy (i32.const 15126) (i32.const 17299) (i32.const 2607))
+ (memory.copy (i32.const 45575) (i32.const 28447) (i32.const 2045))
+ (memory.copy (i32.const 55149) (i32.const 36113) (i32.const 2596))
+ (memory.copy (i32.const 28461) (i32.const 54157) (i32.const 1168))
+ (memory.copy (i32.const 47951) (i32.const 53385) (i32.const 3137))
+ (memory.copy (i32.const 30646) (i32.const 45155) (i32.const 2649))
+ (memory.copy (i32.const 5057) (i32.const 4295) (i32.const 52))
+ (memory.copy (i32.const 6692) (i32.const 24195) (i32.const 441))
+ (memory.copy (i32.const 32984) (i32.const 27117) (i32.const 3445))
+ (memory.copy (i32.const 32530) (i32.const 59372) (i32.const 2785))
+ (memory.copy (i32.const 34361) (i32.const 8962) (i32.const 2406))
+ (memory.copy (i32.const 17893) (i32.const 54538) (i32.const 3381))
+ (memory.copy (i32.const 22685) (i32.const 44151) (i32.const 136))
+ (memory.copy (i32.const 59089) (i32.const 7077) (i32.const 1045))
+ (memory.copy (i32.const 42945) (i32.const 55028) (i32.const 2389))
+ (memory.copy (i32.const 44693) (i32.const 20138) (i32.const 877))
+ (memory.copy (i32.const 36810) (i32.const 25196) (i32.const 3447))
+ (memory.copy (i32.const 45742) (i32.const 31888) (i32.const 854))
+ (memory.copy (i32.const 24236) (i32.const 31866) (i32.const 1377))
+ (memory.copy (i32.const 33778) (i32.const 692) (i32.const 1594))
+ (memory.copy (i32.const 60618) (i32.const 18585) (i32.const 2987))
+ (memory.copy (i32.const 50370) (i32.const 41271) (i32.const 1406))
+ )
+ )`
+ );
+ inst.exports.testfn();
+ let b = new Uint8Array(inst.exports.memory.buffer);
+ checkRange(b, 0, 124, 0);
+ checkRange(b, 124, 1517, 9);
+ checkRange(b, 1517, 2132, 0);
+ checkRange(b, 2132, 2827, 10);
+ checkRange(b, 2827, 2921, 92);
+ checkRange(b, 2921, 3538, 83);
+ checkRange(b, 3538, 3786, 77);
+ checkRange(b, 3786, 4042, 97);
+ checkRange(b, 4042, 4651, 99);
+ checkRange(b, 4651, 5057, 0);
+ checkRange(b, 5057, 5109, 99);
+ checkRange(b, 5109, 5291, 0);
+ checkRange(b, 5291, 5524, 72);
+ checkRange(b, 5524, 5691, 92);
+ checkRange(b, 5691, 6552, 83);
+ checkRange(b, 6552, 7133, 77);
+ checkRange(b, 7133, 7665, 99);
+ checkRange(b, 7665, 8314, 0);
+ checkRange(b, 8314, 8360, 62);
+ checkRange(b, 8360, 8793, 86);
+ checkRange(b, 8793, 8979, 83);
+ checkRange(b, 8979, 9373, 79);
+ checkRange(b, 9373, 9518, 95);
+ checkRange(b, 9518, 9934, 59);
+ checkRange(b, 9934, 10087, 77);
+ checkRange(b, 10087, 10206, 5);
+ checkRange(b, 10206, 10230, 77);
+ checkRange(b, 10230, 10249, 41);
+ checkRange(b, 10249, 11148, 83);
+ checkRange(b, 11148, 11356, 74);
+ checkRange(b, 11356, 11380, 93);
+ checkRange(b, 11380, 11939, 74);
+ checkRange(b, 11939, 12159, 68);
+ checkRange(b, 12159, 12575, 83);
+ checkRange(b, 12575, 12969, 79);
+ checkRange(b, 12969, 13114, 95);
+ checkRange(b, 13114, 14133, 59);
+ checkRange(b, 14133, 14404, 76);
+ checkRange(b, 14404, 14428, 57);
+ checkRange(b, 14428, 14458, 59);
+ checkRange(b, 14458, 14580, 32);
+ checkRange(b, 14580, 14777, 89);
+ checkRange(b, 14777, 15124, 59);
+ checkRange(b, 15124, 15126, 36);
+ checkRange(b, 15126, 15192, 100);
+ checkRange(b, 15192, 15871, 96);
+ checkRange(b, 15871, 15998, 95);
+ checkRange(b, 15998, 17017, 59);
+ checkRange(b, 17017, 17288, 76);
+ checkRange(b, 17288, 17312, 57);
+ checkRange(b, 17312, 17342, 59);
+ checkRange(b, 17342, 17464, 32);
+ checkRange(b, 17464, 17661, 89);
+ checkRange(b, 17661, 17727, 59);
+ checkRange(b, 17727, 17733, 5);
+ checkRange(b, 17733, 17893, 96);
+ checkRange(b, 17893, 18553, 77);
+ checkRange(b, 18553, 18744, 42);
+ checkRange(b, 18744, 18801, 76);
+ checkRange(b, 18801, 18825, 57);
+ checkRange(b, 18825, 18876, 59);
+ checkRange(b, 18876, 18885, 77);
+ checkRange(b, 18885, 18904, 41);
+ checkRange(b, 18904, 19567, 83);
+ checkRange(b, 19567, 20403, 96);
+ checkRange(b, 20403, 21274, 77);
+ checkRange(b, 21274, 21364, 100);
+ checkRange(b, 21364, 21468, 74);
+ checkRange(b, 21468, 21492, 93);
+ checkRange(b, 21492, 22051, 74);
+ checkRange(b, 22051, 22480, 68);
+ checkRange(b, 22480, 22685, 100);
+ checkRange(b, 22685, 22694, 68);
+ checkRange(b, 22694, 22821, 10);
+ checkRange(b, 22821, 22869, 100);
+ checkRange(b, 22869, 24107, 97);
+ checkRange(b, 24107, 24111, 37);
+ checkRange(b, 24111, 24236, 77);
+ checkRange(b, 24236, 24348, 72);
+ checkRange(b, 24348, 24515, 92);
+ checkRange(b, 24515, 24900, 83);
+ checkRange(b, 24900, 25136, 95);
+ checkRange(b, 25136, 25182, 85);
+ checkRange(b, 25182, 25426, 68);
+ checkRange(b, 25426, 25613, 89);
+ checkRange(b, 25613, 25830, 96);
+ checkRange(b, 25830, 26446, 100);
+ checkRange(b, 26446, 26517, 10);
+ checkRange(b, 26517, 27468, 92);
+ checkRange(b, 27468, 27503, 95);
+ checkRange(b, 27503, 27573, 77);
+ checkRange(b, 27573, 28245, 92);
+ checkRange(b, 28245, 28280, 95);
+ checkRange(b, 28280, 29502, 77);
+ checkRange(b, 29502, 29629, 42);
+ checkRange(b, 29629, 30387, 83);
+ checkRange(b, 30387, 30646, 77);
+ checkRange(b, 30646, 31066, 92);
+ checkRange(b, 31066, 31131, 77);
+ checkRange(b, 31131, 31322, 42);
+ checkRange(b, 31322, 31379, 76);
+ checkRange(b, 31379, 31403, 57);
+ checkRange(b, 31403, 31454, 59);
+ checkRange(b, 31454, 31463, 77);
+ checkRange(b, 31463, 31482, 41);
+ checkRange(b, 31482, 31649, 83);
+ checkRange(b, 31649, 31978, 72);
+ checkRange(b, 31978, 32145, 92);
+ checkRange(b, 32145, 32530, 83);
+ checkRange(b, 32530, 32766, 95);
+ checkRange(b, 32766, 32812, 85);
+ checkRange(b, 32812, 33056, 68);
+ checkRange(b, 33056, 33660, 89);
+ checkRange(b, 33660, 33752, 59);
+ checkRange(b, 33752, 33775, 36);
+ checkRange(b, 33775, 33778, 32);
+ checkRange(b, 33778, 34603, 9);
+ checkRange(b, 34603, 35218, 0);
+ checkRange(b, 35218, 35372, 10);
+ checkRange(b, 35372, 35486, 77);
+ checkRange(b, 35486, 35605, 5);
+ checkRange(b, 35605, 35629, 77);
+ checkRange(b, 35629, 35648, 41);
+ checkRange(b, 35648, 36547, 83);
+ checkRange(b, 36547, 36755, 74);
+ checkRange(b, 36755, 36767, 93);
+ checkRange(b, 36767, 36810, 83);
+ checkRange(b, 36810, 36839, 100);
+ checkRange(b, 36839, 37444, 96);
+ checkRange(b, 37444, 38060, 100);
+ checkRange(b, 38060, 38131, 10);
+ checkRange(b, 38131, 39082, 92);
+ checkRange(b, 39082, 39117, 95);
+ checkRange(b, 39117, 39187, 77);
+ checkRange(b, 39187, 39859, 92);
+ checkRange(b, 39859, 39894, 95);
+ checkRange(b, 39894, 40257, 77);
+ checkRange(b, 40257, 40344, 89);
+ checkRange(b, 40344, 40371, 59);
+ checkRange(b, 40371, 40804, 77);
+ checkRange(b, 40804, 40909, 5);
+ checkRange(b, 40909, 42259, 92);
+ checkRange(b, 42259, 42511, 77);
+ checkRange(b, 42511, 42945, 83);
+ checkRange(b, 42945, 43115, 77);
+ checkRange(b, 43115, 43306, 42);
+ checkRange(b, 43306, 43363, 76);
+ checkRange(b, 43363, 43387, 57);
+ checkRange(b, 43387, 43438, 59);
+ checkRange(b, 43438, 43447, 77);
+ checkRange(b, 43447, 43466, 41);
+ checkRange(b, 43466, 44129, 83);
+ checkRange(b, 44129, 44958, 96);
+ checkRange(b, 44958, 45570, 77);
+ checkRange(b, 45570, 45575, 92);
+ checkRange(b, 45575, 45640, 77);
+ checkRange(b, 45640, 45742, 42);
+ checkRange(b, 45742, 45832, 72);
+ checkRange(b, 45832, 45999, 92);
+ checkRange(b, 45999, 46384, 83);
+ checkRange(b, 46384, 46596, 95);
+ checkRange(b, 46596, 46654, 92);
+ checkRange(b, 46654, 47515, 83);
+ checkRange(b, 47515, 47620, 77);
+ checkRange(b, 47620, 47817, 79);
+ checkRange(b, 47817, 47951, 95);
+ checkRange(b, 47951, 48632, 100);
+ checkRange(b, 48632, 48699, 97);
+ checkRange(b, 48699, 48703, 37);
+ checkRange(b, 48703, 49764, 77);
+ checkRange(b, 49764, 49955, 42);
+ checkRange(b, 49955, 50012, 76);
+ checkRange(b, 50012, 50036, 57);
+ checkRange(b, 50036, 50087, 59);
+ checkRange(b, 50087, 50096, 77);
+ checkRange(b, 50096, 50115, 41);
+ checkRange(b, 50115, 50370, 83);
+ checkRange(b, 50370, 51358, 92);
+ checkRange(b, 51358, 51610, 77);
+ checkRange(b, 51610, 51776, 83);
+ checkRange(b, 51776, 51833, 89);
+ checkRange(b, 51833, 52895, 100);
+ checkRange(b, 52895, 53029, 97);
+ checkRange(b, 53029, 53244, 68);
+ checkRange(b, 53244, 54066, 100);
+ checkRange(b, 54066, 54133, 97);
+ checkRange(b, 54133, 54137, 37);
+ checkRange(b, 54137, 55198, 77);
+ checkRange(b, 55198, 55389, 42);
+ checkRange(b, 55389, 55446, 76);
+ checkRange(b, 55446, 55470, 57);
+ checkRange(b, 55470, 55521, 59);
+ checkRange(b, 55521, 55530, 77);
+ checkRange(b, 55530, 55549, 41);
+ checkRange(b, 55549, 56212, 83);
+ checkRange(b, 56212, 57048, 96);
+ checkRange(b, 57048, 58183, 77);
+ checkRange(b, 58183, 58202, 41);
+ checkRange(b, 58202, 58516, 83);
+ checkRange(b, 58516, 58835, 95);
+ checkRange(b, 58835, 58855, 77);
+ checkRange(b, 58855, 59089, 95);
+ checkRange(b, 59089, 59145, 77);
+ checkRange(b, 59145, 59677, 99);
+ checkRange(b, 59677, 60134, 0);
+ checkRange(b, 60134, 60502, 89);
+ checkRange(b, 60502, 60594, 59);
+ checkRange(b, 60594, 60617, 36);
+ checkRange(b, 60617, 60618, 32);
+ checkRange(b, 60618, 60777, 42);
+ checkRange(b, 60777, 60834, 76);
+ checkRange(b, 60834, 60858, 57);
+ checkRange(b, 60858, 60909, 59);
+ checkRange(b, 60909, 60918, 77);
+ checkRange(b, 60918, 60937, 41);
+ checkRange(b, 60937, 61600, 83);
+ checkRange(b, 61600, 62436, 96);
+ checkRange(b, 62436, 63307, 77);
+ checkRange(b, 63307, 63397, 100);
+ checkRange(b, 63397, 63501, 74);
+ checkRange(b, 63501, 63525, 93);
+ checkRange(b, 63525, 63605, 74);
+ checkRange(b, 63605, 63704, 100);
+ checkRange(b, 63704, 63771, 97);
+ checkRange(b, 63771, 63775, 37);
+ checkRange(b, 63775, 64311, 77);
+ checkRange(b, 64311, 64331, 26);
+ checkRange(b, 64331, 64518, 92);
+ checkRange(b, 64518, 64827, 11);
+ checkRange(b, 64827, 64834, 26);
+ checkRange(b, 64834, 65536, 0);
+}
+
+// Make sure dead code doesn't prevent compilation.
+wasmEvalText(
+ `(module
+ (memory 0 10)
+ (data (i32.const 0))
+ (func
+ (return)
+ (memory.init 0)
+ )
+ )`);
+
+wasmEvalText(
+ `(module
+ (memory 0 10)
+ (func
+ (return)
+ (memory.fill)
+ )
+ )`);
+
+wasmEvalText(
+ `(module
+ (table (export "t") 10 funcref)
+ (elem (i32.const 0) 0)
+ (func
+ (return)
+ (elem.drop 0)
+ )
+ )`);