← Chrome — 2026-W33

25189dfe0a49b3f8324586374b8251b8d12ad1c2  [WebAudio] MediaStreamAudioSourceNode error with large render quantum

severity low class InputValidation CVSS 5.3 signal score 3.8 third_party/blink/renderer/modules/ AI review PLAUSIBLE
Structural signals: area:third_party/blink/renderer/modules/ (+2.5), surgical (+1.3)

The bug at a glance

A web-reachable render quantum (renderSizeHint) could be set far larger than media::limits::kMaxSamplesPerPacket, and MediaStreamAudioSourceNode copied audio into per-packet buffers sized to that limit; the missing bound meant an oversized quantum could overrun or fail a fixed-size media packet buffer. The fix adds an explicit NotSupportedError bound at node creation, so the downstream corruption/crash is averted but its exact primitive is inferred.

Ordinary web content can choose an AudioContext renderSizeHint and sample rate so the render quantum exceeds the media stream packet limit, feeding an oversized block into the media pipeline; a defender cares because the previous absence of a bound let author-controlled sizing reach fixed-capacity packet buffers.

Root cause

MediaStreamAudioSourceNode::Create did not validate context.renderQuantumSize() against media::limits::kMaxSamplesPerPacket. When the render quantum exceeds the maximum samples per packet, audio produced per quantum does not fit the media stream source’s packet buffering assumptions (sized to kMaxSamplesPerPacket), leading to a buffer overrun or hard failure when samples are delivered (inferred downstream). The patch includes media/base/limits.h and throws a NotSupportedError DOMException at node construction when renderQuantumSize() exceeds kMaxSamplesPerPacket, rejecting the oversized configuration before any buffer is used.

Key code

Reject render quantum exceeding max samples per packet

+  if (context.renderQuantumSize() >
+      static_cast<uint32_t>(media::limits::kMaxSamplesPerPacket)) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotSupportedError,
+        String::Format(... context.renderQuantumSize(), media::limits::kMaxSamplesPerPacket));
+    return nullptr;
+  }

Patch walkthrough

  • third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc — Adds a bounds check (and the media/base/limits.h include) rejecting node creation with NotSupportedError when the context render quantum size exceeds media::limits::kMaxSamplesPerPacket, closing a missing-validation gap where an oversized quantum reached packet-sized media buffers.
  • third_party/blink/web_tests/webaudio/MediaStreamAudioSource/mediastreamaudiosourcenode-rendersizehint.https.html — Adds a web test proving both constructor and createMediaStreamSource throw NotSupportedError when a 1,000,000-frame quantum (sampleRate 384000, renderSizeHint 1000000) exceeds the 768000 kMaxSamplesPerPacket limit.

Background

renderSizeHint / renderQuantumSize — Author-controllable AudioContext option that sets the per-callback render block size, validated here only within the AudioContext range [1, 2304000].

media::limits::kMaxSamplesPerPacket — A media-layer cap (768000) on samples per audio packet that media stream source buffering relies on.

MediaStreamAudioSourceNode — Web Audio node that feeds a MediaStream’s audio into the audio graph, bridging render quanta and media packets.

Vulnerability window

  1. Reachability — Web content in a stock build creates an AudioContext with a large renderSizeHint and high sampleRate, then constructs a MediaStreamAudioSourceNode (renderSizeHint may be experimental/flag-gated on some channels, inferred).
  2. Trigger — renderQuantumSize exceeds kMaxSamplesPerPacket so an oversized audio block is routed through the media stream source.
  3. Primitive — Pre-patch, the oversized quantum overruns or violates the fixed packet-size buffer assumptions in the media pipeline, risking OOB write or CHECK failure (inferred).
  4. Escalation — Any corruption primitive would require controlling adjacent allocations; the diff neither shows nor enables such escalation (inferred).

Proof of concept

Conceptually, create an AudioContext with sampleRate 384000 and renderSizeHint ~1,000,000 (valid for context creation but above kMaxSamplesPerPacket) and construct a MediaStreamAudioSourceNode over a live MediaStream; pre-patch the oversized quantum flows into packet-sized media buffers. No exploit code provided.

Exploitation

  1. Setup — Page obtains a MediaStream and creates an AudioContext with an oversized renderSizeHint and high sample rate (inferred).
  2. Trigger — Constructing the MediaStreamAudioSourceNode routes an over-limit quantum into the media packet buffer (inferred).
  3. Impact — Pre-patch outcome is a buffer overrun or renderer crash; controlled corruption would need heap grooming (inferred).

Detection & hunting

For defenders and detection engineers:

  • grep for renderQuantumSize()/RenderQuantumFrames() flowing into media stream or packet buffers without a kMaxSamplesPerPacket bound — Find audio paths that copy render-quantum-sized data into fixed-capacity media buffers without validating against the packet limit.
  • weggli for missing comparisons against media::limits::kMaxSamplesPerPacket before buffer sizing/copy — Hunt for other node constructors that accept author-controlled quantum sizes without bounding them to media limits.

Audit directions

  • Other Web Audio nodes bridging to MediaStream/WebRTC that depend on render quantum size — Audit for the same class of missing bound where an author-set render quantum can exceed media packet/buffer limits.
  • Callers of media::limits constants across blink audio/video bridges — Verify every fixed-capacity media buffer sized by these limits is guarded against larger web-controlled inputs.

Before / after

Loading diff…