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

An H.264 picture with 65536 slices makes slice_num collide with the
slice_table sentinel. slice_table is uint16_t, initialized via
memset(..., -1, ...) so spare entries (one per row, mb_stride =
mb_width + 1) stay 0xFFFF. slice_num is an uncapped ++h->current_slice.
At slice 65535 the collision makes slice_table[spare] == slice_num
pass, defeating the deblock_topleft check in xchg_mb_border and the
top_type zeroing in fill_decode_caches.

With both guards bypassed at mb_x = 0, top_borders[top_idx][-1]
underflows 96 bytes and XCHG writes at -88 below the allocation
(plus -72 and -56 for chroma in the non-444 path).

Fixes: heap-buffer-overflow

Found-by: Nicholas Carlini <[email protected]>


>From 3de898fc001b4bfb705feb3f6d5394de8cee836e Mon Sep 17 00:00:00 2001
From: Nicholas Carlini <[email protected]>
Date: Sat, 14 Mar 2026 04:47:53 +0000
Subject: [PATCH] avcodec/h264_slice: reject slice_num >= 0xFFFF

An H.264 picture with 65536 slices makes slice_num collide with the
slice_table sentinel. slice_table is uint16_t, initialized via
memset(..., -1, ...) so spare entries (one per row, mb_stride =
mb_width + 1) stay 0xFFFF. slice_num is an uncapped ++h->current_slice.
At slice 65535 the collision makes slice_table[spare] == slice_num
pass, defeating the deblock_topleft check in xchg_mb_border and the
top_type zeroing in fill_decode_caches.

With both guards bypassed at mb_x = 0, top_borders[top_idx][-1]
underflows 96 bytes and XCHG writes at -88 below the allocation
(plus -72 and -56 for chroma in the non-444 path).

Fixes: heap-buffer-overflow

Found-by: Nicholas Carlini <[email protected]>
---
 libavcodec/h264_slice.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 69f70c90bb..fb1d947e5b 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1979,6 +1979,14 @@ static int h264_slice_init(H264Context *h, 
H264SliceContext *sl,
                           h->ps.pps->chroma_qp_index_offset[1]) +
                    6 * (h->ps.sps->bit_depth_luma - 8);
 
+    /* slice_table is uint16_t initialized to 0xFFFF as a sentinel. If
+     * slice_num reaches 0xFFFF, comparisons against spare entries in
+     * slice_table spuriously succeed. */
+    if (h->current_slice >= 0xFFFE) {
+        av_log(h->avctx, AV_LOG_ERROR, "Too many slices (> %d)\n", 0xFFFE);
+        return AVERROR_INVALIDDATA;
+    }
+
     sl->slice_num       = ++h->current_slice;
 
     if (sl->slice_num)
-- 
2.52.0

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

Reply via email to