This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 24adcf3a72d88e1b38360678e3331eeb6de6849c
Author:     Alexandru Ardelean <[email protected]>
AuthorDate: Thu Apr 9 16:01:11 2026 +0300
Commit:     Ramiro Polla <[email protected]>
CommitDate: Fri Apr 10 16:02:28 2026 +0000

    avdevice/v4l2: fix potential memleak when allocating device buffers
    
    In the loop which allocates the buffers for a V4L2 device, if failure
    occurs for a certain buffer (e.g. 3rd of 4 buffers), then the previously
    allocated buffers (and the buffer array) would not be free'd in
    the mmap_init(). This would cause a leak.
    
    This change handles the error cases of that loop to free all allocated
    resources, so that when mmap_init() fails nothing is leaked.
    
    Signed-off-by: Alexandru Ardelean <[email protected]>
---
 libavdevice/v4l2.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index c38ecbb378..a4122c452f 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -356,6 +356,15 @@ static void list_standards(AVFormatContext *ctx)
     }
 }
 
+static void mmap_free(struct video_data *s, int n)
+{
+    while (--n > 0) {
+        v4l2_munmap(s->buf_start[n], s->buf_len[n]);
+    }
+    av_freep(&s->buf_start);
+    av_freep(&s->buf_len);
+}
+
 static int mmap_init(AVFormatContext *ctx)
 {
     int i, res;
@@ -402,13 +411,14 @@ static int mmap_init(AVFormatContext *ctx)
         if (v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf) < 0) {
             res = AVERROR(errno);
             av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF): %s\n", 
av_err2str(res));
-            return res;
+            goto fail;
         }
 
         if (s->multiplanar) {
             if (buf.length != 1) {
                 av_log(ctx, AV_LOG_ERROR, "multiplanar only supported when 
buf.length == 1\n");
-                return AVERROR_PATCHWELCOME;
+                res = AVERROR_PATCHWELCOME;
+                goto fail;
             }
             buf_length = buf.m.planes[0].length;
             buf_offset = buf.m.planes[0].m.mem_offset;
@@ -422,7 +432,8 @@ static int mmap_init(AVFormatContext *ctx)
             av_log(ctx, AV_LOG_ERROR,
                    "buf_len[%d] = %d < expected frame size %d\n",
                    i, s->buf_len[i], s->frame_size);
-            return AVERROR(ENOMEM);
+            res = AVERROR(ENOMEM);
+            goto fail;
         }
         s->buf_start[i] = v4l2_mmap(NULL, buf_length,
                                PROT_READ | PROT_WRITE, MAP_SHARED,
@@ -431,11 +442,15 @@ static int mmap_init(AVFormatContext *ctx)
         if (s->buf_start[i] == MAP_FAILED) {
             res = AVERROR(errno);
             av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", av_err2str(res));
-            return res;
+            goto fail;
         }
     }
 
     return 0;
+
+fail:
+    mmap_free(s, i);
+    return res;
 }
 
 static int enqueue_buffer(struct video_data *s, struct v4l2_buffer *buf)
@@ -681,18 +696,13 @@ static int mmap_start(AVFormatContext *ctx)
 static void mmap_close(struct video_data *s)
 {
     enum v4l2_buf_type type;
-    int i;
 
     type = s->buf_type;
     /* We do not check for the result, because we could
      * not do anything about it anyway...
      */
     v4l2_ioctl(s->fd, VIDIOC_STREAMOFF, &type);
-    for (i = 0; i < s->buffers; i++) {
-        v4l2_munmap(s->buf_start[i], s->buf_len[i]);
-    }
-    av_freep(&s->buf_start);
-    av_freep(&s->buf_len);
+    mmap_free(s, s->buffers);
 }
 
 static int v4l2_set_parameters(AVFormatContext *ctx)

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to