Commit dc796851 authored by Luca Barbato's avatar Luca Barbato

indeo: Bound-check before applying transform

Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable@libav.org
parent cd78e934
...@@ -346,6 +346,13 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band, ...@@ -346,6 +346,13 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band,
band->inv_transform = transforms[transform_id].inv_trans; band->inv_transform = transforms[transform_id].inv_trans;
band->dc_transform = transforms[transform_id].dc_trans; band->dc_transform = transforms[transform_id].dc_trans;
band->is_2d_trans = transforms[transform_id].is_2d_trans; band->is_2d_trans = transforms[transform_id].is_2d_trans;
if (transform_id < 10)
band->transform_size = 8;
else
band->transform_size = 4;
if (band->blk_size != band->transform_size)
return AVERROR_INVALIDDATA;
scan_indx = get_bits(&ctx->gb, 4); scan_indx = get_bits(&ctx->gb, 4);
if (scan_indx == 15) { if (scan_indx == 15) {
......
...@@ -147,39 +147,47 @@ static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx) ...@@ -147,39 +147,47 @@ static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx)
/* select transform function and scan pattern according to plane and band number */ /* select transform function and scan pattern according to plane and band number */
switch ((p << 2) + i) { switch ((p << 2) + i) {
case 0: case 0:
band->inv_transform = ff_ivi_inverse_slant_8x8; band->inv_transform = ff_ivi_inverse_slant_8x8;
band->dc_transform = ff_ivi_dc_slant_2d; band->dc_transform = ff_ivi_dc_slant_2d;
band->scan = ff_zigzag_direct; band->scan = ff_zigzag_direct;
band->transform_size = 8;
break; break;
case 1: case 1:
band->inv_transform = ff_ivi_row_slant8; band->inv_transform = ff_ivi_row_slant8;
band->dc_transform = ff_ivi_dc_row_slant; band->dc_transform = ff_ivi_dc_row_slant;
band->scan = ff_ivi_vertical_scan_8x8; band->scan = ff_ivi_vertical_scan_8x8;
band->transform_size = 8;
break; break;
case 2: case 2:
band->inv_transform = ff_ivi_col_slant8; band->inv_transform = ff_ivi_col_slant8;
band->dc_transform = ff_ivi_dc_col_slant; band->dc_transform = ff_ivi_dc_col_slant;
band->scan = ff_ivi_horizontal_scan_8x8; band->scan = ff_ivi_horizontal_scan_8x8;
band->transform_size = 8;
break; break;
case 3: case 3:
band->inv_transform = ff_ivi_put_pixels_8x8; band->inv_transform = ff_ivi_put_pixels_8x8;
band->dc_transform = ff_ivi_put_dc_pixel_8x8; band->dc_transform = ff_ivi_put_dc_pixel_8x8;
band->scan = ff_ivi_horizontal_scan_8x8; band->scan = ff_ivi_horizontal_scan_8x8;
band->transform_size = 8;
break; break;
case 4: case 4:
band->inv_transform = ff_ivi_inverse_slant_4x4; band->inv_transform = ff_ivi_inverse_slant_4x4;
band->dc_transform = ff_ivi_dc_slant_2d; band->dc_transform = ff_ivi_dc_slant_2d;
band->scan = ff_ivi_direct_scan_4x4; band->scan = ff_ivi_direct_scan_4x4;
band->transform_size = 4;
break; break;
} }
band->is_2d_trans = band->inv_transform == ff_ivi_inverse_slant_8x8 || band->is_2d_trans = band->inv_transform == ff_ivi_inverse_slant_8x8 ||
band->inv_transform == ff_ivi_inverse_slant_4x4; band->inv_transform == ff_ivi_inverse_slant_4x4;
if (band->transform_size != band->blk_size)
return AVERROR_INVALIDDATA;
/* select dequant matrix according to plane and band number */ /* select dequant matrix according to plane and band number */
if (!p) { if (!p) {
quant_mat = (pic_conf.luma_bands > 1) ? i+1 : 0; quant_mat = (pic_conf.luma_bands > 1) ? i+1 : 0;
......
...@@ -407,6 +407,24 @@ static int ivi_dec_tile_data_size(GetBitContext *gb) ...@@ -407,6 +407,24 @@ static int ivi_dec_tile_data_size(GetBitContext *gb)
return len; return len;
} }
static int ivi_dc_transform(IVIBandDesc *band, int *prev_dc, int buf_offs,
int blk_size)
{
int buf_size = band->pitch * band->aheight - buf_offs;
int min_size = (blk_size - 1) * band->pitch + blk_size;
if (!band->dc_transform)
return 0;
if (min_size > buf_size)
return AVERROR_INVALIDDATA;
band->dc_transform(prev_dc, band->buf + buf_offs,
band->pitch, blk_size);
return 0;
}
static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
ivi_mc_func mc, int mv_x, int mv_y, ivi_mc_func mc, int mv_x, int mv_y,
...@@ -424,6 +442,12 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band, ...@@ -424,6 +442,12 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
int num_coeffs = blk_size * blk_size; int num_coeffs = blk_size * blk_size;
int col_mask = blk_size - 1; int col_mask = blk_size - 1;
int scan_pos = -1; int scan_pos = -1;
int min_size = band->pitch * (band->transform_size - 1) +
band->transform_size;
int buf_size = band->pitch * band->aheight - offs;
if (min_size > buf_size)
return AVERROR_INVALIDDATA;
if (!band->scan) { if (!band->scan) {
av_log(avctx, AV_LOG_ERROR, "Scan pattern is not set.\n"); av_log(avctx, AV_LOG_ERROR, "Scan pattern is not set.\n");
...@@ -589,9 +613,9 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, ...@@ -589,9 +613,9 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
/* for intra blocks apply the dc slant transform */ /* for intra blocks apply the dc slant transform */
/* for inter - perform the motion compensation without delta */ /* for inter - perform the motion compensation without delta */
if (is_intra) { if (is_intra) {
if (band->dc_transform) ret = ivi_dc_transform(band, &prev_dc, buf_offs, blk_size);
band->dc_transform(&prev_dc, band->buf + buf_offs, if (ret < 0)
band->pitch, blk_size); return ret;
} else { } else {
ret = ivi_mc(mc_no_delta_func, band->buf, band->ref_buf, ret = ivi_mc(mc_no_delta_func, band->buf, band->ref_buf,
buf_offs, mv_x, mv_y, band->pitch, mc_type); buf_offs, mv_x, mv_y, band->pitch, mc_type);
......
...@@ -159,6 +159,7 @@ typedef struct IVIBandDesc { ...@@ -159,6 +159,7 @@ typedef struct IVIBandDesc {
int num_tiles; ///< number of tiles in this band int num_tiles; ///< number of tiles in this band
IVITile *tiles; ///< array of tile descriptors IVITile *tiles; ///< array of tile descriptors
InvTransformPtr *inv_transform; InvTransformPtr *inv_transform;
int transform_size;
DCTransformPtr *dc_transform; DCTransformPtr *dc_transform;
int is_2d_trans; ///< 1 indicates that the two-dimensional inverse transform is used int is_2d_trans; ///< 1 indicates that the two-dimensional inverse transform is used
int32_t checksum; ///< for debug purposes int32_t checksum; ///< for debug purposes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment