This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 92804c9e25 avformat/rtmppkt: Check recursion depth
92804c9e25 is described below
commit 92804c9e25623f2d5c5c8d64d4b0a538d1861cd7
Author: Michael Niedermayer <[email protected]>
AuthorDate: Tue May 19 17:41:42 2026 +0200
Commit: michaelni <[email protected]>
CommitDate: Wed Jun 3 23:36:13 2026 +0000
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 | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c
index 9cf3763c1b..4977935210 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,11 @@ static int amf_tag_skip(GetByteContext *gb)
if (bytestream2_get_bytes_left(gb) < 1)
return -1;
+ if (depth > MAX_DEPTH) {
+ av_log(NULL, AV_LOG_ERROR, "amf_tag_skip: exceeded max depth\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
type = bytestream2_get_byte(gb);
switch (type) {
case AMF_DATA_TYPE_NUMBER:
@@ -481,7 +488,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 +508,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 +522,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 +559,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 +602,18 @@ 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) {
+ av_log(NULL, AV_LOG_ERROR, "amf_tag_contents: exceeded max depth\n");
+ return;
+ }
+
if (data >= data_end)
return;
switch ((type = *data++)) {
@@ -649,7 +661,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 +684,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;
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]