Commit 64aeae9808 for ffmpeg
commit 64aeae98089bd6a2e9d46990abbe36fc08c432a7
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Wed Oct 14 17:12:12 2026 +0200
avcodec/lcevcdec: do not enhance a base picture whose format is not the one signalled
Fixes: NULL pointer dereference
Fixes: ESfSEfFqsNZe/gray8_hevc_420_10bit_1d.hevc
Found during triage/review of the security report yOAdvErxaeGg
NULL pointer dereference Replicated through UnModified FFmpeg with ASAN
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 57baaad15b..e1d908fd52 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -101,6 +101,7 @@ typedef struct DecodeContext {
FFLCEVCContext *ctx;
int frame;
enum AVPixelFormat format;
+ enum AVPixelFormat base_format;
int base_width;
int base_height;
int width;
@@ -1665,6 +1666,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
if (dc->lcevc.frame) {
ret = ff_lcevc_parse_frame(dc->lcevc.ctx, frame, &dc->lcevc.format,
+ &dc->lcevc.base_format,
&dc->lcevc.width, &dc->lcevc.height);
if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
return ret;
@@ -1672,7 +1674,8 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
// force get_buffer2() to allocate the base frame with at least the dimensions
// of the final enhanced frame, in order to prevent reinitializing the buffer
// pools unnecessarely
- if (!ret && dc->lcevc.width && dc->lcevc.height) {
+ if (!ret && dc->lcevc.width && dc->lcevc.height &&
+ frame->format == dc->lcevc.base_format) {
dc->lcevc.base_width = frame->width;
dc->lcevc.base_height = frame->height;
frame->width = FFMAX(frame->width, dc->lcevc.width);
@@ -1742,11 +1745,13 @@ int ff_attach_decode_data(AVCodecContext *avctx, AVFrame *frame)
if (dc->lcevc.frame) {
int ret = ff_lcevc_parse_frame(dc->lcevc.ctx, frame, &dc->lcevc.format,
+ &dc->lcevc.base_format,
&dc->lcevc.width, &dc->lcevc.height);
if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
return ret;
- if (!ret && dc->lcevc.width && dc->lcevc.height) {
+ if (!ret && dc->lcevc.width && dc->lcevc.height &&
+ frame->format == dc->lcevc.base_format) {
dc->lcevc.base_width = frame->width;
dc->lcevc.base_height = frame->height;
} else
@@ -2427,6 +2432,7 @@ av_cold void ff_decode_internal_sync(AVCodecContext *dst, const AVCodecContext *
dst_dc->lcevc.width = src_dc->lcevc.width;
dst_dc->lcevc.height = src_dc->lcevc.height;
dst_dc->lcevc.format = src_dc->lcevc.format;
+ dst_dc->lcevc.base_format = src_dc->lcevc.base_format;
#endif
}
diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c
index c82aa7229f..3e990c0544 100644
--- a/libavcodec/lcevcdec.c
+++ b/libavcodec/lcevcdec.c
@@ -513,7 +513,8 @@ int ff_lcevc_process(void *logctx, AVFrame *frame)
}
int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const AVFrame *frame,
- enum AVPixelFormat *format, int *width, int *height)
+ enum AVPixelFormat *format, enum AVPixelFormat *base_format,
+ int *width, int *height)
{
LCEVCRawProcessBlock *block = NULL;
const LCEVCRawGlobalConfig *gc;
@@ -536,6 +537,7 @@ int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const AVFrame *frame,
gc = block->payload;
*format = ff_lcevc_depth_type[gc->enhancement_depth_type][gc->chroma_sampling_type];
+ *base_format = ff_lcevc_depth_type[gc->base_depth_type][gc->chroma_sampling_type];
if (gc->resolution_type < 63) {
*width = ff_lcevc_resolution_type[gc->resolution_type].width;
*height = ff_lcevc_resolution_type[gc->resolution_type].height;
diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h
index b757acc3f9..91b58d15a5 100644
--- a/libavcodec/lcevcdec.h
+++ b/libavcodec/lcevcdec.h
@@ -66,6 +66,7 @@ typedef struct FFLCEVCFrame {
int ff_lcevc_alloc(FFLCEVCContext **plcevc, AVDictionary **options, int loglevel);
int ff_lcevc_process(void *logctx, struct AVFrame *frame);
int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const struct AVFrame *frame,
- enum AVPixelFormat *format, int *width, int *height);
+ enum AVPixelFormat *format, enum AVPixelFormat *base_format,
+ int *width, int *height);
#endif /* AVCODEC_LCEVCDEC_H */