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.
This commit is contained in:
Franciszek Kalinowski
2026-05-19 09:36:50 +02:00
committed by michaelni
parent 34dfa8bf2b
commit c79dfd29e6
+4 -2
View File
@@ -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);