25189dfe0a49b3f8324586374b8251b8d12ad1c2 [WebAudio] MediaStreamAudioSourceNode error with large render quantum
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
- 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).
- Trigger — renderQuantumSize exceeds kMaxSamplesPerPacket so an oversized audio block is routed through the media stream source.
- 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).
- 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
- Setup — Page obtains a MediaStream and creates an AudioContext with an oversized renderSizeHint and high sample rate (inferred).
- Trigger — Constructing the MediaStreamAudioSourceNode routes an over-limit quantum into the media packet buffer (inferred).
- 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.