From 235f744f48ccecd9432c3fc5ced724bec0e4bb3e Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 20 Jul 2013 02:15:15 +0200 Subject: demux_mkv: fix some potential issues with small backwards seeks In some cases, the demuxer seeks backwards to unread EBML tags, so that other code can parse the properly. In theory, it could happen that a small backwards seek requires the stream buffer to be refilled (for example, because the preceding read caused a buffer refill and threw away the previous contents. So insert some strategical stream_peek() calls, which will transparently memmove() the buffer contents if needed. (Also, get rid of the pos variable in ebml_resync_cluster. This is an unrelated cosmetic change, I guess.) --- demux/demux_mkv.c | 1 + demux/ebml.c | 13 +++++++------ stream/stream.h | 6 ++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 8013aa3527..2cfb7de422 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1777,6 +1777,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) *demuxer->params->matroska_was_valid = true; while (1) { + stream_peek(s, 4); uint32_t id = ebml_read_id(s, NULL); if (s->eof) { mp_tmsg(MSGT_DEMUX, MSGL_WARN, diff --git a/demux/ebml.c b/demux/ebml.c index 98ab1ef306..9b198fc132 100644 --- a/demux/ebml.c +++ b/demux/ebml.c @@ -274,20 +274,21 @@ int ebml_read_skip(stream_t *s, uint64_t *length) */ int ebml_resync_cluster(stream_t *s) { - int64_t pos = stream_tell(s); uint32_t last_4_bytes = 0; - mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Corrupt file detected. " - "Trying to resync starting from position %"PRId64"...\n", pos); + mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Corrupt file detected. Trying to " + "resync starting from position %"PRId64"...\n", stream_tell(s)); while (!s->eof) { // Assumes MATROSKA_ID_CLUSTER is 4 bytes, with no 0 bytes. if (last_4_bytes == MATROSKA_ID_CLUSTER) { + int64_t pos = stream_tell(s) - 4; mp_msg(MSGT_DEMUX, MSGL_ERR, - "[mkv] Cluster found at %"PRId64".\n", pos - 4); - stream_seek(s, pos - 4); + "[mkv] Cluster found at %"PRId64".\n", pos); + stream_seek(s, pos); return 0; } + if (stream_buffered(s) < 4) + stream_peek(s, STREAM_BUFFER_SIZE); last_4_bytes = (last_4_bytes << 8) | stream_read_char(s); - pos++; } return -1; } diff --git a/stream/stream.h b/stream/stream.h index a0cd3d58fc..b637461eda 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -215,6 +215,12 @@ inline static int64_t stream_tell(stream_t *s) return s->pos + s->buf_pos - s->buf_len; } +// Return number of buffered bytes. (Useful for optimization purposes.) +inline static int stream_buffered(stream_t *s) +{ + return s->buf_len - s->buf_pos; +} + int stream_skip(stream_t *s, int64_t len); int stream_seek(stream_t *s, int64_t pos); int stream_read(stream_t *s, char *mem, int total); -- cgit v1.2.3