diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2012-12-10 12:44:09 -0500 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2013-07-10 10:25:50 +0200 |
commit | e786cc33312083382f4ca394e67e1cb58c786289 (patch) | |
tree | 5fe61280d1770d376e6ea969b55ee7ed7f795e83 | |
parent | 8c62082b5127011db0c251f6a48b2872af8c3bc6 (diff) | |
download | ffmpeg-e786cc33312083382f4ca394e67e1cb58c786289.tar.gz |
swfdec: do better validation of tag length
Avoids trying to read a packet with 0 or negative size.
Avoids a potential infinite loop due to seeking backwards.
Partially based on a patch by Michael Niedermayer.
(cherry picked from commit e70c5b034c4787377e82cab2d5565486baec0c2a)
Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
-rw-r--r-- | libavformat/swfdec.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index 6966176a34..faf74c525c 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -91,6 +91,10 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) tag = get_swf_tag(pb, &len); if (tag < 0) return AVERROR(EIO); + if (len < 0) { + av_log(s, AV_LOG_ERROR, "invalid tag length: %d\n", len); + return AVERROR_INVALIDDATA; + } if (tag == TAG_VIDEOSTREAM) { int ch_id = avio_rl16(pb); len -= 2; @@ -150,7 +154,10 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) st = s->streams[i]; if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) { frame = avio_rl16(pb); - if ((res = av_get_packet(pb, pkt, len-2)) < 0) + len -= 2; + if (len <= 0) + goto skip; + if ((res = av_get_packet(pb, pkt, len)) < 0) return res; pkt->pos = pos; pkt->pts = frame; @@ -164,9 +171,14 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) { if (st->codec->codec_id == CODEC_ID_MP3) { avio_skip(pb, 4); - if ((res = av_get_packet(pb, pkt, len-4)) < 0) + len -= 4; + if (len <= 0) + goto skip; + if ((res = av_get_packet(pb, pkt, len)) < 0) return res; } else { // ADPCM, PCM + if (len <= 0) + goto skip; if ((res = av_get_packet(pb, pkt, len)) < 0) return res; } @@ -193,7 +205,10 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) st = vst; } avio_rl16(pb); /* BITMAP_ID */ - if ((res = av_new_packet(pkt, len-2)) < 0) + len -= 2; + if (len < 4) + goto skip; + if ((res = av_new_packet(pkt, len)) < 0) return res; avio_read(pb, pkt->data, 4); if (AV_RB32(pkt->data) == 0xffd8ffd9 || @@ -210,6 +225,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) return pkt->size; } skip: + len = FFMAX(0, len); avio_skip(pb, len); } } |