← All reports

Bitstream parsing moves from the GPU process to the WebProcess

Component: WebCore WebRTC codecs | 4ae8b7a

Source/WebCore/platform/video-codecs/cocoa/GPUVideoDecoderVTB.mm

+int32_t GPUVideoDecoderVTB::decodeFrame(int64_t timeStamp, std::span<const uint8_t> data, RefPtr<VideoInfo>&& videoInfo)
+{
+ assertIsCurrent(queue());
+
+ if (videoInfo)
+ setVideoInfo(videoInfo.releaseNonNull());
+
+ return decodeFrameInternal(timeStamp, data);
+}
...
-void GPUVideoDecoderVTB::setVideoInfo(Ref<VideoInfo>&& videoInfo, uint8_t reorderSize)
+void GPUVideoDecoderVTB::setVideoInfo(Ref<VideoInfo>&& videoInfo)
{
updateFormat(videoInfo);
+ m_reorderQueueMaxSize = videoInfo->reorderQueueMaxSize().value_or(0);
m_videoInfo = WTF::move(videoInfo);
- m_reorderSize = reorderSize;

WebRTC and WebCodecs video decoding runs in the GPU process. LibWebRTCCodecsProxy receives encoded frames over IPC and feeds them to VideoToolbox (VTB). VTB needs a format description built from codec configuration (SPS/PPS/VPS, avcC/hvcC) and expects length-prefixed NAL units, but WebRTC delivers AnnexB start-code streams.

Parsing of H.264/HEVC (AnnexB, avcC/hvcC) and VP9 bitstreams moves into the WebProcess (LibWebRTCCodecs). The WebProcess converts AnnexB frames to length-prefixed form and builds a VideoInfo that now includes a parsed reorderQueueMaxSize. That VideoInfo reaches the GPU process through setDecoderFormatDescription and, optionally, with each decodeFrame. The four codec-specific VTB subclasses collapse into one final GPUVideoDecoderVTB.

Historically bug-prone bitstream parsing leaves the more privileged GPU process, which now trusts an IPC-delivered VideoInfo to configure VideoToolbox and size its reorder queue.

The trust direction is reversed: under the compromised-renderer threat model, the GPU process now receives a VideoInfo fully controlled by the attacker, whose serialization changed in WebCoreArgumentCoders.serialization.in. Check how GPUVideoDecoderVTB uses extensionAtoms and the colorspace/codec config to build the format description, and whether validation was lost along with the removed parser. Check the sender-chosen uint8_t reorderQueueMaxSize for unbounded frame retention and its interaction with flush/drain. Check mid-stream VideoInfo arrival: frames before any format, repeated format changes, decoder destruction during an update, and teardown of the old session with frames in flight. Malformed NAL lengths, or a declared format that does not match the frame content, now go straight to VideoToolbox. Finally, check that VP9/AV1 special cases survived the collapse, including the deleted shouldOverrideColorSpaceAttachments and the BT.709 default in createVideoInfoFromVP9Stream.