summaryrefslogtreecommitdiff
path: root/libavformat/matroskadec.c
diff options
context:
space:
mode:
authorwm4 <nfxjfg@googlemail.com>2015-06-12 13:11:41 +0200
committerMichael Niedermayer <michaelni@gmx.at>2015-06-12 19:30:11 +0200
commit7e240f95818310ed721321e62130aa1c69f9cbe6 (patch)
tree727903485eae6da6a628ffec04ce545b08e163a1 /libavformat/matroskadec.c
parentcfe8a89b0087d08b73f1fec850b1a972f82388bb (diff)
matroskadec: verify seekhead IDs
Some files have SeekHead elements with broken IDs. They mismatch with the ID of the destination element. These files are written by "IDMmkvlib0.1" (as identified by the MuxingApp and WritingApp elements), and the SeekHead IDs are actually endian-swapped. This confuses the SeekHead logic of the demuxer. It will read some elements twice, because the SeekHead ID is used to identify and remember already read elements. With the file at hand, the stream list was duplicated by reading the Tracks element twice. Fix this by rejecting invalid EBML IDs in SeekHead entries. (This fix is relatively specific to the broken file at hand, and doesn't protect against some other cases of broken SeekHead, such as valid but mismatching target element IDs.) Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/matroskadec.c')
-rw-r--r--libavformat/matroskadec.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 16063412de..3512f0f8c8 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -995,6 +995,15 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
return res;
}
+static int is_ebml_id_valid(uint32_t id)
+{
+ // Due to endian nonsense in Matroska, the highest byte with any bits set
+ // will contain the leading length bit. This bit in turn identifies the
+ // total byte length of the element by its position within the byte.
+ unsigned int bits = av_log2(id);
+ return id && (bits + 7) / 8 == (8 - bits % 8);
+}
+
/*
* Allocate and return the entry for the level1 element with the given ID. If
* an entry already exists, return the existing entry.
@@ -1005,6 +1014,9 @@ static MatroskaLevel1Element *matroska_find_level1_elem(MatroskaDemuxContext *ma
int i;
MatroskaLevel1Element *elem;
+ if (!is_ebml_id_valid(id))
+ return NULL;
+
// Some files link to all clusters; useless.
if (id == MATROSKA_ID_CLUSTER)
return NULL;