Commit 6551acab authored by wm4's avatar wm4 Committed by Michael Niedermayer

avformat/matroskadec: fix handling of recursive SeekHead elements

When matroska_execute_seekhead() is called, it goes through the list of
seekhead entries and attempts to read elements not read yet. When doing
this, the parser can find further SeekHead elements, and will extend the
matroska->seekhead list. This can lead to a (practically) infinite loop
with certain broken files. (Maybe it can happen even with valid files.
The demuxer doesn't seem to check correctly whether an element has
already been read.)

Fix this by ignoring elements that were added to the seekhead field
during executing seekhead entries.

This does not fix the possible situation when multiple SeekHead elements
after the file header (i.e. occur after the "before_pos" file position)
point to the same elements. These elements will probably be parsed
multiple times, likely leading to bugs.

Fixes ticket #4162.
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent b1c8dfc8
...@@ -1414,13 +1414,17 @@ static void matroska_execute_seekhead(MatroskaDemuxContext *matroska) ...@@ -1414,13 +1414,17 @@ static void matroska_execute_seekhead(MatroskaDemuxContext *matroska)
EbmlList *seekhead_list = &matroska->seekhead; EbmlList *seekhead_list = &matroska->seekhead;
int64_t before_pos = avio_tell(matroska->ctx->pb); int64_t before_pos = avio_tell(matroska->ctx->pb);
int i; int i;
int nb_elem;
// we should not do any seeking in the streaming case // we should not do any seeking in the streaming case
if (!matroska->ctx->pb->seekable || if (!matroska->ctx->pb->seekable ||
(matroska->ctx->flags & AVFMT_FLAG_IGNIDX)) (matroska->ctx->flags & AVFMT_FLAG_IGNIDX))
return; return;
for (i = 0; i < seekhead_list->nb_elem; i++) { // do not read entries that are added while parsing seekhead entries
nb_elem = seekhead_list->nb_elem;
for (i = 0; i < nb_elem; i++) {
MatroskaSeekhead *seekhead = seekhead_list->elem; MatroskaSeekhead *seekhead = seekhead_list->elem;
if (seekhead[i].pos <= before_pos) if (seekhead[i].pos <= before_pos)
continue; continue;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment