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.
WebAssembly.Memory({shared:true}).grow() reallocates the underlying
AK::ByteBuffer outline (kmalloc+kfree) but, per the threads proposal,
must not detach the associated SharedArrayBuffer.
ArrayBuffer::detach_buffer was the only path that walked m_cached_views
and cleared the cached raw m_data pointer on each TypedArrayBase, so
every existing view retained a dangling pointer into the freed outline.
The AsmInterpreter GetByValue / PutByValue fast paths dereference that
cached pointer directly, yielding a use-after-free triggerable from
JavaScript.
Add ArrayBuffer::refresh_cached_typed_array_view_data_pointers() which
re-derives m_data for each registered view from the current outline
base (and refreshes UnownedFixedLengthByteBuffer::size), and call it
from Memory::refresh_the_memory_buffer on the SAB-fixed-length path
where detach is spec-forbidden.
Cache raw data pointers on fixed-length typed array views so asm
GetByValue and PutByValue can use them directly for indexed
element access.
Replace the asm typed-array hot-path
ArrayBuffer/DataBlock/ByteBuffer walk with one cached_data_ptr load.
Remove six unconditional loads, four branches, and the byte_offset
add before the element access, trading them for one
cached_data_ptr null check.
Keep direct C++ typed-array access on IsValidIntegerIndex-based
checks, invalidate cached pointers eagerly when a backing
ArrayBuffer is detached, and add regression coverage for shrink,
regrow, and detach on number and BigInt typed arrays.
We treat any mention of [[ArrayBufferByteLengthData]] and related
atomic operations as FIXMEs to be fixed at a later date. We also add the
HostGrowSharedArrayBuffer abstract operation, which will be overridden
by LibWeb to grow shared WebAssembly memories.
The relevant type of ArrayBuffer DataBlock is now a struct containing
both a ByteBuffer* and a size_t size, and not just a ByteBuffer*, with
the size being that of the ByteBuffer. This type of DataBlock is only
used for WebAssembly.Memory (see commit 4fd43a8f96), meaning this
change won't affect any other code. This change is required to pass one
WPT subtest in wasm/jsapi/memory/grow.any.html, since old fixed-length
SharedArrayBuffers after a WebAssembly.Memory growth should keep their
length, while the new buffer after the growth will have the updated
length.
This reverts commit c14173f651. We
should only annotate the minimum number of symbols that external
consumers actually use, so I am starting from scratch to do that
This will allow structured deserialization in LibWeb to create shared
buffers without having to go through CreateSharedByteDataBlock. That
will let us pass in the underlying ByteBuffer, rather than having to
allocate a second buffer via CreateSharedByteDataBlock and memcpy the
data into it.
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:
* JS::NonnullGCPtr -> GC::Ref
* JS::GCPtr -> GC::Ptr
* JS::HeapFunction -> GC::Function
* JS::CellImpl -> GC::Cell
* JS::Handle -> GC::Root