Commit fc9bc08d authored by Ronald S. Bultje's avatar Ronald S. Bultje

Indeo3: fix crashes on corrupt bitstreams.

Splits at borders of cells are invalid, since it leaves one of the
cells with a width/height of zero. Also, propagate errors on buffer
allocation failures, so we don't continue decoding (which crashes).

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable@libav.org
parent bd7a647c
...@@ -724,6 +724,8 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, ...@@ -724,6 +724,8 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
SPLIT_CELL(ref_cell->height, curr_cell.height); SPLIT_CELL(ref_cell->height, curr_cell.height);
ref_cell->ypos += curr_cell.height; ref_cell->ypos += curr_cell.height;
ref_cell->height -= curr_cell.height; ref_cell->height -= curr_cell.height;
if (ref_cell->height <= 0 || curr_cell.height <= 0)
return AVERROR_INVALIDDATA;
} else if (code == V_SPLIT) { } else if (code == V_SPLIT) {
if (curr_cell.width > strip_width) { if (curr_cell.width > strip_width) {
/* split strip */ /* split strip */
...@@ -732,6 +734,8 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, ...@@ -732,6 +734,8 @@ static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
SPLIT_CELL(ref_cell->width, curr_cell.width); SPLIT_CELL(ref_cell->width, curr_cell.width);
ref_cell->xpos += curr_cell.width; ref_cell->xpos += curr_cell.width;
ref_cell->width -= curr_cell.width; ref_cell->width -= curr_cell.width;
if (ref_cell->width <= 0 || curr_cell.width <= 0)
return AVERROR_INVALIDDATA;
} }
while (1) { /* loop until return */ while (1) { /* loop until return */
...@@ -887,13 +891,16 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, ...@@ -887,13 +891,16 @@ static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
if (width != ctx->width || height != ctx->height) { if (width != ctx->width || height != ctx->height) {
int res;
av_dlog(avctx, "Frame dimensions changed!\n"); av_dlog(avctx, "Frame dimensions changed!\n");
ctx->width = width; ctx->width = width;
ctx->height = height; ctx->height = height;
free_frame_buffers(ctx); free_frame_buffers(ctx);
allocate_frame_buffers(ctx, avctx); if ((res = allocate_frame_buffers(ctx, avctx)) < 0)
return res;
avcodec_set_dimensions(avctx, width, height); avcodec_set_dimensions(avctx, width, height);
} }
......
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