From: Michael Niedermayer <[email protected]>
This avoids adding index entries for files where the index
is defined in an incompatible way, or where it simply is broken.
This requires doing a short seek to the second index entry to
validate the index, and thus we need to seek back at the end
of the parsing function, even if we were able to parse the whole
index successfully.
---
libavformat/flvdec.c | 32 +++++++++++++++++++++++++-------
1 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index de6168c..c652baa 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -203,20 +203,38 @@ static int parse_keyframes_index(AVFormatContext *s,
AVIOContext *ioc, AVStream
}
}
- if (!ret && timeslen == fileposlen)
+ if (!ret && timeslen == fileposlen && fileposlen > 1 &&
+ max_pos <= filepositions[0]) {
+ int64_t dts, size0, size1;
+ /* Seek back to the end of the index (instead to before it)
+ * afterwards, since we parsed it successfully. */
+ initial_pos = avio_tell(ioc);
+ avio_seek(ioc, filepositions[1] - 4, SEEK_SET);
+ size0 = avio_rb32(ioc);
+ avio_r8(ioc);
+ size1 = avio_rb24(ioc);
+ dts = avio_rb24(ioc);
+ dts |= avio_r8(ioc) << 24;
+ /* A quick index sanity check: size0, the size of the packet
+ * preceding the second index entry, should be less than the
+ * file position. The timestamp of the packet should be
+ * within 5 seconds from what the index claimed it to be.
+ * Anything else indicates an incorrectly interpreted or simply
+ * broken index.
+ */
+ if (size0 > filepositions[1] || FFABS(dts - times[1]*1000) > 5000)
+ goto finish;
for (i = 0; i < fileposlen; i++)
av_add_index_entry(vstream, filepositions[i], times[i]*1000, 0, 0,
AVINDEX_KEYFRAME);
- else
+ } else
av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
finish:
av_freep(×);
av_freep(&filepositions);
- // If we got unexpected data, but successfully reset back to
- // the start pos, the caller can continue parsing
- if (ret < 0 && avio_seek(ioc, initial_pos, SEEK_SET) > 0)
- return 0;
- return ret;
+ if (avio_seek(ioc, initial_pos, SEEK_SET) != initial_pos)
+ return ret ? ret : AVERROR(EIO);
+ return 0;
}
static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream
*vstream, const char *key, int64_t max_pos, int depth) {
--
1.7.3.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel