[FFmpeg-cvslog] avformat/mov: Bail when invalid sample data is present.

Dale Curtis git at videolan.org
Fri Sep 1 01:57:30 EEST 2017


ffmpeg | branch: master | Dale Curtis <dalecurtis at chromium.org> | Mon Jul 31 13:44:22 2017 -0700| [f1e47f87131dd7c3718496b83911e17586e26e80] | committer: Michael Niedermayer

avformat/mov: Bail when invalid sample data is present.

ctts data in ffmpeg relies on the index entries array to be 1:1
with samples... yet sc->sample_count can be read directly from
the 'stsz' box and index entries are only generated if a chunk
count has been read from 'stco' box.

Ensure that if sc->sample_count > 0, sc->chunk_count is too as
a basic sanity check. Additionally we need to check that after
the index is built we have the right number of entries, so we
also check in mov_read_trun() that sc->sample_count ==
st->nb_index_entries.

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=f1e47f87131dd7c3718496b83911e17586e26e80
---

 libavformat/mov.c | 33 ++++++++++-----------------------
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 876f48d912..89b2af7597 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -3755,8 +3755,9 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     c->trak_index = -1;
 
     /* sanity checks */
-    if (sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
-                            (!sc->sample_size && !sc->sample_count))) {
+    if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
+                            (!sc->sample_size && !sc->sample_count))) ||
+        (!sc->chunk_count && sc->sample_count)) {
         av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n",
                st->index);
         return 0;
@@ -4284,26 +4285,6 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     entries = avio_rb32(pb);
     av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries);
 
-    /* Always assume the presence of composition time offsets.
-     * Without this assumption, for instance, we cannot deal with a track in fragmented movies that meet the following.
-     *  1) in the initial movie, there are no samples.
-     *  2) in the first movie fragment, there is only one sample without composition time offset.
-     *  3) in the subsequent movie fragments, there are samples with composition time offset. */
-    if (!sc->ctts_count && sc->sample_count)
-    {
-        /* Complement ctts table if moov atom doesn't have ctts atom. */
-        ctts_data = av_fast_realloc(NULL, &sc->ctts_allocated_size, sizeof(*sc->ctts_data) * sc->sample_count);
-        if (!ctts_data)
-            return AVERROR(ENOMEM);
-        /* Don't use a count greater than 1 here since it will leave a gap in
-         * the ctts index which the code below relies on being sequential. */
-        sc->ctts_data = ctts_data;
-        for (i = 0; i < sc->sample_count; i++) {
-            sc->ctts_data[sc->ctts_count].count = 1;
-            sc->ctts_data[sc->ctts_count].duration = 0;
-            sc->ctts_count++;
-        }
-    }
     if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data))
         return AVERROR_INVALIDDATA;
     if (flags & MOV_TRUN_DATA_OFFSET)        data_offset        = avio_rb32(pb);
@@ -4364,13 +4345,19 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             unsigned int size_needed = st->nb_index_entries * sizeof(*sc->ctts_data);
             unsigned int request_size = size_needed > sc->ctts_allocated_size ?
                 FFMAX(size_needed, 2 * sc->ctts_allocated_size) : size_needed;
+            unsigned int old_ctts_size = sc->ctts_allocated_size;
             ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size, request_size);
             if (!ctts_data) {
                 av_freep(&sc->ctts_data);
                 return AVERROR(ENOMEM);
             }
-
             sc->ctts_data = ctts_data;
+
+            // In case there were samples without ctts entries, ensure they get
+            // zero valued entries. This ensures clips which mix boxes with and
+            // without ctts entries don't pickup uninitialized data.
+            memset((uint8_t*)(sc->ctts_data) + old_ctts_size, 0, sc->ctts_allocated_size - old_ctts_size);
+
             if (ctts_index != old_nb_index_entries) {
                 memmove(sc->ctts_data + ctts_index + 1, sc->ctts_data + ctts_index,
                         sizeof(*sc->ctts_data) * (sc->ctts_count - ctts_index));



More information about the ffmpeg-cvslog mailing list