From 557df77eab7d3726c34221aeb999afe9e7818d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 11 Sep 2013 22:53:15 +0300 Subject: [PATCH 01/11] mpc8: Make sure the first stream exists before parsing the seek table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 17d57848fc14e82f76a65ffb25c90f2f011dc4a0) Signed-off-by: Luca Barbato --- libavformat/mpc8.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c index 66cf01ab73..c7aa87519c 100644 --- a/libavformat/mpc8.c +++ b/libavformat/mpc8.c @@ -139,6 +139,11 @@ static void mpc8_parse_seektable(AVFormatContext *s, int64_t off) int i, t, seekd; GetBitContext gb; + if (s->nb_streams == 0) { + av_log(s, AV_LOG_ERROR, "No stream added before parsing seek table\n"); + return; + } + avio_seek(s->pb, off, SEEK_SET); mpc8_get_chunk_header(s->pb, &tag, &size); if(tag != TAG_SEEKTABLE){ From 9eba02d5dd7036294ea350cb772822deec95b867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 11 Sep 2013 14:54:05 +0300 Subject: [PATCH 02/11] omadec: Properly check lengths before incrementing the position MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 342c43d154e586bc022c86b168fe8d36f69da9d3) Signed-off-by: Luca Barbato --- libavformat/omadec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/omadec.c b/libavformat/omadec.c index 8548fb5f78..040345187b 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -170,7 +170,11 @@ static int nprobe(AVFormatContext *s, uint8_t *enc_header, unsigned size, taglen = AV_RB32(&enc_header[pos+32]); datalen = AV_RB32(&enc_header[pos+36]) >> 4; - pos += 44 + taglen; + pos += 44; + if (size - pos < taglen) + return -1; + + pos += taglen; if (datalen << 4 > size - pos) return -1; From 153deed18bed43d16b272e8681b2a9b988d2682a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 11 Sep 2013 22:56:55 +0300 Subject: [PATCH 03/11] sierravmd: Do sanity checking of frame sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit the size to INT_MAX/2 (for simplicity) to be sure that size + BYTES_PER_FRAME_RECORD won't overflow. Also factorize other existing error return paths. Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 0ef1660a6365ce60ead8858936b6f3f8ea862826) Signed-off-by: Luca Barbato --- libavformat/sierravmd.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c index 359282c875..a8534be54c 100644 --- a/libavformat/sierravmd.c +++ b/libavformat/sierravmd.c @@ -88,7 +88,7 @@ static int vmd_read_header(AVFormatContext *s) unsigned char *raw_frame_table; int raw_frame_table_size; int64_t current_offset; - int i, j; + int i, j, ret; unsigned int total_frames; int64_t current_audio_pts = 0; unsigned char chunk[BYTES_PER_FRAME_RECORD]; @@ -175,15 +175,13 @@ static int vmd_read_header(AVFormatContext *s) raw_frame_table = av_malloc(raw_frame_table_size); vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame)); if (!raw_frame_table || !vmd->frame_table) { - av_free(raw_frame_table); - av_free(vmd->frame_table); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto error; } if (avio_read(pb, raw_frame_table, raw_frame_table_size) != raw_frame_table_size) { - av_free(raw_frame_table); - av_free(vmd->frame_table); - return AVERROR(EIO); + ret = AVERROR(EIO); + goto error; } total_frames = 0; @@ -199,6 +197,11 @@ static int vmd_read_header(AVFormatContext *s) avio_read(pb, chunk, BYTES_PER_FRAME_RECORD); type = chunk[0]; size = AV_RL32(&chunk[2]); + if (size > INT_MAX / 2) { + av_log(s, AV_LOG_ERROR, "Invalid frame size\n"); + ret = AVERROR_INVALIDDATA; + goto error; + } if(!size && type != 1) continue; switch(type) { @@ -235,6 +238,11 @@ static int vmd_read_header(AVFormatContext *s) vmd->frame_count = total_frames; return 0; + +error: + av_free(raw_frame_table); + av_free(vmd->frame_table); + return ret; } static int vmd_read_packet(AVFormatContext *s, From e47543eda585a6a3655d29bca17ab218f85f6646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 12 Sep 2013 11:31:53 +0300 Subject: [PATCH 04/11] vocdec: Don't update codec parameters mid-stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we really want to support parameter changes, they need to be signalled along with the AVPackets as parameter change side data, not just changing the AVCodecContext parameters when a packet is demuxed (since there may be other earlier packets yet undecoded). Something similar was already done for the sample rate in 0883109b2, but some parameters were left changeable. This avoids having to recheck the channel count for validity for each decoded frame in (ad)pcm decoders, unless the decoders explicitly say that they accept parameter changes. Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 5bbfe193a0a41bd2adb648c8c3f6901a575734a2) Signed-off-by: Luca Barbato --- libavformat/vocdec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/vocdec.c b/libavformat/vocdec.c index 4e06513735..2fb8440931 100644 --- a/libavformat/vocdec.c +++ b/libavformat/vocdec.c @@ -91,11 +91,11 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) if (sample_rate) dec->sample_rate = sample_rate; avpriv_set_pts_info(st, 64, 1, dec->sample_rate); + dec->channels = channels; + dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id); } else avio_skip(pb, 1); - dec->channels = channels; tmp_codec = avio_r8(pb); - dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id); voc->remaining_size -= 2; max_size -= 2; channels = 1; @@ -117,10 +117,10 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) if (!dec->sample_rate) { dec->sample_rate = avio_rl32(pb); avpriv_set_pts_info(st, 64, 1, dec->sample_rate); + dec->bits_per_coded_sample = avio_r8(pb); + dec->channels = avio_r8(pb); } else - avio_skip(pb, 4); - dec->bits_per_coded_sample = avio_r8(pb); - dec->channels = avio_r8(pb); + avio_skip(pb, 6); tmp_codec = avio_rl16(pb); avio_skip(pb, 4); voc->remaining_size -= 12; From 9f883e75e66a0cc0ddde78dabf52a8c78a25e9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 12 Sep 2013 11:58:25 +0300 Subject: [PATCH 05/11] cavsdec: Make sure a sequence header has been decoded before decoding pictures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit e90a6846c2c006fbebd00e1f2789f4a86fafacef) Signed-off-by: Luca Barbato Conflicts: libavcodec/cavsdec.c --- libavcodec/cavsdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index cef6b953a5..7cfb2ca21b 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -931,6 +931,11 @@ static int decode_pic(AVSContext *h) int skip_count = -1; enum cavs_mb mb_type; + if (!h->top_qp) { + av_log(h->avctx, AV_LOG_ERROR, "No sequence header decoded yet\n"); + return AVERROR_INVALIDDATA; + } + skip_bits(&h->gb, 16);//bbv_dwlay if (h->stc == PIC_PB_START_CODE) { h->cur.f->pict_type = get_bits(&h->gb, 2) + AV_PICTURE_TYPE_I; From b4c479a82adbb1301e3e549cd80cdd65208ddd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 12 Sep 2013 12:27:58 +0300 Subject: [PATCH 06/11] vp3: Check the framerate for validity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 6fc8226e29055858f28973bb3d27b63b3b65e616) Signed-off-by: Luca Barbato --- libavcodec/vp3.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 0340c22bb2..1d68c09ad6 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2160,6 +2160,10 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) fps.num = get_bits_long(gb, 32); fps.den = get_bits_long(gb, 32); if (fps.num && fps.den) { + if (fps.num < 0 || fps.den < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid framerate\n"); + return AVERROR_INVALIDDATA; + } av_reduce(&avctx->time_base.num, &avctx->time_base.den, fps.den, fps.num, 1<<30); } From aeca97a7b5c1ea966ace310dbf4db52d64faa698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 16 Sep 2013 15:05:03 +0300 Subject: [PATCH 07/11] svq3: Check for any negative return value from ff_h264_check_intra_pred_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also pass on any returned error code. Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 1115689d54ea95a084421f5a182b8dc56cbff978) Signed-off-by: Luca Barbato Conflicts: libavcodec/svq3.c --- libavcodec/svq3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index 68bf2f7a55..683b9dc948 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -634,9 +634,9 @@ static int svq3_decode_mb(SVQ3Context *svq3, unsigned int mb_type) dir = i_mb_type_info[mb_type - 8].pred_mode; dir = (dir >> 1) ^ 3 * (dir & 1) ^ 1; - if ((h->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, dir, 0)) == -1) { - av_log(h->s.avctx, AV_LOG_ERROR, "check_intra_pred_mode = -1\n"); - return -1; + if ((h->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, dir, 0)) < 0) { + av_log(h->s.avctx, AV_LOG_ERROR, "ff_h264_check_intra_pred_mode < 0\n"); + return h->intra16x16_pred_mode; } cbp = i_mb_type_info[mb_type - 8].cbp; From 9272aa469848cdd6516050e702acac6ecd1ed9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 16 Sep 2013 15:19:52 +0300 Subject: [PATCH 08/11] mace: Make sure that the channel count is set to a valid value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also return a proper error code. Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit e1f3847f860a1094a46be4c5f10db8df616c3135) Signed-off-by: Luca Barbato Conflicts: libavcodec/mace.c --- libavcodec/mace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/mace.c b/libavcodec/mace.c index c78a207a09..5074e4bb14 100644 --- a/libavcodec/mace.c +++ b/libavcodec/mace.c @@ -229,8 +229,8 @@ static av_cold int mace_decode_init(AVCodecContext * avctx) { MACEContext *ctx = avctx->priv_data; - if (avctx->channels > 2) - return -1; + if (avctx->channels > 2 || avctx->channels < 1) + return AVERROR(EINVAL); avctx->sample_fmt = AV_SAMPLE_FMT_S16P; avcodec_get_frame_defaults(&ctx->frame); From 9f7a8b8f8f6ad024410232d926b774261ef2ef36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 16 Sep 2013 15:36:24 +0300 Subject: [PATCH 09/11] matroskadec: Verify realaudio codec parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 569d18aa9dc989c37bb4d4b968026fe5afa6fff9) Signed-off-by: Luca Barbato --- libavformat/matroskadec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index fe4d932cf2..8a0c91bf9c 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1580,6 +1580,10 @@ static int matroska_read_header(AVFormatContext *s) track->audio.sub_packet_h = avio_rb16(&b); track->audio.frame_size = avio_rb16(&b); track->audio.sub_packet_size = avio_rb16(&b); + if (flavor <= 0 || track->audio.coded_framesize <= 0 || + track->audio.sub_packet_h <= 0 || track->audio.frame_size <= 0 || + track->audio.sub_packet_size <= 0) + return AVERROR_INVALIDDATA; track->audio.buf = av_malloc(track->audio.frame_size * track->audio.sub_packet_h); if (codec_id == AV_CODEC_ID_RA_288) { st->codec->block_align = track->audio.coded_framesize; From 20c8f176293e7520c6205b664e25ecf8a711253e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 16 Sep 2013 16:01:02 +0300 Subject: [PATCH 10/11] rv34: Check the return value from ff_rv34_decode_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 711c970168297683860422e95d6b7e37ee3c8367) Signed-off-by: Luca Barbato --- libavcodec/rv30.c | 4 +++- libavcodec/rv40.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c index 3c3579b565..b61b75dd77 100644 --- a/libavcodec/rv30.c +++ b/libavcodec/rv30.c @@ -244,9 +244,11 @@ static void rv30_loop_filter(RV34DecContext *r, int row) static av_cold int rv30_decode_init(AVCodecContext *avctx) { RV34DecContext *r = avctx->priv_data; + int ret; r->rv30 = 1; - ff_rv34_decode_init(avctx); + if ((ret = ff_rv34_decode_init(avctx)) < 0) + return ret; if(avctx->extradata_size < 2){ av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n"); return -1; diff --git a/libavcodec/rv40.c b/libavcodec/rv40.c index f95622ab5a..d317d07966 100644 --- a/libavcodec/rv40.c +++ b/libavcodec/rv40.c @@ -545,9 +545,11 @@ static void rv40_loop_filter(RV34DecContext *r, int row) static av_cold int rv40_decode_init(AVCodecContext *avctx) { RV34DecContext *r = avctx->priv_data; + int ret; r->rv30 = 0; - ff_rv34_decode_init(avctx); + if ((ret = ff_rv34_decode_init(avctx)) < 0) + return ret; if(!aic_top_vlc.bits) rv40_init_tables(); r->parse_slice_header = rv40_parse_slice_header; From 163196562fe744149ef599d754c30c08a9898381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 16 Sep 2013 17:17:26 +0300 Subject: [PATCH 11/11] oggparseogm: Convert to use bytestream2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Martin Storsjö (cherry picked from commit 19b9659f3174599e8685d329c4330b1ea8c4c6db) Signed-off-by: Luca Barbato --- libavformat/oggparseogm.c | 52 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index 7b3cda221e..56ea5575f2 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -37,60 +37,62 @@ ogm_header(AVFormatContext *s, int idx) struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; - const uint8_t *p = os->buf + os->pstart; + GetByteContext p; uint64_t time_unit; uint64_t spu; - if(!(*p & 1)) + bytestream2_init(&p, os->buf + os->pstart, os->psize); + if (!(bytestream2_peek_byte(&p) & 1)) return 0; - if(*p == 1) { - p++; + if (bytestream2_peek_byte(&p) == 1) { + bytestream2_skip(&p, 1); - if(*p == 'v'){ + if (bytestream2_peek_byte(&p) == 'v'){ int tag; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - p += 8; - tag = bytestream_get_le32(&p); + bytestream2_skip(&p, 8); + tag = bytestream2_get_le32(&p); st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag); st->codec->codec_tag = tag; - } else if (*p == 't') { + } else if (bytestream2_peek_byte(&p) == 't') { st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_TEXT; - p += 12; + bytestream2_skip(&p, 12); } else { - uint8_t acid[5]; + uint8_t acid[5] = { 0 }; int cid; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - p += 8; - bytestream_get_buffer(&p, acid, 4); + bytestream2_skip(&p, 8); + bytestream2_get_buffer(&p, acid, 4); acid[4] = 0; cid = strtol(acid, NULL, 16); st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid); st->need_parsing = AVSTREAM_PARSE_FULL; } - p += 4; /* useless size field */ + bytestream2_skip(&p, 4); /* useless size field */ - time_unit = bytestream_get_le64(&p); - spu = bytestream_get_le64(&p); - p += 4; /* default_len */ - p += 8; /* buffersize + bits_per_sample */ + time_unit = bytestream2_get_le64(&p); + spu = bytestream2_get_le64(&p); + bytestream2_skip(&p, 4); /* default_len */ + bytestream2_skip(&p, 8); /* buffersize + bits_per_sample */ if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ - st->codec->width = bytestream_get_le32(&p); - st->codec->height = bytestream_get_le32(&p); + st->codec->width = bytestream2_get_le32(&p); + st->codec->height = bytestream2_get_le32(&p); avpriv_set_pts_info(st, 64, time_unit, spu * 10000000); } else { - st->codec->channels = bytestream_get_le16(&p); - p += 2; /* block_align */ - st->codec->bit_rate = bytestream_get_le32(&p) * 8; + st->codec->channels = bytestream2_get_le16(&p); + bytestream2_skip(&p, 2); /* block_align */ + st->codec->bit_rate = bytestream2_get_le32(&p) * 8; st->codec->sample_rate = spu * 10000000 / time_unit; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); } - } else if (*p == 3) { - if (os->psize > 8) - ff_vorbis_comment(s, &st->metadata, p+7, os->psize-8); + } else if (bytestream2_peek_byte(&p) == 3) { + bytestream2_skip(&p, 7); + if (bytestream2_get_bytes_left(&p) > 1) + ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1); } return 1;