diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-09-23 11:56:24 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-09-23 11:56:29 +0200 |
commit | 09e06cd90fa2208446851d921f1104bbb957b883 (patch) | |
tree | 8a0281eb2105913a79376b86367d70ddd21d0117 | |
parent | eaa20afa760815aeccf5626185d901dd3504143d (diff) | |
parent | c951e4b442df9dde6051634a85359eb809bf2142 (diff) | |
download | ffmpeg-09e06cd90fa2208446851d921f1104bbb957b883.tar.gz |
Merge commit 'c951e4b442df9dde6051634a85359eb809bf2142'
* commit 'c951e4b442df9dde6051634a85359eb809bf2142':
flv: Make onTextData parsing robust
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/flvdec.c | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 9a5ca872b1..d81a70b93b 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -653,35 +653,84 @@ static void clear_index_entries(AVFormatContext *s, int64_t pos) } } +static int amf_skip_tag(AVIOContext *pb, AMFDataType type) +{ + int nb = -1, ret, parse_name = 1; + + switch (type) { + case AMF_DATA_TYPE_NUMBER: + avio_skip(pb, 8); + break; + case AMF_DATA_TYPE_BOOL: + avio_skip(pb, 1); + break; + case AMF_DATA_TYPE_STRING: + avio_skip(pb, avio_rb16(pb)); + break; + case AMF_DATA_TYPE_ARRAY: + parse_name = 0; + case AMF_DATA_TYPE_MIXEDARRAY: + nb = avio_rb32(pb); + case AMF_DATA_TYPE_OBJECT: + while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) { + if (parse_name) { + int size = avio_rb16(pb); + if (!size) { + avio_skip(pb, 1); + break; + } + avio_skip(pb, size); + } + if ((ret = amf_skip_tag(pb, avio_r8(pb))) < 0) + return ret; + } + break; + case AMF_DATA_TYPE_NULL: + case AMF_DATA_TYPE_OBJECT_END: + break; + default: + return AVERROR_INVALIDDATA; + } + return 0; +} + static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, int64_t dts, int64_t next) { AVIOContext *pb = s->pb; AVStream *st = NULL; - AMFDataType type; char buf[20]; - int ret, i, length; + int ret = AVERROR_INVALIDDATA; + int i, length = -1; - type = avio_r8(pb); - if (type == AMF_DATA_TYPE_MIXEDARRAY) + switch (avio_r8(pb)) { + case AMF_DATA_TYPE_MIXEDARRAY: avio_seek(pb, 4, SEEK_CUR); - else if (type != AMF_DATA_TYPE_OBJECT) - return AVERROR_INVALIDDATA; - - amf_get_string(pb, buf, sizeof(buf)); - if (strcmp(buf, "type") || avio_r8(pb) != AMF_DATA_TYPE_STRING) - return AVERROR_INVALIDDATA; + case AMF_DATA_TYPE_OBJECT: + break; + default: + goto skip; + } - amf_get_string(pb, buf, sizeof(buf)); - // FIXME parse it as codec_id - amf_get_string(pb, buf, sizeof(buf)); - if (strcmp(buf, "text") || avio_r8(pb) != AMF_DATA_TYPE_STRING) - return AVERROR_INVALIDDATA; + while ((ret = amf_get_string(pb, buf, sizeof(buf))) > 0) { + AMFDataType type = avio_r8(pb); + if (type == AMF_DATA_TYPE_STRING && !strcmp(buf, "text")) { + length = avio_rb16(pb); + ret = av_get_packet(pb, pkt, length); + if (ret < 0) + goto skip; + else + break; + } else { + if ((ret = amf_skip_tag(pb, type)) < 0) + goto skip; + } + } - length = avio_rb16(pb); - ret = av_get_packet(s->pb, pkt, length); - if (ret < 0) - return AVERROR(EIO); + if (length < 0) { + ret = AVERROR_INVALIDDATA; + goto skip; + } for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; @@ -703,6 +752,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, pkt->stream_index = st->index; pkt->flags |= AV_PKT_FLAG_KEY; +skip: avio_seek(s->pb, next + 4, SEEK_SET); return ret; |