Commit 50e9ef29be for ffmpeg
commit 50e9ef29be1766404115b0a4908fa3fd6ed7fa3f
Author: Lynne <dev@lynne.ee>
Date: Thu Dec 18 01:34:58 2025 +0100
mjpegdec: use refstruct for the hwaccel_picture_private
This was missed when the hwaccel_picture_private was made a buffer.
Fixes: YMGIFa63VNkS
Fixes: AISLE-2026-0150-00681
Fixes: memleak
Memleak Replicated through UnModified FFmpeg with ASAN
Found-by: Joshua Rogers (AISLE)
Cherry-picked from https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24652 where
the commit is part of the Vulkan MJPEG hwaccel. The Fixes, replication and
Found-by lines were added when applying it for the security report; the
start_frame() call keeps passing NULL as the preceding commits of that pull
request are not included.
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 3716bbf753..1f11b6fbb7 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -824,15 +824,21 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
if (s->avctx->hwaccel) {
const FFHWAccel *hwaccel = ffhwaccel(s->avctx->hwaccel);
- s->hwaccel_picture_private =
- av_mallocz(hwaccel->frame_priv_data_size);
- if (!s->hwaccel_picture_private)
- return AVERROR(ENOMEM);
+
+ /* A previous frame may have been aborted before its end_frame call,
+ * leaving the private data behind. */
+ av_refstruct_unref(&s->hwaccel_picture_private);
+
+ ret = ff_hwaccel_frame_priv_alloc(s->avctx, &s->hwaccel_picture_private);
+ if (ret < 0)
+ return ret;
ret = hwaccel->start_frame(s->avctx, NULL, s->raw_image_buffer,
s->raw_image_buffer_size);
- if (ret < 0)
+ if (ret < 0) {
+ av_refstruct_unref(&s->hwaccel_picture_private);
return ret;
+ }
}
return 0;
@@ -2582,7 +2588,7 @@ eoi_parser:
if (ret < 0)
return ret;
- av_freep(&s->hwaccel_picture_private);
+ av_refstruct_unref(&s->hwaccel_picture_private);
}
if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0)
return ret;
@@ -2965,7 +2971,7 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
reset_icc_profile(s);
- av_freep(&s->hwaccel_picture_private);
+ av_refstruct_unref(&s->hwaccel_picture_private);
av_freep(&s->jls_state);
return 0;
@@ -2976,6 +2982,8 @@ static av_cold void decode_flush(AVCodecContext *avctx)
MJpegDecodeContext *s = avctx->priv_data;
s->got_picture = 0;
+ av_refstruct_unref(&s->hwaccel_picture_private);
+
s->smv_next_frame = 0;
av_frame_unref(s->smv_frame);
}