[FFmpeg-cvslog] mxfdec: Never seek back in local sets and KLVs

Tomas Härdin git at videolan.org
Fri Feb 10 01:47:55 CET 2012


ffmpeg | branch: master | Tomas Härdin <tomas.hardin at codemill.se> | Thu Jan 26 13:21:38 2012 +0100| [11800c8c8961bc261c7e0f4669e50f3a1e4862cd] | committer: Diego Biurrun

mxfdec: Never seek back in local sets and KLVs

Specially crafted files can lead the parsing code to take too long.
We fix a lot of these problems by not allowing local tags to extend
past the end of the set and not allowing other KLVs to be read past
the end of themselves.

Signed-off-by: Diego Biurrun <diego at biurrun.de>

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

 libavformat/mxfdec.c |   18 +++++++++++++++++-
 1 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index f17952b..d305e73 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -1499,7 +1499,15 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF
         else if ((ret = read_child(ctx, pb, tag, size, uid, -1)) < 0)
             return ret;
 
-        avio_seek(pb, next, SEEK_SET);
+        /* Accept the 64k local set limit being exceeded (Avid). Don't accept
+         * it extending past the end of the KLV though (zzuf5.mxf). */
+        if (avio_tell(pb) > klv_end) {
+            av_log(mxf->fc, AV_LOG_ERROR,
+                   "local tag %#04x extends past end of local set @ %#"PRIx64"\n",
+                   tag, klv->offset);
+            return AVERROR_INVALIDDATA;
+        } else if (avio_tell(pb) <= next)   /* only seek forward, else this can loop for a long time */
+            avio_seek(pb, next, SEEK_SET);
     }
     if (ctx_size) ctx->type = type;
     return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0;
@@ -1717,6 +1725,14 @@ static int mxf_read_header(AVFormatContext *s)
                 } else {
                     uint64_t next = avio_tell(s->pb) + klv.length;
                     res = metadata->read(mxf, s->pb, 0, klv.length, klv.key, klv.offset);
+
+                    /* only seek forward, else this can loop for a long time */
+                    if (avio_tell(s->pb) > next) {
+                        av_log(s, AV_LOG_ERROR, "read past end of KLV @ %#"PRIx64"\n",
+                               klv.offset);
+                        return AVERROR_INVALIDDATA;
+                    }
+
                     avio_seek(s->pb, next, SEEK_SET);
                 }
                 if (res < 0) {



More information about the ffmpeg-cvslog mailing list