From e4d4044339b9c3b0f45f7203cd026eda3c0414c0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Sep 2012 10:39:49 +0200 Subject: [PATCH 1/8] indeo3: fix out of cell write. Fixes CVE-2012-2776. CC:libav-stable@libav.org Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind --- libavcodec/indeo3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index 0f4adc473c..18d9e10270 100644 --- a/libavcodec/indeo3.c +++ b/libavcodec/indeo3.c @@ -421,6 +421,9 @@ static int decode_cell_data(Cell *cell, uint8_t *block, uint8_t *ref_block, blk_row_offset = (row_offset << (2 + v_zoom)) - (cell->width << 2); line_offset = v_zoom ? row_offset : 0; + if (cell->height & v_zoom || cell->width & h_zoom) + return IV3_BAD_DATA; + for (y = 0; y < cell->height; is_first_row = 0, y += 1 + v_zoom) { for (x = 0; x < cell->width; x += 1 + h_zoom) { ref = ref_block; From 2d09cdbaf2f449ba23d54e97e94bd97ca22208c6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 15 Apr 2012 14:11:50 +0200 Subject: [PATCH 2/8] indeo5: check tile size in decode_mb_info(). This prevents writing into a too small array if some parameters changed without the tile being reallocated. Fixes CVE-2012-2794 CC:libav-stable@libav.org Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Anton Khirnov --- libavcodec/indeo5.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index 4f8e0d8e96..4044a04ba2 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -430,6 +430,12 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, ((band->qdelta_present && band->inherit_qdelta) || band->inherit_mv)) return AVERROR_INVALIDDATA; + if (tile->num_MBs != IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)) { + av_log(avctx, AV_LOG_ERROR, "Allocated tile size %d mismatches parameters %d\n", + tile->num_MBs, IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)); + return AVERROR_INVALIDDATA; + } + /* scale factor for motion vectors */ mv_scale = (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3); mv_x = mv_y = 0; From 5d2170c53bf4c2b0499f230c43764e4acf228f88 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Sep 2012 11:06:54 +0200 Subject: [PATCH 3/8] ivi_common: make ff_ivi_process_empty_tile() static. It's not used outside of ivi_common.c --- libavcodec/ivi_common.c | 15 ++++++++++++--- libavcodec/ivi_common.h | 12 ------------ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi_common.c index 6ff0f8028b..65fc500d74 100644 --- a/libavcodec/ivi_common.c +++ b/libavcodec/ivi_common.c @@ -489,8 +489,17 @@ int ff_ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile) return 0; } -void ff_ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, - IVITile *tile, int32_t mv_scale) +/** + * Handle empty tiles by performing data copying and motion + * compensation respectively. + * + * @param[in] avctx ptr to the AVCodecContext + * @param[in] band pointer to the band descriptor + * @param[in] tile pointer to the tile descriptor + * @param[in] mv_scale scaling factor for motion vectors + */ +static void ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, + IVITile *tile, int32_t mv_scale) { int x, y, need_mc, mbn, blk, num_blocks, mv_x, mv_y, mc_type; int offs, mb_offset, row_offset; @@ -673,7 +682,7 @@ static int decode_band(IVI45DecContext *ctx, int plane_num, } tile->is_empty = get_bits1(&ctx->gb); if (tile->is_empty) { - ff_ivi_process_empty_tile(avctx, band, tile, + ivi_process_empty_tile(avctx, band, tile, (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3)); av_dlog(avctx, "Empty tile encountered!\n"); } else { diff --git a/libavcodec/ivi_common.h b/libavcodec/ivi_common.h index edbe96a1ee..1b654f8ead 100644 --- a/libavcodec/ivi_common.h +++ b/libavcodec/ivi_common.h @@ -375,18 +375,6 @@ int ff_ivi_dec_tile_data_size(GetBitContext *gb); */ int ff_ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile); -/** - * Handle empty tiles by performing data copying and motion - * compensation respectively. - * - * @param[in] avctx ptr to the AVCodecContext - * @param[in] band pointer to the band descriptor - * @param[in] tile pointer to the tile descriptor - * @param[in] mv_scale scaling factor for motion vectors - */ -void ff_ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, - IVITile *tile, int32_t mv_scale); - /** * Convert and output the current plane. * This conversion is done by adding back the bias value of 128 From ae3da0ae5550053583a6f281ea7fd940497ea0d1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Sep 2012 11:07:58 +0200 Subject: [PATCH 4/8] indeo4/5: check empty tile size in decode_mb_info(). This prevents writing into a too small array if some parameters changed without the tile being reallocated. Based on a patch by Michael Niedermayer Fixes CVE-2012-2800 CC:libav-stable@libav.org Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind --- libavcodec/ivi_common.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi_common.c index 65fc500d74..d1a86c4b65 100644 --- a/libavcodec/ivi_common.c +++ b/libavcodec/ivi_common.c @@ -498,8 +498,8 @@ int ff_ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile) * @param[in] tile pointer to the tile descriptor * @param[in] mv_scale scaling factor for motion vectors */ -static void ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, - IVITile *tile, int32_t mv_scale) +static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, + IVITile *tile, int32_t mv_scale) { int x, y, need_mc, mbn, blk, num_blocks, mv_x, mv_y, mc_type; int offs, mb_offset, row_offset; @@ -509,6 +509,13 @@ static void ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, void (*mc_no_delta_func)(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + if (tile->num_MBs != IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)) { + av_log(avctx, AV_LOG_ERROR, "Allocated tile size %d mismatches " + "parameters %d in ivi_process_empty_tile()\n", + tile->num_MBs, IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)); + return AVERROR_INVALIDDATA; + } + offs = tile->ypos * band->pitch + tile->xpos; mb = tile->mbs; ref_mb = tile->ref_mbs; @@ -589,6 +596,8 @@ static void ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, dst += band->pitch; } } + + return 0; } @@ -682,8 +691,10 @@ static int decode_band(IVI45DecContext *ctx, int plane_num, } tile->is_empty = get_bits1(&ctx->gb); if (tile->is_empty) { - ivi_process_empty_tile(avctx, band, tile, + result = ivi_process_empty_tile(avctx, band, tile, (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3)); + if (result < 0) + break; av_dlog(avctx, "Empty tile encountered!\n"); } else { tile->data_size = ff_ivi_dec_tile_data_size(&ctx->gb); From 607f57152c59bcec26caaf2060a86d96f76c4e8b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 14 Apr 2012 14:49:22 +0200 Subject: [PATCH 5/8] wmalosslessdec: make MCLMS arrays big enough for what is written into them. Fixes a part of CVE-2012-2795 CC:libav-stable@libav.org Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Anton Khirnov --- libavcodec/wmalosslessdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index c67a392bfe..cfa877f086 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -129,8 +129,8 @@ typedef struct WmallDecodeCtx { int8_t mclms_scaling; int16_t mclms_coeffs[128]; int16_t mclms_coeffs_cur[4]; - int16_t mclms_prevvalues[64]; - int16_t mclms_updates[64]; + int16_t mclms_prevvalues[WMALL_MAX_CHANNELS * 2 * 32]; + int16_t mclms_updates[WMALL_MAX_CHANNELS * 2 * 32]; int mclms_recent; int movave_scaling; From f48fbf2eb5ba7015c65b31c266edf399dd6a82b1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 14 Apr 2012 14:50:25 +0200 Subject: [PATCH 6/8] wmalosslessdec: fix a get_bits(0) in decode_ac_filter Fixes a part of CVE-2012-2795 CC:libav-stable@libav.org Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Anton Khirnov --- libavcodec/wmalosslessdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index cfa877f086..dc83b0607b 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -406,7 +406,8 @@ static void decode_ac_filter(WmallDecodeCtx *s) s->acfilter_scaling = get_bits(&s->gb, 4); for (i = 0; i < s->acfilter_order; i++) - s->acfilter_coeffs[i] = get_bits(&s->gb, s->acfilter_scaling) + 1; + s->acfilter_coeffs[i] = (s->acfilter_scaling ? + get_bits(&s->gb, s->acfilter_scaling) : 0) + 1; } static void decode_mclms(WmallDecodeCtx *s) From 6a99310fce49f51773ab7d8ffa4f4748bbf58db9 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Sep 2012 19:16:32 +0200 Subject: [PATCH 7/8] wmalosslessdec: Fix reading too many bits in decode_channel_residues() Fixes a part of CVE-2012-2795 CC:libav-stable@libav.org Based on a patch by Michael Niedermayer Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind --- libavcodec/wmalosslessdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index dc83b0607b..b97f39752c 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -520,7 +520,7 @@ static int decode_channel_residues(WmallDecodeCtx *s, int ch, int tile_size) residue = quo; else { rem_bits = av_ceil_log2(ave_mean); - rem = rem_bits ? get_bits(&s->gb, rem_bits) : 0; + rem = rem_bits ? get_bits_long(&s->gb, rem_bits) : 0; residue = (quo << rem_bits) + rem; } From d05f72c75445969cd7bdb1d860635c9880c67fb6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 29 Sep 2012 13:25:28 +0200 Subject: [PATCH 8/8] dfa: improve boundary checks in decode_dds1() Fixes CVE-2012-2798 CC:libav-stable@libav.org --- libavcodec/dfa.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index c6f09c89a7..d464acb187 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -153,8 +153,7 @@ static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (frame_end - frame < 2) - return AVERROR_INVALIDDATA; + if (bitbuf & mask) { v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 2; @@ -168,9 +167,12 @@ static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height frame += 2; } } else if (bitbuf & (mask << 1)) { - frame += bytestream2_get_le16(gb) * 2; + v = bytestream2_get_le16(gb)*2; + if (frame - frame_end < v) + return AVERROR_INVALIDDATA; + frame += v; } else { - if (frame_end - frame < width + 2) + if (frame_end - frame < width + 3) return AVERROR_INVALIDDATA; frame[0] = frame[1] = frame[width] = frame[width + 1] = bytestream2_get_byte(gb);