[FFmpeg-devel] [PATCH 1/3] avformat/matroskadec: Reset state also on failure in matroska_reset_status()

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Fri Jul 2 19:17:58 EEST 2021


Michael Niedermayer:
> The calling code does not handle failures and will fail with assertion failures later.
> Seeking can always fail even when the position was previously read.
> 
> Fixes: Assertion failure
> Fixes: 35253/clusterfuzz-testcase-minimized-ffmpeg_dem_MATROSKA_fuzzer-4693059982983168
> 
> Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
> Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
> ---
>  libavformat/matroskadec.c | 19 ++++++++++++-------
>  1 file changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> index 356a02339c..a0e6e0cf8b 100644
> --- a/libavformat/matroskadec.c
> +++ b/libavformat/matroskadec.c
> @@ -804,20 +804,22 @@ static int matroska_read_close(AVFormatContext *s);
>  static int matroska_reset_status(MatroskaDemuxContext *matroska,
>                                   uint32_t id, int64_t position)
>  {
> +    int64_t err = 0;
>      if (position >= 0) {
> -        int64_t err = avio_seek(matroska->ctx->pb, position, SEEK_SET);
> -        if (err < 0)
> -            return err;
> -    }
> +        err = avio_seek(matroska->ctx->pb, position, SEEK_SET);
> +        if (err > 0)
> +            err = 0;
> +    } else
> +        position = avio_tell(matroska->ctx->pb);
>  
>      matroska->current_id    = id;
>      matroska->num_levels    = 1;
>      matroska->unknown_count = 0;
> -    matroska->resync_pos = avio_tell(matroska->ctx->pb);
> +    matroska->resync_pos    = position;
>      if (id)
>          matroska->resync_pos -= (av_log2(id) + 7) / 8;
>  
> -    return 0;
> +    return err;

The changes here will make the demuxer update its internal state as if
it had seeked to its target level-1-element, even though it didn't. Is
this really good?

>  }
>  
>  static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos)
> @@ -1873,6 +1875,7 @@ static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska,
>      uint32_t saved_id  = matroska->current_id;
>      int64_t before_pos = avio_tell(matroska->ctx->pb);
>      int ret = 0;
> +    int ret2;
>  
>      /* seek */
>      if (avio_seek(matroska->ctx->pb, pos, SEEK_SET) == pos) {
> @@ -1897,7 +1900,9 @@ static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska,
>      }
>      /* Seek back - notice that in all instances where this is used
>       * it is safe to set the level to 1. */
> -    matroska_reset_status(matroska, saved_id, before_pos);
> +    ret2 = matroska_reset_status(matroska, saved_id, before_pos);
> +    if (ret >= 0)
> +        ret = ret2;
>  
>      return ret;
>  }
> 



More information about the ffmpeg-devel mailing list