From 2c6cd8098844f2367f8ba0a3a483e405c8f76449 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Oct 2026 03:22:33 +0200 Subject: [PATCH] avcodec/vdpau: free the bitstream buffer table when the picture is released Fixes: pzezUDNFoag5 Fixes: AISLE-2026-0150-00646 Fixes: memleak Memleak Replicated through UnModified FFmpeg with ASAN Found-by: Joshua Rogers (AISLE) The report suggested a free_frame_priv callback that frees bitstream_buffers. --- libavcodec/vdpau.c | 7 +++++++ libavcodec/vdpau_av1.c | 1 + libavcodec/vdpau_h264.c | 1 + libavcodec/vdpau_hevc.c | 1 + libavcodec/vdpau_internal.h | 2 ++ libavcodec/vdpau_mpeg12.c | 2 ++ libavcodec/vdpau_mpeg4.c | 1 + libavcodec/vdpau_vc1.c | 2 ++ libavcodec/vdpau_vp9.c | 1 + 9 files changed, 18 insertions(+) diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index e99ac5338d..2c13113551 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -349,6 +349,13 @@ int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, return vdpau_error(status); } +void ff_vdpau_free_frame_priv(AVRefStructOpaque hwctx, void *data) +{ + struct vdpau_picture_context *pic_ctx = data; + + av_freep(&pic_ctx->bitstream_buffers); +} + #if CONFIG_MPEG1_VDPAU_HWACCEL || \ CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \ CONFIG_VC1_VDPAU_HWACCEL || CONFIG_WMV3_VDPAU_HWACCEL diff --git a/libavcodec/vdpau_av1.c b/libavcodec/vdpau_av1.c index b7e7fa8b0c..aaf8cd57c0 100644 --- a/libavcodec/vdpau_av1.c +++ b/libavcodec/vdpau_av1.c @@ -362,6 +362,7 @@ const FFHWAccel ff_av1_vdpau_hwaccel = { .end_frame = vdpau_av1_end_frame, .decode_slice = vdpau_av1_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_av1_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c index 51c7e99900..df0ae7d5c8 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -271,6 +271,7 @@ const FFHWAccel ff_h264_vdpau_hwaccel = { .end_frame = vdpau_h264_end_frame, .decode_slice = vdpau_h264_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_h264_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c index 1a92c32b27..1a8429475e 100644 --- a/libavcodec/vdpau_hevc.c +++ b/libavcodec/vdpau_hevc.c @@ -551,6 +551,7 @@ const FFHWAccel ff_hevc_vdpau_hwaccel = { .end_frame = vdpau_hevc_end_frame, .decode_slice = vdpau_hevc_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_hevc_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index 347576e0c3..8a4ed13d1a 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -30,6 +30,7 @@ #include "libavutil/frame.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vdpau.h" +#include "libavutil/refstruct.h" #include "avcodec.h" #include "vdpau.h" @@ -125,6 +126,7 @@ int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic, const uint8_t *buffer, uint32_t size); int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, struct vdpau_picture_context *pic); +void ff_vdpau_free_frame_priv(AVRefStructOpaque hwctx, void *data); int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx); int ff_vdpau_add_buffer(struct vdpau_picture_context *pic, const uint8_t *buf, uint32_t buf_size); diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index b3ac94f217..59047d699c 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -116,6 +116,7 @@ const FFHWAccel ff_mpeg1_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_mpeg1_init, .uninit = ff_vdpau_common_uninit, .priv_data_size = sizeof(VDPAUContext), @@ -151,6 +152,7 @@ const FFHWAccel ff_mpeg2_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_mpeg2_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 58c8a6d769..10f8980567 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -122,6 +122,7 @@ const FFHWAccel ff_mpeg4_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_mpeg4_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_mpeg4_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index 323ac4127a..90ce5ace9f 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -149,6 +149,7 @@ const FFHWAccel ff_wmv3_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_vc1_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_vc1_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, @@ -166,6 +167,7 @@ const FFHWAccel ff_vc1_vdpau_hwaccel = { .end_frame = ff_vdpau_mpeg_end_frame, .decode_slice = vdpau_vc1_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_vc1_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params, diff --git a/libavcodec/vdpau_vp9.c b/libavcodec/vdpau_vp9.c index 7b3c1ff4d7..83a17ed74d 100644 --- a/libavcodec/vdpau_vp9.c +++ b/libavcodec/vdpau_vp9.c @@ -232,6 +232,7 @@ const FFHWAccel ff_vp9_vdpau_hwaccel = { .end_frame = vdpau_vp9_end_frame, .decode_slice = vdpau_vp9_decode_slice, .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .free_frame_priv = ff_vdpau_free_frame_priv, .init = vdpau_vp9_init, .uninit = ff_vdpau_common_uninit, .frame_params = ff_vdpau_common_frame_params,