← WebKit — 2026-W39

2691eb67d877a298d0fa85c3b95420d9b677c61d  Avoid unnecessary copies in PlatformRawAudioData

severity medium class IntegerOverflow confidence 0.4 signal score 10.42 Source/WebCore/Modules
Primitive: WebCodecs AudioData buffer sizing - safeMultiply guard and exact CMBlockBuffer trim to described byte count
Triage note: Reworks PlatformRawAudioData::create to own a SharedBuffer, adds WTF::safeMultiply(sizePlane, numberOfChannelStreams, sizeData) overflow check with sourceData->size() < sizeData, and trims the block buffer to exactly dataSize ('caller may have supplied more bytes than the format describes'). Attacker-reachable (JS WebCodecs) hardening, but largely a buffer-ownership refactor; no clearly pre-existing OOB demonstrated here.
Structural signals: smartptr_member_added (+6.47), bounds_guard (+2.0), null_guard (+1.95)

Commit message

Avoid unnecessary copies in PlatformRawAudioData
https://bugs.webkit.org/show_bug.cgi?id=324768
radar://188037154

Reviewed by Youenn Fablet.

PlatformRawAudioData::create() took a span, and every port copied it. Cocoa
passed a WebAudioBufferList pointing at the caller's bytes to
CMSampleBufferSetDataBufferFromAudioBufferList, which takes two allocators and
no deallocator and so allocates its own memory and copies into it; GStreamer
copied into a Vector before wrapping it. An AudioData built from an ArrayBuffer
listed in init.transfer paid for a copy of data the page had already given up.

create() now takes a Ref<SharedBuffer>, and WebCodecsAudioData::create() obtains
it from WebCodecsTransferList::takeData(), which adopts the ArrayBuffer contents
when the BufferSource spans a whole transferred buffer. Cocoa builds the sample
buffer over SharedBuffer::createCMBlockBuffer() and
CMAudioSampleBufferCreateWithPacketDescriptions, trimming the block buffer when
the caller supplied more bytes than the format describes; GStreamer forwards the
buffer to wrapSharedBuffer(). takeData() detaches the whole transfer list, so
the separate detachAll() call is gone.

* Source/WebCore/Modules/webcodecs/WebCodecsAudioData.cpp:
(WebCore::WebCodecsAudioData::create): Take the data through takeData() when a
transfer list is present.
* Source/WebCore/platform/audio/PlatformRawAudioData.h:
* Source/WebCore/platform/audio/PlatformRawAudioData.cpp:
(WebCore::PlatformRawAudioData::create):
* Source/WebCore/platform/audio/cocoa/PlatformRawAudioDataCocoa.cpp:
(WebCore::createSampleBuffer): Build the sample buffer over the shared buffer's
CMBlockBuffer.
(WebCore::PlatformRawAudioData::create): Check the supplied length directly
instead of walking a WebAudioBufferList.
* Source/WebCore/platform/audio/gstreamer/PlatformRawAudioDataGStreamer.cpp:
(WebCore::PlatformRawAudioData::create): Wrap the shared buffer instead of
copying it.

Canonical link: https://commits.webkit.org/321747@main

Before / after

Loading diff…