On Tue, Apr 16, 2013 at 03:19:34PM +0200, Anton Khirnov wrote:
> Also add an additional sanity check to the alt_quant table.
> Fixes invalid reads with corrupted files.
> 
> Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
> CC:[email protected]
> ---
>  libavcodec/indeo3.c |   43 ++++++++++++++++++++++++++-----------------
>  1 file changed, 26 insertions(+), 17 deletions(-)
> 
> diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c
> index 0c0db79..5c52edd 100644
> --- a/libavcodec/indeo3.c
> +++ b/libavcodec/indeo3.c
> @@ -858,17 +858,20 @@ static int decode_plane(Indeo3DecodeContext *ctx, 
> AVCodecContext *avctx,
>  static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext 
> *avctx,
>                                  const uint8_t *buf, int buf_size)
>  {
> -    const uint8_t   *buf_ptr = buf, *bs_hdr;
> +    GetByteContext gb;
> +    const uint8_t   *bs_hdr;
>      uint32_t        frame_num, word2, check_sum, data_size;
>      uint32_t        y_offset, u_offset, v_offset, starts[3], ends[3];
>      uint16_t        height, width;
>      int             i, j;
>  
> +    bytestream2_init(&gb, buf, buf_size);
> +
>      /* parse and check the OS header */
> -    frame_num = bytestream_get_le32(&buf_ptr);
> -    word2     = bytestream_get_le32(&buf_ptr);
> -    check_sum = bytestream_get_le32(&buf_ptr);
> -    data_size = bytestream_get_le32(&buf_ptr);
> +    frame_num = bytestream2_get_le32(&gb);
> +    word2     = bytestream2_get_le32(&gb);
> +    check_sum = bytestream2_get_le32(&gb);
> +    data_size = bytestream2_get_le32(&gb);
>  
>      if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) {
>          av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n");
> @@ -876,28 +879,28 @@ static int decode_frame_headers(Indeo3DecodeContext 
> *ctx, AVCodecContext *avctx,
>      }
>  
>      /* parse the bitstream header */
> -    bs_hdr = buf_ptr;
> +    bs_hdr = gb.buffer;
>  
> -    if (bytestream_get_le16(&buf_ptr) != 32) {
> +    if (bytestream2_get_le16(&gb) != 32) {
>          av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n");
>          return AVERROR_INVALIDDATA;
>      }
>  
>      ctx->frame_num   =  frame_num;
> -    ctx->frame_flags =  bytestream_get_le16(&buf_ptr);
> -    ctx->data_size   = (bytestream_get_le32(&buf_ptr) + 7) >> 3;
> -    ctx->cb_offset   = *buf_ptr++;
> +    ctx->frame_flags =  bytestream2_get_le16(&gb);
> +    ctx->data_size   = (bytestream2_get_le32(&gb) + 7) >> 3;
> +    ctx->cb_offset   = bytestream2_get_byte(&gb);

the last one can be valigned a bit

>  
>      if (ctx->data_size == 16)
>          return 4;
>      if (ctx->data_size > buf_size)
>          ctx->data_size = buf_size;
>  
> -    buf_ptr += 3; // skip reserved byte and checksum
> +    bytestream2_skip(&gb, 3); // skip reserved byte and checksum
>  
>      /* check frame dimensions */
> -    height = bytestream_get_le16(&buf_ptr);
> -    width  = bytestream_get_le16(&buf_ptr);
> +    height = bytestream2_get_le16(&gb);
> +    width  = bytestream2_get_le16(&gb);
>      if (av_image_check_size(width, height, 0, avctx))
>          return AVERROR_INVALIDDATA;
>  
> @@ -923,9 +926,10 @@ static int decode_frame_headers(Indeo3DecodeContext 
> *ctx, AVCodecContext *avctx,
>          avcodec_set_dimensions(avctx, width, height);
>      }
>  
> -    y_offset = bytestream_get_le32(&buf_ptr);
> -    v_offset = bytestream_get_le32(&buf_ptr);
> -    u_offset = bytestream_get_le32(&buf_ptr);
> +    y_offset = bytestream2_get_le32(&gb);
> +    v_offset = bytestream2_get_le32(&gb);
> +    u_offset = bytestream2_get_le32(&gb);
> +    bytestream2_skip(&gb, 4);
>  
>      /* unfortunately there is no common order of planes in the buffer */
>      /* so we use that sorting algo for determining planes data sizes  */
> @@ -952,7 +956,12 @@ static int decode_frame_headers(Indeo3DecodeContext 
> *ctx, AVCodecContext *avctx,
>      ctx->y_data_ptr = bs_hdr + y_offset;
>      ctx->v_data_ptr = bs_hdr + v_offset;
>      ctx->u_data_ptr = bs_hdr + u_offset;
> -    ctx->alt_quant  = buf_ptr + sizeof(uint32_t);
> +
> +    if (FFMIN3(ctx->y_data_ptr, ctx->v_data_ptr, ctx->u_data_ptr) - 16 < 
> gb.buffer) {
> +        av_log(avctx, AV_LOG_ERROR, "Invalid data offsets.\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    ctx->alt_quant  = gb.buffer;
>  
>      if (ctx->data_size == 16) {
>          av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n");
> -- 

I'd rather check [yuv]_offset before initialising [yuv]_data_ptr, otherwise OK
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to