LibJS: Refresh TypedArray cached data pointers on shared memory grow

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.
This commit is contained in:
Yayoi-cs
2026-04-18 22:54:09 +09:00
committed by Andreas Kling
parent ea22c19ab3
commit d8aee7f1e6
Notes: github-actions[bot] 2026-04-20 07:44:15 +00:00
5 changed files with 69 additions and 0 deletions

View File

@@ -261,6 +261,17 @@ void ArrayBuffer::detach_buffer()
m_data_block.byte_buffer = Empty {};
}
void ArrayBuffer::refresh_cached_typed_array_view_data_pointers()
{
if (m_data_block.byte_buffer.has<Empty>())
return;
auto* new_base = buffer().data();
for (auto& view : m_cached_views) {
if (view.viewed_array_buffer() == this)
view.set_cached_data_ptr(new_base + view.byte_offset());
}
}
void ArrayBuffer::register_cached_typed_array_view(TypedArrayBase& view)
{
m_cached_views.set(view);