aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorTomas Härdin <tomas.hardin@codemill.se>2012-01-26 13:21:38 +0100
committerDiego Biurrun <diego@biurrun.de>2012-02-09 12:46:12 +0100
commit11800c8c8961bc261c7e0f4669e50f3a1e4862cd (patch)
tree4928606e2591cd53fdca4f271644ebff81728fed /libavformat
parent687e2fdebd49cea57d1413db3baa13fa65583591 (diff)
downloadffmpeg-11800c8c8961bc261c7e0f4669e50f3a1e4862cd.tar.gz
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@biurrun.de>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/mxfdec.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index f17952b65c..d305e73977 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) {