diff options
author | Tomas Härdin <tomas.hardin@codemill.se> | 2011-12-21 10:49:27 +0100 |
---|---|---|
committer | Tomas Härdin <tomas.hardin@codemill.se> | 2011-12-21 14:17:29 +0100 |
commit | e7839602f469eb9dd5e1341d780c0c1667ac89ad (patch) | |
tree | 91158b40361b405f2cb1a3a7578f34c26733e176 /libavformat/mxfdec.c | |
parent | 184f479096dabcb1eafd9c661304f410a76780ed (diff) | |
download | ffmpeg-e7839602f469eb9dd5e1341d780c0c1667ac89ad.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.
Diffstat (limited to 'libavformat/mxfdec.c')
-rw-r--r-- | libavformat/mxfdec.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 5035a2fc2b..e1363747a9 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -1464,6 +1464,13 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF else if (read_child(ctx, pb, tag, size, uid, -1) < 0) return -1; + /* 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; @@ -1667,6 +1674,14 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) } 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) { |