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]

Reply via email to