You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-06-19 19:03:00 +02:00
avformat/oggparsecelt: bound extra_headers to avoid an effectively infinite loop
celt_header() reads a uint32 `extra_headers` field from the CELT identification
header and stores `1 + extra_headers` into the signed int extra_headers_left.
With extra_headers = 0x7FFFFFFE this becomes INT_MAX and the OGG parser
consumes every subsequent page as a CELT "extra header" without ever reaching
audio data, hanging on any streaming input. A value of 0xFFFFFFFE wraps the
signed addition negative, with the same family of consequences.
Reject any extra_headers count above a small fixed cap (16, well above any
real CELT-over-Ogg stream).
Verified with the audit PoC (a crafted file plus an infinite-page FIFO):
without the patch, ffmpeg consumes pages forever; with the patch it logs
"Too many CELT extra headers (...)" and exits in ~70 ms with
AVERROR_INVALIDDATA.
Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.
(cherry picked from commit 87439ed619)
This commit is contained in:
committed by
Romain Beauxis
parent
831958d0b1
commit
a981a06fe7
@@ -26,6 +26,9 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "oggdec.h"
|
#include "oggdec.h"
|
||||||
|
|
||||||
|
/* CELT-over-Ogg streams use at most a couple of vorbiscomment "extra" headers. */
|
||||||
|
#define CELT_MAX_EXTRA_HEADERS 16
|
||||||
|
|
||||||
struct oggcelt_private {
|
struct oggcelt_private {
|
||||||
int extra_headers_left;
|
int extra_headers_left;
|
||||||
};
|
};
|
||||||
@@ -61,6 +64,12 @@ static int celt_header(AVFormatContext *s, int idx)
|
|||||||
overlap = AV_RL32(p + 48);
|
overlap = AV_RL32(p + 48);
|
||||||
/* unused bytes per packet field skipped */
|
/* unused bytes per packet field skipped */
|
||||||
extra_headers = AV_RL32(p + 56);
|
extra_headers = AV_RL32(p + 56);
|
||||||
|
if (extra_headers > CELT_MAX_EXTRA_HEADERS) {
|
||||||
|
av_log(s, AV_LOG_ERROR,
|
||||||
|
"Too many CELT extra headers (%u)\n", extra_headers);
|
||||||
|
av_free(priv);
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
st->codecpar->codec_id = AV_CODEC_ID_CELT;
|
st->codecpar->codec_id = AV_CODEC_ID_CELT;
|
||||||
st->codecpar->sample_rate = sample_rate;
|
st->codecpar->sample_rate = sample_rate;
|
||||||
|
|||||||
Reference in New Issue
Block a user