[FFmpeg-devel] [PATCH] avcodec/hevcdec: check that the local context list exists before dereferencing it

Paul B Mahol onemda at gmail.com
Thu Feb 11 01:59:51 EET 2021


On Wed, Feb 10, 2021 at 6:57 PM Andreas Rheinhardt <
andreas.rheinhardt at gmail.com> wrote:

> 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.)
>

So how should proceed? Apply this patch and fix other issues after it?

>
> >  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
> >
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list