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

The picture level slice index accumulated in sh_slice_address() and in the
CBS slice header parser (num_entry_points derivation) is used to index the
VVC_MAX_SLICES-sized PPS arrays without a range check. When the current
subpicture holds no slice top-left corner, the accumulated index can reach
pps_num_slices_in_pic_minus1 + 1 and read one entry past
slice_start_offset[] / num_ctus_in_slice[] and, in the parser, past
pps_slice_width_in_tiles_minus1[] / slice_height_in_ctus[], aliasing
unrelated struct fields.

The aliased values then inflate num_entry_points beyond the number of
entry points the decoder-side walk of the same slice produces, so
slice_init_entry_points() consumes entry_point_start_ctu[] entries that
were never refreshed for the current picture. On a picture smaller than an
earlier one the stale values exceed num_ctus_in_curr_slice, and the entry
point walks in slice_init_entry_points() and ff_vvc_frame_submit() read
ctb_addr_in_curr_slice[] past the end of the ctb_addr_in_slice
allocation. The values read out of bounds then index fc->tab.slice_idx[]
out of bounds.

Fixes: out of array access
Fixes: heap-buffer-overflow
Found-by: Umar Pathan (Umar0x)
Signed-off-by: Umar Pathan <[email protected]>
Fixes: ccSUzeWGhBGj
Out of array read Replicated through UnModified FFmpeg with ASAN,UBSAN


>From f1c15bee9855239957517af139a6f6d9868463ab Mon Sep 17 00:00:00 2001
From: Umar Pathan <[email protected]>
Date: Tue, 29 Sep 2026 16:43:13 +0000
Subject: [PATCH 1/3] lavc/vvc: Validate the slice address against the PPS
 slice count

The picture level slice index accumulated in sh_slice_address() and in the
CBS slice header parser (num_entry_points derivation) is used to index the
VVC_MAX_SLICES-sized PPS arrays without a range check. When the current
subpicture holds no slice top-left corner, the accumulated index can reach
pps_num_slices_in_pic_minus1 + 1 and read one entry past
slice_start_offset[] / num_ctus_in_slice[] and, in the parser, past
pps_slice_width_in_tiles_minus1[] / slice_height_in_ctus[], aliasing
unrelated struct fields.

The aliased values then inflate num_entry_points beyond the number of
entry points the decoder-side walk of the same slice produces, so
slice_init_entry_points() consumes entry_point_start_ctu[] entries that
were never refreshed for the current picture. On a picture smaller than an
earlier one the stale values exceed num_ctus_in_curr_slice, and the entry
point walks in slice_init_entry_points() and ff_vvc_frame_submit() read
ctb_addr_in_curr_slice[] past the end of the ctb_addr_in_slice
allocation. The values read out of bounds then index fc->tab.slice_idx[]
out of bounds.

Fixes: out of array access
Fixes: heap-buffer-overflow
Found-by: Umar Pathan (Umar0x)
Signed-off-by: Umar Pathan <[email protected]>
Fixes: ccSUzeWGhBGj
Out of array read Replicated through UnModified FFmpeg with ASAN,UBSAN
---
 libavcodec/cbs_h266_syntax_template.c | 4 ++++
 libavcodec/vvc/ps.c                   | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/libavcodec/cbs_h266_syntax_template.c 
b/libavcodec/cbs_h266_syntax_template.c
index 55178db1ea..6ad4039e1a 100644
--- a/libavcodec/cbs_h266_syntax_template.c
+++ b/libavcodec/cbs_h266_syntax_template.c
@@ -3462,6 +3462,10 @@ static int FUNC(slice_header) (CodedBitstreamContext 
*ctx, RWContext *rw,
             for (i = 0; i < current->curr_subpic_idx; i++) {
                 slice_idx += pps->num_slices_in_subpic[i];
             }
+            if (slice_idx > pps->pps_num_slices_in_pic_minus1) {
+                av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid slice address 
%d\n", slice_idx);
+                return AVERROR_INVALIDDATA;
+            }
 
             if (pps->pps_single_slice_per_subpic_flag) {
                 int width_in_ctus, height_in_ctus;
diff --git a/libavcodec/vvc/ps.c b/libavcodec/vvc/ps.c
index 2a46680adb..4aa1f4767a 100644
--- a/libavcodec/vvc/ps.c
+++ b/libavcodec/vvc/ps.c
@@ -1374,6 +1374,8 @@ static int sh_slice_address(VVCSH *sh, const H266RawSPS 
*sps, const VVCPPS *pps)
         int pic_level_slice_idx = slice_address;
         for (int j = 0; j < sh->r->curr_subpic_idx; j++)
             pic_level_slice_idx += pps->r->num_slices_in_subpic[j];
+        if (pic_level_slice_idx > pps->r->pps_num_slices_in_pic_minus1)
+            return AVERROR_INVALIDDATA;
         sh->ctb_addr_in_curr_slice = pps->ctb_addr_in_slice + 
pps->slice_start_offset[pic_level_slice_idx];
         sh->num_ctus_in_curr_slice = 
pps->num_ctus_in_slice[pic_level_slice_idx];
     } else {
-- 
2.52.0


>From 3f4400eb595cceaf59256dc72230851710607b30 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 6 Oct 2026 06:48:27 +0200
Subject: [PATCH 2/3] avcodec/vvc: Reject slices whose entry point walk does
 not match num_entry_points

Hardening for ccSUzeWGhBGj
Found-by: Umar Pathan (Umar0x)
---
 libavcodec/vvc/ps.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libavcodec/vvc/ps.c b/libavcodec/vvc/ps.c
index 4aa1f4767a..d40c8050db 100644
--- a/libavcodec/vvc/ps.c
+++ b/libavcodec/vvc/ps.c
@@ -1472,7 +1472,8 @@ static void sh_partition_constraints(VVCSH *sh, const 
H266RawSPS *sps, const H26
 static int sh_entry_points(VVCSH *sh, const H266RawSPS *sps, const VVCPPS *pps)
 {
     if (sps->sps_entry_point_offsets_present_flag) {
-        for (int i = 1, j = 0; i < sh->num_ctus_in_curr_slice; i++) {
+        int j = 0;
+        for (int i = 1; i < sh->num_ctus_in_curr_slice; i++) {
             const int pre_ctb_addr_x = sh->ctb_addr_in_curr_slice[i - 1] % 
pps->ctb_width;
             const int pre_ctb_addr_y = sh->ctb_addr_in_curr_slice[i - 1] / 
pps->ctb_width;
             const int ctb_addr_x     = sh->ctb_addr_in_curr_slice[i] % 
pps->ctb_width;
@@ -1485,6 +1486,8 @@ static int sh_entry_points(VVCSH *sh, const H266RawSPS 
*sps, const VVCPPS *pps)
                 sh->entry_point_start_ctu[j++] = i;
             }
         }
+        if (j != sh->r->num_entry_points)
+            return AVERROR_INVALIDDATA;
     }
 
     return 0;
-- 
2.52.0


>From 88736d765994b2abbf38ea5d11583ae1c8a14079 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 6 Oct 2026 23:20:08 +0200
Subject: [PATCH 3/3] avcodec/cbs_h266: Reject subpictures without slices

Hardening for ccSUzeWGhBGj
Found-by: Umar Pathan (Umar0x)
---
 libavcodec/cbs_h266_syntax_template.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavcodec/cbs_h266_syntax_template.c 
b/libavcodec/cbs_h266_syntax_template.c
index 6ad4039e1a..9e0776defe 100644
--- a/libavcodec/cbs_h266_syntax_template.c
+++ b/libavcodec/cbs_h266_syntax_template.c
@@ -2162,6 +2162,8 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, 
RWContext *rw,
                         current->num_slices_in_subpic[i]++;
                     }
                 }
+                if (!current->num_slices_in_subpic[i])
+                    return AVERROR_INVALIDDATA;
                 num_slices += current->num_slices_in_subpic[i];
             }
             if (current->pps_num_slices_in_pic_minus1 + 1 != num_slices)
-- 
2.52.0

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

Reply via email to