mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
WebAssembly.Memory-backed ArrayBuffers wrap external ByteBuffer storage. When that memory grows, ByteBuffer::try_resize() may realloc the backing storage while old fixed-length buffer objects remain reachable from JS. TypedArrayBase cached m_data for all fixed-length buffers, and the asm interpreter fast path dereferenced that cached pointer directly. For wasm memory views this could leave a stale pointer behind across grow(). Restrict cached typed-array data pointers to fixed-length ArrayBuffers that own stable ByteBuffer storage. External/unowned buffers, including WebAssembly.Memory buffers, now keep m_data == nullptr and fall back to code that re-derives buffer().data() on each access. Add regressions for both the original shared-memory grow case and the second-grow stale-view case.
47 lines
2.0 KiB
HTML
47 lines
2.0 KiB
HTML
<!doctype html>
|
|
<script src="include.js"></script>
|
|
<script>
|
|
test(() => {
|
|
// regression test for the stale-view case on shared WebAssembly.Memory.
|
|
// A typed array created from the old memory.buffer before grow() should still read and write the same underlying memory after the grow.
|
|
const mem = new WebAssembly.Memory({ initial: 1, maximum: 1000, shared: true });
|
|
const firstView = new Uint8Array(mem.buffer);
|
|
|
|
mem.grow(1);
|
|
const secondView = new Uint8Array(mem.buffer);
|
|
|
|
mem.grow(100);
|
|
const thirdView = new Uint8Array(mem.buffer);
|
|
|
|
// Writes through the newest view must be visible through the oldest view
|
|
thirdView[0x0] = 0x11;
|
|
thirdView[0x1] = 0x22;
|
|
thirdView[0x2] = 0x33;
|
|
thirdView[0x3] = 0x44;
|
|
println(`firstView[0x0]: 0x${firstView[0x0].toString(16)}`);
|
|
println(`firstView[0x1]: 0x${firstView[0x1].toString(16)}`);
|
|
println(`firstView[0x2]: 0x${firstView[0x2].toString(16)}`);
|
|
println(`firstView[0x3]: 0x${firstView[0x3].toString(16)}`);
|
|
|
|
// Writes through the oldest view must be visible through the newest view.
|
|
firstView[0x4] = 0x55;
|
|
firstView[0x5] = 0x66;
|
|
firstView[0x6] = 0x77;
|
|
firstView[0x7] = 0x88;
|
|
println(`thirdView[0x4]: 0x${thirdView[0x4].toString(16)}`);
|
|
println(`thirdView[0x5]: 0x${thirdView[0x5].toString(16)}`);
|
|
println(`thirdView[0x6]: 0x${thirdView[0x6].toString(16)}`);
|
|
println(`thirdView[0x7]: 0x${thirdView[0x7].toString(16)}`);
|
|
|
|
// And via the intermediate view.
|
|
secondView[0x8] = 0x99;
|
|
secondView[0x9] = 0xaa;
|
|
secondView[0xa] = 0xbb;
|
|
secondView[0xb] = 0xcc;
|
|
println(`firstView[0x8]: 0x${firstView[0x8].toString(16)}`);
|
|
println(`firstView[0x9]: 0x${firstView[0x9].toString(16)}`);
|
|
println(`firstView[0xa]: 0x${firstView[0xa].toString(16)}`);
|
|
println(`firstView[0xb]: 0x${firstView[0xb].toString(16)}`);
|
|
});
|
|
</script>
|