Android security tags, read closely by Lightrion

CVE-2026-45515 AI-generated analysis

platform/packages/modules/Bluetooth, system/stack/a2dp (A2DP sink Opus vendor codec decoder)

AI-generated: written from the bulletin and the fixing diffs by claude-fable-5-1, then checked against the code by claude-opus-5-5 (4 corrections). Verify against the commit before relying on it.

Passes the correct frame_size (the number of samples per channel the output buffer can hold, A2DP_OPUS_DECODE_BUFFER_LENGTH / (A2DP_OPUS_CODEC_OUTPUT_CHS * sizeof(int16_t))) to both opus_decode() calls in a2dp_vendor_opus_decoder_decode_packet instead of the buffer size in bytes. It also adds a channel-count check, removes the per-frame re-decode loop and makes frame_len use the configured stereo output.

Root cause

In system/stack/a2dp/a2dp_vendor_opus_decoder.cc, a2dp_vendor_opus_decoder_decode_packet called opus_decode(handle, pBuffer, bufferSize, a2dp_opus_decoder_cb.decode_buf, A2DP_OPUS_DECODE_BUFFER_LENGTH, 0). Per the commit message, opus_decode expects samples per channel as its frame_size, but A2DP_OPUS_DECODE_BUFFER_LENGTH is the buffer size in bytes. The output is stereo int16 (the commit message gives a fixed channel count of 2), so the bound was larger than decode_buf's real capacity by the factor A2DP_OPUS_CODEC_OUTPUT_CHS * sizeof(int16_t). A crafted Opus packet with a large frame duration could therefore overflow the heap buffer. The new test uses a real 60 ms, 2880 samples per channel packet. The packet-loss-concealment call opus_decode(handle, NULL, 0, ...) had the same wrong bound. The code also had three other problems: it looped numFrames times decoding the same whole packet, it computed frame_len from the packet's numChannels instead of the configured output channel count, and it never validated numChannels.

How the fix works

Completeness

Behavior changes

Per major

Unknowns

Back to September 2026 · Findings