summaryrefslogtreecommitdiffstats
path: root/demux/ebml.c
diff options
context:
space:
mode:
Diffstat (limited to 'demux/ebml.c')
-rw-r--r--demux/ebml.c73
1 files changed, 36 insertions, 37 deletions
diff --git a/demux/ebml.c b/demux/ebml.c
index c875ef564c..2c540ad093 100644
--- a/demux/ebml.c
+++ b/demux/ebml.c
@@ -41,6 +41,26 @@
#define SIZE_MAX ((size_t)-1)
#endif
+// Whether the id is a known Matroska level 1 element (allowed as element on
+// global file level, after the level 0 MATROSKA_ID_SEGMENT).
+// This (intentionally) doesn't include "global" elements.
+bool ebml_is_mkv_level1_id(uint32_t id)
+{
+ switch (id) {
+ case MATROSKA_ID_SEEKHEAD:
+ case MATROSKA_ID_INFO:
+ case MATROSKA_ID_CLUSTER:
+ case MATROSKA_ID_TRACKS:
+ case MATROSKA_ID_CUES:
+ case MATROSKA_ID_ATTACHMENTS:
+ case MATROSKA_ID_CHAPTERS:
+ case MATROSKA_ID_TAGS:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
* Read: the element content data ID.
* Return: the ID.
@@ -252,21 +272,32 @@ char *ebml_read_utf8(stream_t *s, uint64_t *length)
/*
* Skip the current element.
+ * end: the end of the parent element or -1 (for robust error handling)
*/
-int ebml_read_skip(stream_t *s, uint64_t *length)
+int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s)
{
uint64_t len;
int l;
+ int64_t pos = stream_tell(s);
+
len = ebml_read_length(s, &l);
if (len == EBML_UINT_INVALID)
- return 1;
- if (length)
- *length = len + l;
+ goto invalid;
+
+ int64_t pos2 = stream_tell(s);
+ if (len >= INT64_MAX - pos2 || (end > 0 && pos2 + len > end))
+ goto invalid;
- stream_skip(s, len);
+ if (!stream_skip(s, len))
+ goto invalid;
return 0;
+
+invalid:
+ mp_err(log, "Invalid EBML length at position %"PRId64"\n", pos);
+ stream_seek(s, pos);
+ return 1;
}
/*
@@ -292,38 +323,6 @@ int ebml_resync_cluster(struct mp_log *log, stream_t *s)
}
/*
- * Skip the current element, or on error, call ebml_resync_cluster().
- * end gives the maximum possible file pos (due to EBML parent element size).
- */
-int ebml_read_skip_or_resync_cluster(struct mp_log *log, int64_t end,
- stream_t *s)
-{
- uint64_t len;
- int l;
-
- len = ebml_read_length(s, &l);
- if (len == EBML_UINT_INVALID)
- goto resync;
-
- int64_t pos = stream_tell(s);
-
- if (end >= 0 && pos + len > end)
- goto resync;
-
- // When reading corrupted elements, len will often be a random high number,
- // and stream_skip() will fail when skipping past EOF.
- if (!stream_skip(s, len)) {
- stream_seek(s, pos);
- goto resync;
- }
-
- return 0;
-
-resync:
- return ebml_resync_cluster(log, s) < 0 ? -1 : 1;
-}
-
-/*
* Read the next element, but only the header. The contents
* are supposed to be sub-elements which can be read separately.
*/