PR #23174 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23174 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23174.patch
In the >= 9 bit path, color_frame() does `av_memcpy_backptr(dst + 2, 2, bytes - 2)`. When the effective chroma width is 1 pixel (bytes == 1) the count becomes -1 and the underlying fill16() loop runs roughly 2^32 times, producing a heap overflow. The original count was also wrong in units (pixels rather than bytes); fix that at the same time so the 2-pixel case still fills both pixels. Confirmed via a standalone harness reproducing av_memcpy_backptr's fill16 loop with cnt = -1; reaching the call from a crafted H.264 bitstream requires Hi10P plus a frame_num gap on a frame whose effective chroma width is 1 pixel, which is hard to express but is reachable via mid-stream SPS changes. Compiles cleanly; no regressions seen running existing crafted H.264 PoCs and trivial transcodes. Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski. >From b045db016e7078d7636823c1dd6b864dc8a26771 Mon Sep 17 00:00:00 2001 From: Franciszek Kalinowski <[email protected]> Date: Tue, 19 May 2026 09:36:50 +0200 Subject: [PATCH] avcodec/h264_slice: guard color_frame() against chroma-width underflow In the >= 9 bit path, color_frame() does `av_memcpy_backptr(dst + 2, 2, bytes - 2)`. When the effective chroma width is 1 pixel (bytes == 1) the count becomes -1 and the underlying fill16() loop runs roughly 2^32 times, producing a heap overflow. The original count was also wrong in units (pixels rather than bytes); fix that at the same time so the 2-pixel case still fills both pixels. Confirmed via a standalone harness reproducing av_memcpy_backptr's fill16 loop with cnt = -1; reaching the call from a crafted H.264 bitstream requires Hi10P plus a frame_num gap on a frame whose effective chroma width is 1 pixel, which is hard to express but is reachable via mid-stream SPS changes. Compiles cleanly; no regressions seen running existing crafted H.264 PoCs and trivial transcodes. Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski. --- libavcodec/h264_slice.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index dbf7f60230..e3b4436fcb 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -316,8 +316,10 @@ static void color_frame(AVFrame *frame, const int c[4]) int bytes = is_chroma ? AV_CEIL_RSHIFT(frame->width, desc->log2_chroma_w) : frame->width; int height = is_chroma ? AV_CEIL_RSHIFT(frame->height, desc->log2_chroma_h) : frame->height; if (desc->comp[0].depth >= 9) { - ((uint16_t*)dst)[0] = c[p]; - av_memcpy_backptr(dst + 2, 2, bytes - 2); + if (bytes >= 1) + ((uint16_t*)dst)[0] = c[p]; + if (bytes >= 2) + av_memcpy_backptr(dst + 2, 2, 2 * (bytes - 1)); dst += frame->linesize[p]; for (int y = 1; y < height; y++) { memcpy(dst, frame->data[p], 2*bytes); -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
