From 14c21c1ff509eac97f6437aeb51202b15af3a700 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 4 Oct 2011 00:14:48 +0200 Subject: [PATCH 01/24] H264: Only wait before triggering ff_thread_setup_complete() until the next slice that contains a start-of-field/frame macroblock This allows concurrent decoding of the last field/frame, rather than only the last slice, of data packets with multiple NAL units packed together. This will fix the slowdown reported in e.g. bug 52. Signed-off-by: Anton Khirnov --- libavcodec/h264.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 3b550cf380..83c26eff29 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -3633,9 +3633,13 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){ switch (hx->nal_unit_type) { case NAL_SPS: case NAL_PPS: + nals_needed = nal_index; + break; case NAL_IDR_SLICE: case NAL_SLICE: - nals_needed = nal_index; + init_get_bits(&hx->s.gb, ptr, bit_length); + if (!get_ue_golomb(&hx->s.gb)) + nals_needed = nal_index; } continue; } From 124a16f678ddcffe8f1825efb29a6e8da1d580ac Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Tue, 27 Sep 2011 22:15:33 +0000 Subject: [PATCH 02/24] xan: Prevent out of bound accesses Signed-off-by: Janne Grunau --- libavcodec/xan.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index ac19c826a5..f21075c3bf 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -218,6 +218,10 @@ static inline void xan_wc3_copy_pixel_run(XanContext *s, int width = s->avctx->width; unsigned char *palette_plane, *prev_palette_plane; + if ( y + motion_y < 0 || y + motion_y >= s->avctx->height || + x + motion_x < 0 || x + motion_x >= s->avctx->width) + return; + palette_plane = s->current_frame.data[0]; prev_palette_plane = s->last_frame.data[0]; stride = s->current_frame.linesize[0]; @@ -226,7 +230,9 @@ static inline void xan_wc3_copy_pixel_run(XanContext *s, curframe_x = x; prevframe_index = (y + motion_y) * stride + x + motion_x; prevframe_x = x + motion_x; - while(pixel_count && (curframe_index < s->frame_size)) { + while(pixel_count && + curframe_index < s->frame_size && + prevframe_index < s->frame_size) { int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x); memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count); @@ -260,6 +266,7 @@ static int xan_wc3_decode_frame(XanContext *s) { int x, y; unsigned char *opcode_buffer = s->buffer1; + unsigned char *opcode_buffer_end = s->buffer1 + s->buffer1_size; int opcode_buffer_size = s->buffer1_size; const unsigned char *imagedata_buffer = s->buffer2; @@ -268,7 +275,7 @@ static int xan_wc3_decode_frame(XanContext *s) { const unsigned char *size_segment; const unsigned char *vector_segment; const unsigned char *imagedata_segment; - int huffman_offset, size_offset, vector_offset, imagedata_offset; + int huffman_offset, size_offset, vector_offset, imagedata_offset, imagedata_size; if (s->size < 8) return AVERROR_INVALIDDATA; @@ -293,14 +300,17 @@ static int xan_wc3_decode_frame(XanContext *s) { huffman_segment, s->size - huffman_offset) < 0) return AVERROR_INVALIDDATA; - if (imagedata_segment[0] == 2) + if (imagedata_segment[0] == 2) { xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size); - else + imagedata_size = s->buffer2_size; + } else { + imagedata_size = s->size - imagedata_offset - 1; imagedata_buffer = &imagedata_segment[1]; + } /* use the decoded data segments to build the frame */ x = y = 0; - while (total_pixels) { + while (total_pixels && opcode_buffer < opcode_buffer_end) { opcode = *opcode_buffer++; size = 0; @@ -349,6 +359,8 @@ static int xan_wc3_decode_frame(XanContext *s) { size_segment += 3; break; } + if (size > total_pixels) + break; if (opcode < 12) { flag ^= 1; @@ -357,8 +369,11 @@ static int xan_wc3_decode_frame(XanContext *s) { xan_wc3_copy_pixel_run(s, x, y, size, 0, 0); } else { /* output a run of pixels from imagedata_buffer */ + if (imagedata_size < size) + break; xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size); imagedata_buffer += size; + imagedata_size -= size; } } else { /* run-based motion compensation from last frame */ From 95010d18b2d808db9a49377e41bc2f7cf4dfa03e Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sun, 2 Oct 2011 00:48:12 +0000 Subject: [PATCH 03/24] shorten: Prevent block size from increasing Signed-off-by: Janne Grunau --- libavcodec/shorten.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index 80b1b4dba5..8f7436e0a9 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -482,9 +482,15 @@ static int shorten_decode_frame(AVCodecContext *avctx, case FN_BITSHIFT: s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); break; - case FN_BLOCKSIZE: - s->blocksize = get_uint(s, av_log2(s->blocksize)); + case FN_BLOCKSIZE: { + int blocksize = get_uint(s, av_log2(s->blocksize)); + if (blocksize > s->blocksize) { + av_log(avctx, AV_LOG_ERROR, "Increasing block size is not supported\n"); + return AVERROR_PATCHWELCOME; + } + s->blocksize = blocksize; break; + } case FN_QUIT: *data_size = 0; return buf_size; From 1e3336de69d1c4c28a5e306fab20555f4078f2d7 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sun, 25 Sep 2011 20:06:19 +0000 Subject: [PATCH 04/24] mpc8: Fix return value on EOF Signed-off-by: Janne Grunau --- libavformat/mpc8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c index d7a7d6a825..2634ee33b9 100644 --- a/libavformat/mpc8.c +++ b/libavformat/mpc8.c @@ -264,7 +264,7 @@ static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EIO); mpc8_handle_chunk(s, tag, pos, size); } - return 0; + return AVERROR_EOF; } static int mpc8_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) From 2c1ba7994190fa2f1ad430594551070a49353bd1 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Mon, 26 Sep 2011 22:18:29 +0000 Subject: [PATCH 05/24] wmapro: Validate the number of audio channels before using it Signed-off-by: Janne Grunau --- libavcodec/wmaprodec.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 8fd2da575a..2811302435 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -309,10 +309,6 @@ static av_cold int decode_init(AVCodecContext *avctx) s->samples_per_frame = 1 << ff_wma_get_frame_len_bits(avctx->sample_rate, 3, s->decode_flags); - /** init previous block len */ - for (i = 0; i < avctx->channels; i++) - s->channel[i].prev_block_len = s->samples_per_frame; - /** subframe info */ log2_max_num_subframes = ((s->decode_flags & 0x38) >> 3); s->max_num_subframes = 1 << log2_max_num_subframes; @@ -332,6 +328,18 @@ static av_cold int decode_init(AVCodecContext *avctx) s->num_channels = avctx->channels; + if (s->num_channels < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", s->num_channels); + return AVERROR_INVALIDDATA; + } else if (s->num_channels > WMAPRO_MAX_CHANNELS) { + av_log_ask_for_sample(avctx, "unsupported number of channels\n"); + return AVERROR_PATCHWELCOME; + } + + /** init previous block len */ + for (i = 0; i < s->num_channels; i++) + s->channel[i].prev_block_len = s->samples_per_frame; + /** extract lfe channel position */ s->lfe_channel = -1; @@ -343,14 +351,6 @@ static av_cold int decode_init(AVCodecContext *avctx) } } - if (s->num_channels < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", s->num_channels); - return AVERROR_INVALIDDATA; - } else if (s->num_channels > WMAPRO_MAX_CHANNELS) { - av_log_ask_for_sample(avctx, "unsupported number of channels\n"); - return AVERROR_PATCHWELCOME; - } - INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE, scale_huffbits, 1, 1, scale_huffcodes, 2, 2, 616); From 2c6cf1394096d08396faadc6e7c0b404fd6df006 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Mon, 26 Sep 2011 22:18:29 +0000 Subject: [PATCH 06/24] wavpack: Reset internal state on corrupted blocks wavpack_decode_block() supposes that it is called back with the exact same buffer unless it has returned with an error. With multi-channels files, wavpack_decode_frame() was breaking this assumption. Signed-off-by: Janne Grunau --- libavcodec/wavpack.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index a687c279ef..5cd17b5de1 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -1174,6 +1174,15 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, return samplecount * bpp; } +static void wavpack_decode_flush(AVCodecContext *avctx) +{ + WavpackContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->fdec_num; i++) + wv_reset_saved_context(s->fdec[i]); +} + static int wavpack_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) @@ -1206,11 +1215,14 @@ static int wavpack_decode_frame(AVCodecContext *avctx, if(frame_size < 0 || frame_size > buf_size){ av_log(avctx, AV_LOG_ERROR, "Block %d has invalid size (size %d vs. %d bytes left)\n", s->block, frame_size, buf_size); + wavpack_decode_flush(avctx); return -1; } if((samplecount = wavpack_decode_block(avctx, s->block, data, - data_size, buf, frame_size)) < 0) + data_size, buf, frame_size)) < 0) { + wavpack_decode_flush(avctx); return -1; + } s->block++; buf += frame_size; buf_size -= frame_size; } @@ -1219,15 +1231,6 @@ static int wavpack_decode_frame(AVCodecContext *avctx, return s->samples_left > 0 ? 0 : avpkt->size; } -static void wavpack_decode_flush(AVCodecContext *avctx) -{ - WavpackContext *s = avctx->priv_data; - int i; - - for (i = 0; i < s->fdec_num; i++) - wv_reset_saved_context(s->fdec[i]); -} - AVCodec ff_wavpack_decoder = { .name = "wavpack", .type = AVMEDIA_TYPE_AUDIO, From c7e631986b4a326a71a20a1a51000f3fbf6e64e7 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Tue, 27 Sep 2011 22:15:31 +0000 Subject: [PATCH 07/24] bink: Prevent NULL dereferences with missing reference frame Signed-off-by: Janne Grunau --- libavcodec/bink.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 17683730d4..e4fdf4c93e 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -950,8 +950,9 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, for (i = 0; i < BINK_NB_SRC; i++) read_bundle(gb, c, i); - ref_start = c->last.data[plane_idx]; - ref_end = c->last.data[plane_idx] + ref_start = c->last.data[plane_idx] ? c->last.data[plane_idx] + : c->pic.data[plane_idx]; + ref_end = ref_start + (bw - 1 + c->last.linesize[plane_idx] * (bh - 1)) * 8; for (i = 0; i < 64; i++) @@ -980,7 +981,8 @@ static int bink_decode_plane(BinkContext *c, GetBitContext *gb, int plane_idx, if (by == bh) break; dst = c->pic.data[plane_idx] + 8*by*stride; - prev = c->last.data[plane_idx] + 8*by*stride; + prev = (c->last.data[plane_idx] ? c->last.data[plane_idx] + : c->pic.data[plane_idx]) + 8*by*stride; for (bx = 0; bx < bw; bx++, dst += 8, prev += 8) { blk = get_value(c, BINK_SRC_BLOCK_TYPES); // 16x16 block type on odd line means part of the already decoded block, so skip it From 06be075cda0a6ba8bab8f543571b380884f562ac Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Tue, 27 Sep 2011 22:15:32 +0000 Subject: [PATCH 08/24] xan: Prevent NULL dereferences with missing reference frame Signed-off-by: Janne Grunau --- libavcodec/xan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index f21075c3bf..9e58a77f19 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -224,6 +224,8 @@ static inline void xan_wc3_copy_pixel_run(XanContext *s, palette_plane = s->current_frame.data[0]; prev_palette_plane = s->last_frame.data[0]; + if (!prev_palette_plane) + prev_palette_plane = palette_plane; stride = s->current_frame.linesize[0]; line_inc = stride - width; curframe_index = y * stride + x; From 1c1449b548a2a0bf0295a522051b04107286653c Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Tue, 27 Sep 2011 22:15:31 +0000 Subject: [PATCH 09/24] wmavoice: Check for out of bound writes Signed-off-by: Janne Grunau --- libavcodec/wmavoice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index c6e6e76c20..484720ee39 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -1880,6 +1880,8 @@ static void copy_bits(PutBitContext *pb, rmn_bits = rmn_bytes = get_bits_left(gb); if (rmn_bits < nbits) return; + if (nbits > pb->size_in_bits - put_bits_count(pb)) + return; rmn_bits &= 7; rmn_bytes >>= 3; if ((rmn_bits = FFMIN(rmn_bits, nbits)) > 0) put_bits(pb, rmn_bits, get_bits(gb, rmn_bits)); From d99427cb8ba099375d8cce6df808d4acf045ab43 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Tue, 27 Sep 2011 22:15:31 +0000 Subject: [PATCH 10/24] wmavoice: Check for corrupted extra data Signed-off-by: Janne Grunau --- libavcodec/wmavoice.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index 484720ee39..cff3f5fc7e 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -401,6 +401,10 @@ static av_cold int wmavoice_decode_init(AVCodecContext *ctx) s->min_pitch_val = ((ctx->sample_rate << 8) / 400 + 50) >> 8; s->max_pitch_val = ((ctx->sample_rate << 8) * 37 / 2000 + 50) >> 8; pitch_range = s->max_pitch_val - s->min_pitch_val; + if (pitch_range <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid pitch range; broken extradata?\n"); + return -1; + } s->pitch_nbits = av_ceil_log2(pitch_range); s->last_pitch_val = 40; s->last_acb_type = ACB_TYPE_NONE; @@ -422,6 +426,10 @@ static av_cold int wmavoice_decode_init(AVCodecContext *ctx) s->block_conv_table[2] = (pitch_range * 44) >> 6; s->block_conv_table[3] = s->max_pitch_val - 1; s->block_delta_pitch_hrange = (pitch_range >> 3) & ~0xF; + if (s->block_delta_pitch_hrange <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid delta pitch hrange; broken extradata?\n"); + return -1; + } s->block_delta_pitch_nbits = 1 + av_ceil_log2(s->block_delta_pitch_hrange); s->block_pitch_range = s->block_conv_table[2] + s->block_conv_table[3] + 1 + From d337dd3a907110b32c6305bb65e4beca5b830c5d Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 23:13:35 +0000 Subject: [PATCH 11/24] motionpixels: Clear FF_INPUT_BUFFER_PADDING_SIZE bytes at the end of the temporary buffer Signed-off-by: Janne Grunau --- libavcodec/motionpixels.c | 1 + tests/ref/fate/motionpixels | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index 9589b4c386..70b499eabe 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -252,6 +252,7 @@ static int mp_decode_frame(AVCodecContext *avctx, mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4); if (buf_size & 3) memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3); + memset(mp->bswapbuf + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); init_get_bits(&gb, mp->bswapbuf, buf_size * 8); memset(mp->changes_map, 0, avctx->width * avctx->height); diff --git a/tests/ref/fate/motionpixels b/tests/ref/fate/motionpixels index e588ed3e18..30651e92c6 100644 --- a/tests/ref/fate/motionpixels +++ b/tests/ref/fate/motionpixels @@ -109,4 +109,4 @@ 0, 648003, 230400, 0xb343f372 0, 654003, 230400, 0xf7f1e588 0, 660003, 230400, 0x9682bdb2 -0, 666003, 230400, 0x538a3db8 +0, 666003, 230400, 0x16f9aad8 From 210c80331e0604edf9c800865c26ba06ed3c2082 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 23:13:35 +0000 Subject: [PATCH 12/24] motionpixels: Fix the size of workspace buffers Some buffers must be mod 4 in width and/or height. Signed-off-by: Janne Grunau --- libavcodec/motionpixels.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index 70b499eabe..1564ea1151 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -52,14 +52,16 @@ typedef struct MotionPixelsContext { static av_cold int mp_decode_init(AVCodecContext *avctx) { MotionPixelsContext *mp = avctx->priv_data; + int w4 = (avctx->width + 3) & ~3; + int h4 = (avctx->height + 3) & ~3; motionpixels_tableinit(); mp->avctx = avctx; dsputil_init(&mp->dsp, avctx); - mp->changes_map = av_mallocz(avctx->width * avctx->height); + mp->changes_map = av_mallocz(avctx->width * h4); mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1; mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel)); - mp->hpt = av_mallocz(avctx->height * avctx->width / 16 * sizeof(YuvPixel)); + mp->hpt = av_mallocz(h4 * w4 / 16 * sizeof(YuvPixel)); avctx->pix_fmt = PIX_FMT_RGB555; return 0; } From e3ca9b93d9f464861638dda3280fcf65e402466a Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 23:13:35 +0000 Subject: [PATCH 13/24] dsicinav: Check for out of bounds reads Signed-off-by: Janne Grunau --- libavcodec/dsicinav.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/dsicinav.c b/libavcodec/dsicinav.c index 0e0d73b68d..5fe99ba26c 100644 --- a/libavcodec/dsicinav.c +++ b/libavcodec/dsicinav.c @@ -216,6 +216,8 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, bitmap_frame_size = buf_size - 4; /* handle palette */ + if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0))) + return AVERROR_INVALIDDATA; if (palette_type == 0) { for (i = 0; i < palette_colors_count; ++i) { cin->palette[i] = bytestream_get_le24(&buf); From 4fd56f842cbaecf74df94c38f9c10452342f436a Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 23:13:35 +0000 Subject: [PATCH 14/24] quickdraw: Check for out of bound reads Signed-off-by: Janne Grunau --- libavcodec/qdrw.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index 2dc059e555..7410f6e152 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -37,6 +37,7 @@ static int decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = avpkt->data + avpkt->size; int buf_size = avpkt->size; QdrawContext * const a = avctx->priv_data; AVFrame * const p= (AVFrame*)&a->pic; @@ -59,6 +60,8 @@ static int decode_frame(AVCodecContext *avctx, outdata = a->pic.data[0]; + if (buf_end - buf < 0x68 + 4) + return AVERROR_INVALIDDATA; buf += 0x68; /* jump to palette */ colors = AV_RB32(buf); buf += 4; @@ -67,6 +70,8 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors); return -1; } + if (buf_end - buf < (colors + 1) * 8) + return AVERROR_INVALIDDATA; pal = (uint32_t*)p->data[1]; for (i = 0; i <= colors; i++) { @@ -89,6 +94,8 @@ static int decode_frame(AVCodecContext *avctx, } p->palette_has_changed = 1; + if (buf_end - buf < 18) + return AVERROR_INVALIDDATA; buf += 18; /* skip unneeded data */ for (i = 0; i < avctx->height; i++) { int size, left, code, pix; @@ -100,6 +107,9 @@ static int decode_frame(AVCodecContext *avctx, out = outdata; size = AV_RB16(buf); /* size of packed line */ buf += 2; + if (buf_end - buf < size) + return AVERROR_INVALIDDATA; + left = size; next = buf + size; while (left > 0) { @@ -115,6 +125,8 @@ static int decode_frame(AVCodecContext *avctx, } else { /* copy */ if ((out + code) > (outdata + a->pic.linesize[0])) break; + if (buf_end - buf < code + 1) + return AVERROR_INVALIDDATA; memcpy(out, buf, code + 1); out += code + 1; buf += code + 1; From 64263dd526ec25ede1591fc1144715a20cc7bc4e Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 23:13:35 +0000 Subject: [PATCH 15/24] tiertexseqv: Check for out of bound reads Signed-off-by: Janne Grunau --- libavcodec/tiertexseqv.c | 65 +++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/libavcodec/tiertexseqv.c b/libavcodec/tiertexseqv.c index cdb342a30c..d48fa15a72 100644 --- a/libavcodec/tiertexseqv.c +++ b/libavcodec/tiertexseqv.c @@ -35,15 +35,19 @@ typedef struct SeqVideoContext { } SeqVideoContext; -static const unsigned char *seq_unpack_rle_block(const unsigned char *src, unsigned char *dst, int dst_size) +static const unsigned char *seq_unpack_rle_block(const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst, int dst_size) { int i, len, sz; GetBitContext gb; int code_table[64]; - /* get the rle codes (at most 64 bytes) */ - init_get_bits(&gb, src, 64 * 8); + /* get the rle codes */ + init_get_bits(&gb, src, (src_end - src) * 8); for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { + if (get_bits_left(&gb) < 4) + return NULL; code_table[i] = get_sbits(&gb, 4); sz += FFABS(code_table[i]); } @@ -54,8 +58,12 @@ static const unsigned char *seq_unpack_rle_block(const unsigned char *src, unsig len = code_table[i]; if (len < 0) { len = -len; + if (src_end - src < 1) + return NULL; memset(dst, *src++, FFMIN(len, dst_size)); } else { + if (src_end - src < len) + return NULL; memcpy(dst, src, FFMIN(len, dst_size)); src += len; } @@ -65,25 +73,30 @@ static const unsigned char *seq_unpack_rle_block(const unsigned char *src, unsig return src; } -static const unsigned char *seq_decode_op1(SeqVideoContext *seq, const unsigned char *src, unsigned char *dst) +static const unsigned char *seq_decode_op1(SeqVideoContext *seq, + const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst) { const unsigned char *color_table; int b, i, len, bits; GetBitContext gb; unsigned char block[8 * 8]; + if (src_end - src < 1) + return NULL; len = *src++; if (len & 0x80) { switch (len & 3) { case 1: - src = seq_unpack_rle_block(src, block, sizeof(block)); + src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); for (b = 0; b < 8; b++) { memcpy(dst, &block[b * 8], 8); dst += seq->frame.linesize[0]; } break; case 2: - src = seq_unpack_rle_block(src, block, sizeof(block)); + src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); for (i = 0; i < 8; i++) { for (b = 0; b < 8; b++) dst[b * seq->frame.linesize[0]] = block[i * 8 + b]; @@ -92,9 +105,13 @@ static const unsigned char *seq_decode_op1(SeqVideoContext *seq, const unsigned break; } } else { + if (len <= 0) + return NULL; + bits = ff_log2_tab[len - 1] + 1; + if (src_end - src < len + 8 * bits) + return NULL; color_table = src; src += len; - bits = ff_log2_tab[len - 1] + 1; init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; for (b = 0; b < 8; b++) { for (i = 0; i < 8; i++) @@ -106,10 +123,16 @@ static const unsigned char *seq_decode_op1(SeqVideoContext *seq, const unsigned return src; } -static const unsigned char *seq_decode_op2(SeqVideoContext *seq, const unsigned char *src, unsigned char *dst) +static const unsigned char *seq_decode_op2(SeqVideoContext *seq, + const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst) { int i; + if (src_end - src < 8 * 8) + return NULL; + for (i = 0; i < 8; i++) { memcpy(dst, src, 8); src += 8; @@ -119,11 +142,16 @@ static const unsigned char *seq_decode_op2(SeqVideoContext *seq, const unsigned return src; } -static const unsigned char *seq_decode_op3(SeqVideoContext *seq, const unsigned char *src, unsigned char *dst) +static const unsigned char *seq_decode_op3(SeqVideoContext *seq, + const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst) { int pos, offset; do { + if (src_end - src < 2) + return NULL; pos = *src++; offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7); dst[offset] = *src++; @@ -132,8 +160,9 @@ static const unsigned char *seq_decode_op3(SeqVideoContext *seq, const unsigned return src; } -static void seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) +static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) { + const unsigned char *data_end = data + data_size; GetBitContext gb; int flags, i, j, x, y, op; unsigned char c[3]; @@ -144,6 +173,8 @@ static void seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int if (flags & 1) { palette = (uint32_t *)seq->frame.data[1]; + if (data_end - data < 256 * 3) + return AVERROR_INVALIDDATA; for (i = 0; i < 256; i++) { for (j = 0; j < 3; j++, data++) c[j] = (*data << 2) | (*data >> 4); @@ -153,6 +184,8 @@ static void seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int } if (flags & 2) { + if (data_end - data < 128) + return AVERROR_INVALIDDATA; init_get_bits(&gb, data, 128 * 8); data += 128; for (y = 0; y < 128; y += 8) for (x = 0; x < 256; x += 8) { @@ -160,17 +193,20 @@ static void seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int op = get_bits(&gb, 2); switch (op) { case 1: - data = seq_decode_op1(seq, data, dst); + data = seq_decode_op1(seq, data, data_end, dst); break; case 2: - data = seq_decode_op2(seq, data, dst); + data = seq_decode_op2(seq, data, data_end, dst); break; case 3: - data = seq_decode_op3(seq, data, dst); + data = seq_decode_op3(seq, data, data_end, dst); break; } + if (!data) + return AVERROR_INVALIDDATA; } } + return 0; } static av_cold int seqvideo_decode_init(AVCodecContext *avctx) @@ -201,7 +237,8 @@ static int seqvideo_decode_frame(AVCodecContext *avctx, return -1; } - seqvideo_decode(seq, buf, buf_size); + if (seqvideo_decode(seq, buf, buf_size)) + return AVERROR_INVALIDDATA; *data_size = sizeof(AVFrame); *(AVFrame *)data = seq->frame; From 172060328771d149b076f00352b004b5b5272d38 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 23:13:35 +0000 Subject: [PATCH 16/24] dsicinav: Check for out of bounds writes Signed-off-by: Janne Grunau --- libavcodec/dsicinav.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/dsicinav.c b/libavcodec/dsicinav.c index 5fe99ba26c..3b545e7b8f 100644 --- a/libavcodec/dsicinav.c +++ b/libavcodec/dsicinav.c @@ -219,6 +219,8 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0))) return AVERROR_INVALIDDATA; if (palette_type == 0) { + if (palette_colors_count > 256) + return AVERROR_INVALIDDATA; for (i = 0; i < palette_colors_count; ++i) { cin->palette[i] = bytestream_get_le24(&buf); bitmap_frame_size -= 3; From 5f05cf4ea9aaafed8edcabe785c2719786103ec1 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Fri, 30 Sep 2011 01:26:22 +0000 Subject: [PATCH 17/24] shorten: Fix out of bound writes in fix_bitshift() The data pointers s->decoded[*] already take into account s->nwrap. Signed-off-by: Janne Grunau --- libavcodec/shorten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index 8f7436e0a9..22c5c0a152 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -155,7 +155,7 @@ static void fix_bitshift(ShortenContext *s, int32_t *buffer) if (s->bitshift != 0) for (i = 0; i < s->blocksize; i++) - buffer[s->nwrap + i] <<= s->bitshift; + buffer[i] <<= s->bitshift; } From 1cd0a5516396bd6fb54e4df1e7c88ed18416299b Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 03:12:07 +0000 Subject: [PATCH 18/24] motionpixels: Prevent calling init_vlc() with invalid parameters Signed-off-by: Janne Grunau --- libavcodec/motionpixels.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index 1564ea1151..d054e00342 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -281,6 +281,8 @@ static int mp_decode_frame(AVCodecContext *avctx, if (sz == 0) goto end; + if (mp->max_codes_bits <= 0) + goto end; if (init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0)) goto end; mp_decode_frame_helper(mp, &gb); From 3e0757c2a87c8cf3e452f67bca279001c64cedff Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 03:12:07 +0000 Subject: [PATCH 19/24] xan: Fixed out of bound accesses in xan_unpack() Signed-off-by: Janne Grunau --- libavcodec/xan.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index 9e58a77f19..c71a718537 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -130,13 +130,16 @@ static int xan_huffman_decode(unsigned char *dest, int dest_len, * * @param dest destination buffer of dest_len, must be padded with at least 130 bytes */ -static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len) +static void xan_unpack(unsigned char *dest, int dest_len, + const unsigned char *src, int src_len) { unsigned char opcode; int size; + unsigned char *dest_org = dest; unsigned char *dest_end = dest + dest_len; + const unsigned char *src_end = src + src_len; - while (dest < dest_end) { + while (dest < dest_end && src < src_end) { opcode = *src++; if (opcode < 0xe0) { @@ -161,9 +164,11 @@ static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_l back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1; size2 = ((opcode & 0x0c) << 6) + *src++ + 5; - if (size + size2 > dest_end - dest) - return; } + if (dest_end - dest < size + size2 || + dest + size - dest_org < back || + src_end - src < size) + return; memcpy(dest, src, size); dest += size; src += size; av_memcpy_backptr(dest, back, size2); dest += size2; @@ -171,6 +176,8 @@ static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_l int finish = opcode >= 0xfc; size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4; + if (dest_end - dest < size || src_end - src < size) + return; memcpy(dest, src, size); dest += size; src += size; if (finish) return; @@ -303,7 +310,8 @@ static int xan_wc3_decode_frame(XanContext *s) { return AVERROR_INVALIDDATA; if (imagedata_segment[0] == 2) { - xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size); + xan_unpack(s->buffer2, s->buffer2_size, + &imagedata_segment[1], s->size - imagedata_offset - 1); imagedata_size = s->buffer2_size; } else { imagedata_size = s->size - imagedata_offset - 1; From 3db3fdf4c669aed9379be430c17f151d4d0697c5 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 20:38:01 +0000 Subject: [PATCH 20/24] xan: Check for out of bound reads in xan_huffman_decode() Signed-off-by: Janne Grunau --- libavcodec/xan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index c71a718537..3965617838 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -112,7 +112,10 @@ static int xan_huffman_decode(unsigned char *dest, int dest_len, init_get_bits(&gb, ptr, ptr_len * 8); while ( val != 0x16 ) { - val = src[val - 0x17 + get_bits1(&gb) * byte]; + unsigned idx = val - 0x17 + get_bits1(&gb) * byte; + if (idx >= 2 * byte) + return -1; + val = src[idx]; if ( val < 0x16 ) { if (dest >= dest_end) From 7d17a794f0348ba40d5cda7d969564cb83981001 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Thu, 29 Sep 2011 03:12:07 +0000 Subject: [PATCH 21/24] xan: Prevent NULL dereference with missing palette Signed-off-by: Janne Grunau --- libavcodec/xan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/xan.c b/libavcodec/xan.c index 3965617838..54d6d15da4 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -553,6 +553,11 @@ static int xan_decode_frame(AVCodecContext *avctx, } buf_size = buf_end - buf; } + if (s->palettes_count <= 0) { + av_log(s->avctx, AV_LOG_ERROR, "No palette found\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = avctx->get_buffer(avctx, &s->current_frame))) { av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; From 9bd854b1ff342f82efa6d2ad4e8fefddce5fa731 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sun, 25 Sep 2011 20:06:20 +0000 Subject: [PATCH 22/24] mpc8: Check out of bound bands limit Signed-off-by: Janne Grunau --- libavcodec/mpc8.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index a126fc8a8f..b38664215b 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -266,6 +266,8 @@ static int mpc8_decode_frame(AVCodecContext * avctx, maxband = c->last_max_band + get_vlc2(gb, band_vlc.table, MPC8_BANDS_BITS, 2); if(maxband > 32) maxband -= 33; } + if(maxband > c->maxbands) + return AVERROR_INVALIDDATA; c->last_max_band = maxband; /* read subband indexes */ From c2f2dfb3dd20e036b8b08c0fd1486a3044e8f02a Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 7 Oct 2011 18:08:55 +0200 Subject: [PATCH 23/24] motionpixels: decode only the 111 complete frames for fate Signed-off-by: Janne Grunau --- tests/fate.mak | 2 +- tests/ref/fate/motionpixels | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/fate.mak b/tests/fate.mak index 754896e501..36d6e28405 100644 --- a/tests/fate.mak +++ b/tests/fate.mak @@ -175,7 +175,7 @@ fate-maxis-xa: CMD = md5 -i $(SAMPLES)/maxis-xa/SC2KBUG.XA -f s16le FATE_TESTS += fate-mimic fate-mimic: CMD = framecrc -idct simple -i $(SAMPLES)/mimic/mimic2-womanloveffmpeg.cam -vsync 0 FATE_TESTS += fate-motionpixels -fate-motionpixels: CMD = framecrc -i $(SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 +fate-motionpixels: CMD = framecrc -i $(SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -vframes 111 FATE_TESTS += fate-mpc7-demux fate-mpc7-demux: CMD = crc -i $(SAMPLES)/musepack/inside-mp7.mpc -acodec copy FATE_TESTS += fate-mpc8-demux diff --git a/tests/ref/fate/motionpixels b/tests/ref/fate/motionpixels index 30651e92c6..fa86f7379f 100644 --- a/tests/ref/fate/motionpixels +++ b/tests/ref/fate/motionpixels @@ -109,4 +109,3 @@ 0, 648003, 230400, 0xb343f372 0, 654003, 230400, 0xf7f1e588 0, 660003, 230400, 0x9682bdb2 -0, 666003, 230400, 0x16f9aad8 From 98ef887a759c66febcb612407c6bb361c4d50bcb Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Fri, 7 Oct 2011 17:02:36 -0700 Subject: [PATCH 24/24] mpegps: Use av_get_packet() instead of poorly emulating it. --- libavformat/mpeg.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index ef683b1a05..52bf40faa5 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -566,14 +566,7 @@ static int mpegps_read_packet(AVFormatContext *s, else if (st->codec->bits_per_coded_sample == 28) return AVERROR(EINVAL); } - av_new_packet(pkt, len); - ret = avio_read(s->pb, pkt->data, pkt->size); - if (ret < 0) { - pkt->size = 0; - } else if (ret < pkt->size) { - pkt->size = ret; - memset(pkt->data + ret, 0, FF_INPUT_BUFFER_PADDING_SIZE); - } + ret = av_get_packet(s->pb, pkt, len); pkt->pts = pts; pkt->dts = dts; pkt->pos = dummy_pos;