summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/matroskadec.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 81e9bb9bff..cba2b3d1f8 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -1203,11 +1203,29 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska,
MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
AVIOContext *pb = matroska->ctx->pb;
int64_t pos = avio_tell(pb);
- if (level->length != EBML_UNKNOWN_LENGTH &&
- (pos + length) > (level->start + level->length)) {
+
+ if (length != EBML_UNKNOWN_LENGTH &&
+ level->length != EBML_UNKNOWN_LENGTH) {
+ uint64_t elem_end = pos + length,
+ level_end = level->start + level->length;
+
+ if (level_end < elem_end) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Element at 0x%"PRIx64" ending at 0x%"PRIx64" exceeds "
+ "containing master element ending at 0x%"PRIx64"\n",
+ pos, elem_end, level_end);
+ return AVERROR_INVALIDDATA;
+ }
+ } else if (level->length != EBML_UNKNOWN_LENGTH) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "Unknown-sized element "
+ "at 0x%"PRIx64" inside parent with finite size\n", pos);
+ return AVERROR_INVALIDDATA;
+ } else if (length == EBML_UNKNOWN_LENGTH && id != MATROSKA_ID_CLUSTER) {
+ // According to the specifications only clusters and segments
+ // are allowed to be unknown-sized.
av_log(matroska->ctx, AV_LOG_ERROR,
- "Invalid length 0x%"PRIx64" > 0x%"PRIx64" in parent\n",
- length, level->start + level->length);
+ "Found unknown-sized element other than a cluster at "
+ "0x%"PRIx64". Dropping the invalid element.\n", pos);
return AVERROR_INVALIDDATA;
}
}