Commit ed314d8860 for ffmpeg

commit ed314d886012bd52d3ea9705861b8c6743c200c4
Author: Michael Niedermayer <michael@niedermayer.cc>
Date:   Wed Oct 7 00:05:08 2026 +0200

    avformat/rtpdec_rfc4175: Do not leak the frame finalized on a missed marker

    When a packet with a new timestamp put the previous frame into pkt, an
    invalid packet returned an error with the frame still in pkt, and a
    packet with the marker set put the new frame into the same pkt. In both
    cases the previous frame was lost and its buffer leaked, once per such
    packet, so a sender can exhaust the memory of the receiver.
    Return the previous frame in these cases, and the new one from the
    following call.

    Fixes: memleak
    Fixes: iF2DzMcFQavi
    Memory leak Replicated through UnModified FFmpeg with ASAN
    Found during triage of the security report V8a3e2cGQI7w

diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c
index 3d31bb268b..32b09ae80b 100644
--- a/libavformat/rtpdec_rfc4175.c
+++ b/libavformat/rtpdec_rfc4175.c
@@ -238,13 +238,21 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
                                  uint16_t seq, int flags)
 {
     int length, line, offset, cont, field;
-    const uint8_t *headers = buf + 2; /* skip extended seqnum */
-    const uint8_t *payload = buf + 2;
-    int payload_len = len - 2;
+    const uint8_t *headers, *payload;
+    int payload_len;
     int missed_last_packet = 0;

     uint8_t *dest;

+    if (!buf) {
+        *timestamp = data->timestamp;
+        return rfc4175_finalize_packet(data, pkt, st->index);
+    }
+
+    headers = buf + 2; /* skip extended seqnum */
+    payload = buf + 2;
+    payload_len = len - 2;
+
     if (*timestamp != data->timestamp) {
         if (data->frame && (!data->interlaced || data->field)) {
             /*
@@ -255,8 +263,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
              * previous frame (or pair of fields) anyway by filling the AVPacket.
              */
             av_log(ctx, AV_LOG_ERROR, "Missed previous RTP Marker\n");
-            missed_last_packet = 1;
-            rfc4175_finalize_packet(data, pkt, st->index);
+            missed_last_packet = rfc4175_finalize_packet(data, pkt, st->index) >= 0;
         }

         if (!data->frame)
@@ -266,7 +273,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,

         if (!data->frame) {
             av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
-            return AVERROR(ENOMEM);
+            return missed_last_packet ? 0 : AVERROR(ENOMEM);
         }
     }

@@ -276,7 +283,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
      */
     do {
         if (payload_len < 6)
-            return AVERROR_INVALIDDATA;
+            goto invalid;

         cont = payload[4] & 0x80;
         payload += 6;
@@ -288,7 +295,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
         int copy_offset;

         if (payload_len < data->pgroup)
-            return AVERROR_INVALIDDATA;
+            goto invalid;

         length = (headers[0] << 8) | headers[1];
         field = (headers[2] & 0x80) >> 7;
@@ -299,7 +306,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
         data->field = field;

         if (!data->pgroup || length % data->pgroup)
-            return AVERROR_INVALIDDATA;
+            goto invalid;

         if (length > payload_len)
             length = payload_len;
@@ -308,12 +315,12 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
             line = 2 * line + field;

         if (line >= data->height)
-            return AVERROR_INVALIDDATA;
+            goto invalid;

         /* prevent ill-formed packets to write after buffer's end */
         copy_offset = (line * data->width + offset) * data->pgroup / data->xinc;
         if (copy_offset + length > data->frame_size || !data->frame)
-            return AVERROR_INVALIDDATA;
+            goto invalid;

         dest = data->frame + copy_offset;
         memcpy(dest, payload, length);
@@ -322,13 +329,16 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
         payload_len -= length;
     } while (cont);

-    if ((flags & RTP_FLAG_MARKER)) {
+    if (missed_last_packet) {
+        return !!(flags & RTP_FLAG_MARKER);
+    } else if ((flags & RTP_FLAG_MARKER)) {
         return rfc4175_finalize_packet(data, pkt, st->index);
-    } else if (missed_last_packet) {
-        return 0;
     }

     return AVERROR(EAGAIN);
+
+invalid:
+    return missed_last_packet ? 0 : AVERROR_INVALIDDATA;
 }

 const RTPDynamicProtocolHandler ff_rfc4175_rtp_handler = {