PR #24407 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24407
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24407.patch

use after free / double free / segv


>From 8a41b5aa0c572e46b7647c72b95be7ae104a313c Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Sun, 6 Sep 2026 14:39:12 +0200
Subject: [PATCH 1/3] avcodec/vvc/dec: free the tabs when pic_arrays_init()
 fails

Fixes: SEGV / dereference of uninitialized memory
Fixes: poc.266 / poc.c
Fixes: XjGK97xKVd0y
Found-by: agent00712 <[email protected]>
---
 libavcodec/vvc/dec.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index 926288e07b..d306fb0bf1 100644
--- a/libavcodec/vvc/dec.c
+++ b/libavcodec/vvc/dec.c
@@ -369,13 +369,11 @@ static int pic_arrays_init(VVCContext *s, VVCFrameContext 
*fc)
     const VVCPPS *pps            = fc->ps.pps;
     const int ctu_count          = pps->ctb_count;
     const int pic_size_in_min_pu = pps->min_pu_width * pps->min_pu_height;
-    int ret;
 
     free_cus(fc);
 
-    ret = frame_context_for_each_tl(fc, tl_create);
-    if (ret < 0)
-        return ret;
+    if (frame_context_for_each_tl(fc, tl_create) < 0)
+        goto fail;
 
     // for error handling case, we may call free_cus before 
VVC_TASK_STAGE_INIT, so we need to set cus to 0 here
     memset(fc->tab.cus, 0, sizeof(*fc->tab.cus) * ctu_count);
@@ -386,7 +384,7 @@ static int pic_arrays_init(VVCContext *s, VVCFrameContext 
*fc)
         av_refstruct_pool_uninit(&fc->rpl_tab_pool);
         fc->rpl_tab_pool = av_refstruct_pool_alloc(ctu_count * 
sizeof(RefPicListTab), 0);
         if (!fc->rpl_tab_pool)
-            return AVERROR(ENOMEM);
+            goto fail;
     }
 
     if (fc->tab.sz.pic_size_in_min_pu != pic_size_in_min_pu) {
@@ -394,7 +392,7 @@ static int pic_arrays_init(VVCContext *s, VVCFrameContext 
*fc)
         fc->tab_dmvr_mvf_pool = av_refstruct_pool_alloc(
             pic_size_in_min_pu * sizeof(MvField), 
AV_REFSTRUCT_POOL_FLAG_ZERO_EVERY_TIME);
         if (!fc->tab_dmvr_mvf_pool)
-            return AVERROR(ENOMEM);
+            goto fail;
     }
 
     fc->tab.sz.ctu_count          = pps->ctb_count;
@@ -410,6 +408,11 @@ static int pic_arrays_init(VVCContext *s, VVCFrameContext 
*fc)
     fc->tab.sz.pixel_shift        = sps->pixel_shift;
 
     return 0;
+
+fail:
+    fc->tab.sz.ctu_count = 0;
+    pic_arrays_free(fc);
+    return AVERROR(ENOMEM);
 }
 
 int ff_vvc_per_frame_init(VVCFrameContext *fc)
-- 
2.52.0


>From 00c2e3bea4756b04917bf10f22317a19ca33c808 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 7 Sep 2026 04:59:11 +0200
Subject: [PATCH 2/3] avcodec/vvc/dec: compare the CTU area in ibc_tl_init()

Fixes: reallocation of the IBC virtual buffers on every frame
---
 libavcodec/vvc/dec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index d306fb0bf1..f7c51f01a1 100644
--- a/libavcodec/vvc/dec.c
+++ b/libavcodec/vvc/dec.c
@@ -301,7 +301,7 @@ static void ibc_tl_init(TabList *l, VVCFrameContext *fc)
     const int has_ibc    = sps ? sps->r->sps_ibc_enabled_flag : 0;
     const int changed    = fc->tab.sz.chroma_format_idc != chroma_idc ||
         fc->tab.sz.ctu_height != ctu_height ||
-        fc->tab.sz.ctu_size != ctu_size ||
+        fc->tab.sz.ctu_size != ctu_size * ctu_size ||
         fc->tab.sz.pixel_shift != ps;
 
     fc->tab.sz.ibc_buffer_width = ctu_size ? 2 * MAX_CTU_SIZE * MAX_CTU_SIZE / 
ctu_size : 0;
-- 
2.52.0


>From e0d38a803f1577f0320ebef924e065fd91409c0f Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 7 Sep 2026 04:59:11 +0200
Subject: [PATCH 3/3] avcodec/vvc/thread: clear fc->ft when the frame thread is
 freed

Fixes: use after free / double free
---
 libavcodec/vvc/thread.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vvc/thread.c b/libavcodec/vvc/thread.c
index 164ad83430..f898373bb9 100644
--- a/libavcodec/vvc/thread.c
+++ b/libavcodec/vvc/thread.c
@@ -711,7 +711,7 @@ void ff_vvc_frame_thread_free(VVCFrameContext *fc)
     ff_cond_destroy(&ft->cond);
     av_freep(&ft->rows);
     av_freep(&ft->tasks);
-    av_freep(&ft);
+    av_freep(&fc->ft);
 }
 
 static void frame_thread_init_score(VVCFrameContext *fc)
-- 
2.52.0

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

Reply via email to