Commit 9cfea1ceb8 for ffmpeg
commit 9cfea1ceb8274fa0b3ea54fafc3eedda47cf2c53
Author: Umar Pathan <hello@umar.ac>
Date: Tue Sep 29 16:43:13 2026 +0000
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 <hello@umar.ac>
Fixes: ccSUzeWGhBGj
Out of array read Replicated through UnModified FFmpeg with ASAN,UBSAN
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 {