[FFmpeg-cvslog] avformat/matroskadec: Redo EOF handling

Andreas Rheinhardt git at videolan.org
Tue Jul 16 22:49:51 EEST 2019


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at gmail.com> | Fri May 17 00:30:11 2019 +0200| [3ed2755baaf3f8a9f088f8c7b9cc7bd8c629e8fb] | committer: James Almer

avformat/matroskadec: Redo EOF handling

This commit closes the last hole in the system of checks for a
known-length file ending too early: Now an error message is emitted
in case the file ends directly after an EBML element.

Furthermore, this commit adds a check and a corresponding warning
whether there is data beyond the Matroska segment (only reasonable for
known-length segments). If everything looks alright, then parsing is
stopped as soon as EOF is reached (in contrast, the earlier code would
always call matroska_resync at the end).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>

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

 libavformat/matroskadec.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 19eb5b0041..8ab233b8df 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -1187,10 +1187,15 @@ static int ebml_parse(MatroskaDemuxContext *matroska,
                 if (matroska->is_live)
                     // in live mode, finish parsing if EOF is reached.
                     return 1;
-                if (level && level->length == EBML_UNKNOWN_LENGTH && pos == avio_tell(pb)) {
-                    // Unknown-length levels automatically end at EOF.
-                    matroska->num_levels--;
-                    return LEVEL_ENDED;
+                if (level && pos == avio_tell(pb)) {
+                    if (level->length == EBML_UNKNOWN_LENGTH) {
+                        // Unknown-length levels automatically end at EOF.
+                        matroska->num_levels--;
+                        return LEVEL_ENDED;
+                    } else {
+                        av_log(matroska->ctx, AV_LOG_ERROR, "File ended prematurely "
+                               "at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
+                    }
                 }
             }
             return res;
@@ -3622,6 +3627,14 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
     ebml_free(matroska_blockgroup, block);
     memset(block, 0, sizeof(*block));
     } else if (!matroska->num_levels) {
+        if (!avio_feof(matroska->ctx->pb)) {
+            avio_r8(matroska->ctx->pb);
+            if (!avio_feof(matroska->ctx->pb)) {
+                av_log(matroska->ctx, AV_LOG_WARNING, "File extends beyond "
+                       "end of segment.\n");
+                return AVERROR_INVALIDDATA;
+            }
+        }
         matroska->done = 1;
         return AVERROR_EOF;
     }
@@ -3642,7 +3655,7 @@ static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt)
     while (matroska_deliver_packet(matroska, pkt)) {
         if (matroska->done)
             return (ret < 0) ? ret : AVERROR_EOF;
-        if (matroska_parse_cluster(matroska) < 0)
+        if (matroska_parse_cluster(matroska) < 0 && !matroska->done)
             ret = matroska_resync(matroska, matroska->resync_pos);
     }
 



More information about the ffmpeg-cvslog mailing list