Chromium fuzzing produced a whacky file with extra tkhds. This caused an AVStream that was already in use to be corrupted by assigning it a new id, which blows up later in mov_read_trun because the MOVFragmentStreamInfo.index_entry now points OOB. --- libavformat/isom.h | 3 ++- libavformat/mov.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/libavformat/isom.h b/libavformat/isom.h index e629663949..e14d670f2f 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -230,7 +230,8 @@ typedef struct MOVStreamContext { uint32_t format; - int has_sidx; // If there is an sidx entry for this stream. + int has_sidx; ///< If there is a sidx entry for this stream. + int has_tkhd; ///< If there is a tkhd entry for this stream. struct { struct AVAESCTR* aes_ctr; unsigned int per_sample_iv_size; // Either 0, 8, or 16. diff --git a/libavformat/mov.c b/libavformat/mov.c index ec57a05803..47c53d7992 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4438,6 +4438,12 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) st = c->fc->streams[c->fc->nb_streams-1]; sc = st->priv_data; + // Each stream (trak) should have exactly 1 tkhd. This catches bad files and + // avoids corrupting AVStreams mapped to an earlier tkhd. + if (sc->has_tkhd) + return AVERROR_INVALIDDATA; + sc->has_tkhd = 1; + version = avio_r8(pb); flags = avio_rb24(pb); st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0; @@ -4704,6 +4710,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) break; } } + av_assert0(index_entry_pos <= st->nb_index_entries); avio_r8(pb); /* version */ flags = avio_rb24(pb); -- 2.20.0.rc2.403.gdbc3b29805-goog _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel