[FFmpeg-devel] [PATCH] avcodec/hevcdec: check that the local context list exists before dereferencing it
Andreas Rheinhardt
andreas.rheinhardt at gmail.com
Wed Feb 10 19:57:02 EET 2021
James Almer:
> Since the decoder is not flagged as init cleanup capable, hevc_decode_free()
> is being called manually if the hevc_decode_extradata() call fails at the end
> of hevc_decode_init().
> In a frame threading scenario, however, if AVCodec->init() returns an error,
> ff_frame_thread_free() will be called regardless of the above flag being set
> or not, resulting in hevc_decode_free() being called a second time for the
> same context.
>
> Solve this by ensuring pointers are not dereferenced if they are NULL, and
> setting the decoder as init cleanup capable.
>
> Fixes ticket #9099.
>
> Signed-off-by: James Almer <jamrial at gmail.com>
> ---
> Maybe ff_frame_thread_free() should not call AVCodec->close() for thread contexts
> where AVCodec->init() failed and FF_CODEC_CAP_INIT_CLEANUP is not set?
>
Fixing this has been on my to-do list. (The situation is even worse than
you describe it: It is possible that AVCodec->close is called on an
AVCodecContext whose private_data couldn't be allocated.)
> libavcodec/hevcdec.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
> index 92eb888033..898dac8cbb 100644
> --- a/libavcodec/hevcdec.c
> +++ b/libavcodec/hevcdec.c
> @@ -3417,6 +3417,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
> av_freep(&s->sh.offset);
> av_freep(&s->sh.size);
>
> + if (s->HEVClcList && s->sList) {
> for (i = 1; i < s->threads_number; i++) {
> HEVCLocalContext *lc = s->HEVClcList[i];
> if (lc) {
> @@ -3424,9 +3425,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
> av_freep(&s->sList[i]);
> }
> }
> - if (s->HEVClc == s->HEVClcList[0])
> - s->HEVClc = NULL;
> - av_freep(&s->HEVClcList[0]);
> + }
> + av_freep(&s->HEVClc);
> av_freep(&s->HEVClcList);
> av_freep(&s->sList);
>
> @@ -3622,7 +3622,6 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx)
> if (avctx->extradata_size > 0 && avctx->extradata) {
> ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1);
> if (ret < 0) {
> - hevc_decode_free(avctx);
> return ret;
> }
> }
> @@ -3673,7 +3672,7 @@ AVCodec ff_hevc_decoder = {
> .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
> AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
> .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING |
> - FF_CODEC_CAP_ALLOCATE_PROGRESS,
> + FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP,
> .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles),
> .hw_configs = (const AVCodecHWConfigInternal *const []) {
> #if CONFIG_HEVC_DXVA2_HWACCEL
>
More information about the ffmpeg-devel
mailing list