diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/jit-test/tests/wasm/memory-partial-oob-store.js | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/wasm/memory-partial-oob-store.js')
-rw-r--r-- | js/src/jit-test/tests/wasm/memory-partial-oob-store.js | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/memory-partial-oob-store.js b/js/src/jit-test/tests/wasm/memory-partial-oob-store.js new file mode 100644 index 0000000000..d017f8eafb --- /dev/null +++ b/js/src/jit-test/tests/wasm/memory-partial-oob-store.js @@ -0,0 +1,129 @@ +// Cloned from memory.js but kept separate because it may have to be disabled on +// some devices until bugs are fixed. + +// Bug 1666747 - partially OOB unaligned stores are not handled correctly on ARM +// and ARM64. The simulators don't implement the correct semantics anyhow, so +// when the bug is fixed in the code generator they must remain excluded here. +var conf = getBuildConfiguration(); +var excluded = conf.arm64 || conf["arm64-simulator"] || conf.arm || conf["arm-simulator"]; +var thirtytwobit = conf["pointer-byte-size"] == 4; + +const RuntimeError = WebAssembly.RuntimeError; + +function storeModuleSrc(type, ext, offset, align) { + var load_ext = ext === '' ? '' : ext + '_s'; + return `(module + (memory (export "mem") 1) + (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f") + (data (i32.const 16) "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff") + (func $store (param i32) (param ${type}) + (${type}.store${ext} + offset=${offset} + ${align != 0 ? 'align=' + align : ''} + (local.get 0) + (local.get 1) + ) + ) (export "store" (func 0)) + (func $load (param i32) (result ${type}) + (${type}.load${load_ext} + offset=${offset} + ${align != 0 ? 'align=' + align : ''} + (local.get 0) + ) + ) (export "load" (func 1)))`; +} + +function storeModule(type, ext, offset, align, exportBox = null) { + let exports = wasmEvalText(storeModuleSrc(type, ext, offset, align)).exports; + if (exportBox !== null) + exportBox.exports = exports; + return exports; +} + +function testStoreOOB(type, ext, base, offset, align, value) { + let exportBox = {}; + if (type === 'i64') { + assertErrorMessage(() => wasmAssert( + storeModuleSrc(type, ext, offset, align), + [{type, func: '$store', args: [`i32.const ${base}`, `i64.const ${value}`]}], + {}, + exportBox + ), RuntimeError, /index out of bounds/); + } else { + assertErrorMessage(() => storeModule(type, ext, offset, align, exportBox).store(base, value), + RuntimeError, + /index out of bounds/); + } + + // Check that there were no partial writes at the end of the memory. + let buf = new Int8Array(exportBox.exports.mem.buffer); + let len = buf.length; + for ( let addr = base + offset ; addr < len; addr++ ) + assertEq(buf[addr], 0); +} + +// Test bounds checks and edge cases. + +for (let align of [0,1,2,4]) { + + for (let offset of [0, 1, 2, 3, 4, 8, 16, 41, 0xfff0, 0xfff8]) { + // Accesses of 1 byte. + let lastValidIndex = 0x10000 - 1 - offset; + if (align < 2 && !excluded) { + testStoreOOB('i32', '8', lastValidIndex + 1, offset, align, -42); + } + + // Accesses of 2 bytes. + lastValidIndex = 0x10000 - 2 - offset; + if (align < 4 && !excluded) { + testStoreOOB('i32', '16', lastValidIndex + 1, offset, align, -32768); + } + + // Accesses of 4 bytes. + lastValidIndex = 0x10000 - 4 - offset; + if (!excluded) { + testStoreOOB('i32', '', lastValidIndex + 1, offset, align, 1337); + testStoreOOB('f32', '', lastValidIndex + 1, offset, align, Math.fround(13.37)); + } + + // Accesses of 8 bytes. + lastValidIndex = 0x10000 - 8 - offset; + if (!excluded) { + testStoreOOB('f64', '', lastValidIndex + 1, offset, align, 1.23456789); + } + } + + for (let offset of [0, 1, 2, 3, 4, 8, 16, 41, 0xfff0, 0xfff8]) { + // Accesses of 1 byte. + let lastValidIndex = 0x10000 - 1 - offset; + if (align < 2 && !excluded) { + testStoreOOB('i64', '8', lastValidIndex + 1, offset, align, -42); + } + + // Accesses of 2 bytes. + lastValidIndex = 0x10000 - 2 - offset; + if (align < 4 && !excluded) { + testStoreOOB('i64', '16', lastValidIndex + 1, offset, align, -32768); + } + + // Accesses of 4 bytes. + lastValidIndex = 0x10000 - 4 - offset; + if (!excluded) { + testStoreOOB('i64', '32', lastValidIndex + 1, offset, align, 0xf1231337 | 0); + } + + // Accesses of 8 bytes. + lastValidIndex = 0x10000 - 8 - offset; + if (!excluded) { + testStoreOOB('i64', '', lastValidIndex + 1, offset, align, '0x1234567887654321'); + } + } +} + +// On 32-bit platforms, a declared-aligned i64 store is implemented as two +// presumed-aligned 32-bit stores. This tests that we don't store the low +// word before the high word if the low word is in-bounds but the high word +// is not. +if (thirtytwobit) { + testStoreOOB('i64', '', 0x10000 - 4, 0, 0, '0x0123456789abcdef'); +} |