PR #23037 opened by Zhao Zhili (quink)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23037
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23037.patch

generate_missing_ref walked frame->f->data[] until a NULL slot, which
on alpha-video frames extended to data[3] and read
sps->hshift[3]/vshift[3] out of bounds.

The alpha plane is produced by the alpha layer via
replace_alpha_plane; the base decoder path never reads or writes it.
Bound the fill loop by the SPS coded plane count. This both removes
the out-of-bounds shift access and avoids an unnecessary full-frame
memset of the alpha plane.

Fixes: out of array read
Fixes: 
500770604/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-6157374833623040

Found-by: continuous fuzzing process 
https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg


>From 029404e16eb0a44f04bf161aeae2b05f785bb32f Mon Sep 17 00:00:00 2001
From: Zhao Zhili <[email protected]>
Date: Thu, 7 May 2026 12:46:10 +0800
Subject: [PATCH 1/2] avcodec/hevc: limit missing-ref fill to coded planes

generate_missing_ref walked frame->f->data[] until a NULL slot, which
on alpha-video frames extended to data[3] and read
sps->hshift[3]/vshift[3] out of bounds.

The alpha plane is produced by the alpha layer via
replace_alpha_plane; the base decoder path never reads or writes it.
Bound the fill loop by the SPS coded plane count. This both removes
the out-of-bounds shift access and avoids an unnecessary full-frame
memset of the alpha plane.

Fixes: out of array read
Fixes: 
500770604/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-6157374833623040

Found-by: continuous fuzzing process 
https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
---
 libavcodec/hevc/refs.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 1faede4e3d..f53768f816 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -473,12 +473,13 @@ static HEVCFrame *generate_missing_ref(HEVCContext *s, 
HEVCLayerContext *l, int
         return NULL;
 
     if (!s->avctx->hwaccel) {
+        int nb_planes = l->sps->chroma_format_idc ? 3 : 1;
         if (!l->sps->pixel_shift) {
-            for (i = 0; frame->f->data[i]; i++)
+            for (i = 0; i < nb_planes; i++)
                 memset(frame->f->data[i], 1 << (l->sps->bit_depth - 1),
                        frame->f->linesize[i] * AV_CEIL_RSHIFT(l->sps->height, 
l->sps->vshift[i]));
         } else {
-            for (i = 0; frame->f->data[i]; i++)
+            for (i = 0; i < nb_planes; i++)
                 for (y = 0; y < (l->sps->height >> l->sps->vshift[i]); y++) {
                     uint8_t *dst = frame->f->data[i] + y * 
frame->f->linesize[i];
                     AV_WN16(dst, 1 << (l->sps->bit_depth - 1));
-- 
2.52.0


>From 04752f42bb4aeb08bd5c32b738c333ee7dc302fa Mon Sep 17 00:00:00 2001
From: Zhao Zhili <[email protected]>
Date: Thu, 7 May 2026 14:42:09 +0800
Subject: [PATCH 2/2] avcodec/hevc: scope missing-ref loop counters locally

---
 libavcodec/hevc/refs.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index f53768f816..55db706a8a 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -466,7 +466,6 @@ static void mark_ref(HEVCFrame *frame, int flag)
 static HEVCFrame *generate_missing_ref(HEVCContext *s, HEVCLayerContext *l, 
int poc)
 {
     HEVCFrame *frame;
-    int i, y;
 
     frame = alloc_frame(s, l);
     if (!frame)
@@ -475,12 +474,12 @@ static HEVCFrame *generate_missing_ref(HEVCContext *s, 
HEVCLayerContext *l, int
     if (!s->avctx->hwaccel) {
         int nb_planes = l->sps->chroma_format_idc ? 3 : 1;
         if (!l->sps->pixel_shift) {
-            for (i = 0; i < nb_planes; i++)
+            for (int i = 0; i < nb_planes; i++)
                 memset(frame->f->data[i], 1 << (l->sps->bit_depth - 1),
                        frame->f->linesize[i] * AV_CEIL_RSHIFT(l->sps->height, 
l->sps->vshift[i]));
         } else {
-            for (i = 0; i < nb_planes; i++)
-                for (y = 0; y < (l->sps->height >> l->sps->vshift[i]); y++) {
+            for (int i = 0; i < nb_planes; i++)
+                for (int y = 0; y < (l->sps->height >> l->sps->vshift[i]); 
y++) {
                     uint8_t *dst = frame->f->data[i] + y * 
frame->f->linesize[i];
                     AV_WN16(dst, 1 << (l->sps->bit_depth - 1));
                     av_memcpy_backptr(dst + 2, 2, 2*(l->sps->width >> 
l->sps->hshift[i]) - 2);
-- 
2.52.0

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

Reply via email to