diff options
Diffstat (limited to 'js/src/jit-test/tests/wasm/passive-segs-partial-table.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/passive-segs-partial-table.js | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/passive-segs-partial-table.js b/js/src/jit-test/tests/wasm/passive-segs-partial-table.js new file mode 100644 index 0000000000..2d2e8fcf72 --- /dev/null +++ b/js/src/jit-test/tests/wasm/passive-segs-partial-table.js @@ -0,0 +1,153 @@ +// Sundry test cases for the "partial write" bounds checking semantics. + +// table.init: out of bounds of the table or the element segment, and should +// not perform the operation at all. +// +// Arithmetic overflow of tableoffset + len or of segmentoffset + len should not +// affect the behavior. + +// Note, the length of the element segment is 16. +const tbl_init_len = 16; + +function tbl_init(min, max, backup, write, segoffs=0) { + let ins = wasmEvalText( + `(module + (table (export "tbl") ${min} ${max} funcref) + (elem func $f0 $f1 $f2 $f3 $f4 $f5 $f6 $f7 $f8 $f9 $f10 $f11 $f12 $f13 $f14 $f15) + (func $f0 (export "f0")) + (func $f1 (export "f1")) + (func $f2 (export "f2")) + (func $f3 (export "f3")) + (func $f4 (export "f4")) + (func $f5 (export "f5")) + (func $f6 (export "f6")) + (func $f7 (export "f7")) + (func $f8 (export "f8")) + (func $f9 (export "f9")) + (func $f10 (export "f10")) + (func $f11 (export "f11")) + (func $f12 (export "f12")) + (func $f13 (export "f13")) + (func $f14 (export "f14")) + (func $f15 (export "f15")) + (func (export "run") (param $offs i32) (param $len i32) + (table.init 0 (local.get $offs) (i32.const ${segoffs}) (local.get $len))))`); + // A fill writing past the end of the table should throw *and* have filled + // all the way up to the end. + // + // A fill reading past the end of the segment should throw *and* have filled + // table with as much data as was available. + let offs = min - backup; + assertErrorMessage(() => ins.exports.run(offs, write), + WebAssembly.RuntimeError, + /index out of bounds/); + let tbl = ins.exports.tbl; + for (let i=0; i < min; i++) { + assertEq(tbl.get(i), null); + } +} + +// We exceed the bounds of the table but not of the element segment +tbl_init(tbl_init_len*2, tbl_init_len*4, Math.floor(tbl_init_len/2), tbl_init_len); +tbl_init(tbl_init_len*2, tbl_init_len*4, Math.floor(tbl_init_len/2)-1, tbl_init_len); + +// We exceed the bounds of the element segment but not the table +tbl_init(tbl_init_len*10, tbl_init_len*20, tbl_init_len*4, tbl_init_len*2); +tbl_init(tbl_init_len*10, tbl_init_len*20, tbl_init_len*4-1, tbl_init_len*2-1); + +// We arithmetically overflow the table limit but not the segment limit +tbl_init(tbl_init_len*4, tbl_init_len*4, tbl_init_len, 0xFFFFFFF0); + +// We arithmetically overflow the segment limit but not the table limit +tbl_init(tbl_init_len, tbl_init_len, tbl_init_len, 0xFFFFFFFC, Math.floor(tbl_init_len/2)); + +// table.copy: out of bounds of the table for the source or target, and should +// perform the operation at all. Major cases: +// +// - non-overlapping regions +// - overlapping regions with src > dest +// - overlapping regions with src == dest +// - overlapping regions with src < dest +// - arithmetic overflow on src addresses +// - arithmetic overflow on target addresses +// +// for each of those, +// +// - src address oob +// - target address oob +// - both oob +// +// Note we do not test the multi-table case here because that is part of the +// reftypes proposal; tests are in the gc/ subdirectory. + +const tbl_copy_len = 16; + +function tbl_copy(min, max, srcOffs, targetOffs, len) { + let ins = wasmEvalText( + `(module + (table (export "tbl") ${min} ${max} funcref) + (func $f0 (export "f0")) + (func $f1 (export "f1")) + (func $f2 (export "f2")) + (func $f3 (export "f3")) + (func $f4 (export "f4")) + (func $f5 (export "f5")) + (func $f6 (export "f6")) + (func $f7 (export "f7")) + (func $f8 (export "f8")) + (func $f9 (export "f9")) + (func $f10 (export "f10")) + (func $f11 (export "f11")) + (func $f12 (export "f12")) + (func $f13 (export "f13")) + (func $f14 (export "f14")) + (func $f15 (export "f15")) + (func (export "run") (param $targetOffs i32) (param $srcOffs i32) (param $len i32) + (table.copy (local.get $targetOffs) (local.get $srcOffs) (local.get $len))))`); + + let tbl = ins.exports.tbl; + + let copyDown = srcOffs < targetOffs; + let targetAvail = tbl.length - targetOffs; + let srcAvail = tbl.length - srcOffs; + let srcLim = srcOffs + Math.min(len, targetAvail, srcAvail); + + for (let i=srcOffs, j=0; i < srcLim; i++, j++) + tbl.set(i, ins.exports["f" + j]); + assertErrorMessage(() => ins.exports.run(targetOffs, srcOffs, len), + WebAssembly.RuntimeError, + /index out of bounds/); + + for (var i=0, s=0; i < tbl.length; i++ ) { + if (i >= srcOffs && i < srcLim) { + assertEq(tbl.get(i), ins.exports["f" + (s++)]); + continue; + } + assertEq(tbl.get(i), null); + } +} + +// OOB target address, nonoverlapping +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, 0, Math.floor(1.5*tbl_copy_len), tbl_copy_len); +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, 0, Math.floor(1.5*tbl_copy_len)-1, tbl_copy_len-1); + +// OOB source address, nonoverlapping +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len), 0, tbl_copy_len); +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len)-1, 0, tbl_copy_len-1); + +// OOB target address, overlapping, src < target +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, tbl_copy_len-5, Math.floor(1.5*tbl_copy_len), tbl_copy_len); + +// OOB source address, overlapping, target < src +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len), tbl_copy_len-5, tbl_copy_len); + +// OOB both, overlapping, including src == target +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, tbl_copy_len+5, Math.floor(1.5*tbl_copy_len), tbl_copy_len); +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len), tbl_copy_len+5, tbl_copy_len); +tbl_copy(tbl_copy_len*2, tbl_copy_len*4, tbl_copy_len+5, tbl_copy_len+5, tbl_copy_len); + +// Arithmetic overflow on source address. +tbl_copy(tbl_copy_len*8, tbl_copy_len*8, tbl_copy_len*7, 0, 0xFFFFFFE0); + +// Arithmetic overflow on target adddress is an overlapping case. +tbl_copy(tbl_copy_len*8, tbl_copy_len*8, 0, tbl_copy_len*7, 0xFFFFFFE0); |