PR #23157 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23157 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23157.patch
Based on flvdec.c Fixes: out of array access Found-by: Xueqing Signed-off-by: Michael Niedermayer <[email protected]> >From dfac7ebd3ddf2562f6a294cc403d730dfc03075a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Tue, 19 May 2026 17:41:42 +0200 Subject: [PATCH] avformat/rtmppkt: Check recursion depth Based on flvdec.c Fixes: out of array access Found-by: Xueqing Signed-off-by: Michael Niedermayer <[email protected]> --- libavformat/rtmppkt.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c index 9cf3763c1b..6643f17a81 100644 --- a/libavformat/rtmppkt.c +++ b/libavformat/rtmppkt.c @@ -28,6 +28,8 @@ #include "flv.h" #include "url.h" +#define MAX_DEPTH 16 ///< arbitrary limit to prevent unbounded recursion + void ff_amf_write_bool(uint8_t **dst, int val) { bytestream_put_byte(dst, AMF_DATA_TYPE_BOOL); @@ -437,7 +439,7 @@ void ff_rtmp_packet_destroy(RTMPPacket *pkt) pkt->size = 0; } -static int amf_tag_skip(GetByteContext *gb) +static int amf_tag_skip(GetByteContext *gb, int depth) { AMFDataType type; unsigned nb = -1; @@ -445,6 +447,9 @@ static int amf_tag_skip(GetByteContext *gb) if (bytestream2_get_bytes_left(gb) < 1) return -1; + if (depth > MAX_DEPTH) + return AVERROR_PATCHWELCOME; + type = bytestream2_get_byte(gb); switch (type) { case AMF_DATA_TYPE_NUMBER: @@ -481,7 +486,7 @@ static int amf_tag_skip(GetByteContext *gb) return -1; bytestream2_skip(gb, size); } - t = amf_tag_skip(gb); + t = amf_tag_skip(gb, depth + 1); if (t < 0 || bytestream2_get_bytes_left(gb) <= 0) return -1; } @@ -501,7 +506,7 @@ int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end) bytestream2_init(&gb, data, data_end - data); - ret = amf_tag_skip(&gb); + ret = amf_tag_skip(&gb, 0); if (ret < 0 || bytestream2_get_bytes_left(&gb) <= 0) return -1; av_assert0(bytestream2_tell(&gb) >= 0 && bytestream2_tell(&gb) <= data_end - data); @@ -515,7 +520,7 @@ static int amf_get_field_value2(GetByteContext *gb, int len; while (bytestream2_peek_byte(gb) != AMF_DATA_TYPE_OBJECT && bytestream2_get_bytes_left(gb) > 0) { - int ret = amf_tag_skip(gb); + int ret = amf_tag_skip(gb, 0); if (ret < 0) return -1; } @@ -552,7 +557,7 @@ static int amf_get_field_value2(GetByteContext *gb, } return 0; } - len = amf_tag_skip(gb); + len = amf_tag_skip(gb, 0); if (len < 0 || bytestream2_get_bytes_left(gb) <= 0) return -1; } @@ -595,13 +600,16 @@ static const char* rtmp_packet_type(int type) } static void amf_tag_contents(void *ctx, const uint8_t *data, - const uint8_t *data_end) + const uint8_t *data_end, int depth) { unsigned int size, nb = -1; char buf[1024]; AMFDataType type; int parse_key = 1; + if (depth > MAX_DEPTH) + return; + if (data >= data_end) return; switch ((type = *data++)) { @@ -649,7 +657,7 @@ static void amf_tag_contents(void *ctx, const uint8_t *data, data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); } - amf_tag_contents(ctx, data, data_end); + amf_tag_contents(ctx, data, data_end, depth + 1); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; @@ -672,7 +680,7 @@ void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p) uint8_t *src = p->data, *src_end = p->data + p->size; while (src < src_end) { int sz; - amf_tag_contents(ctx, src, src_end); + amf_tag_contents(ctx, src, src_end, 0); sz = ff_amf_tag_size(src, src_end); if (sz < 0) break; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
