Indeo3: fix crashes on corrupt bitstreams.

Message ID 20120228183638.5E5BA5E0BE@aruru.libav.org
State New
Headers show

Commit Message

Janne Grunau Feb. 28, 2012, 6:36 p.m.
Module: libav
Branch: master
Commit: fc9bc08dca9ac32526251e19fcf738d23b8c68d1

Author:    Ronald S. Bultje <rsbultje@gmail.com>
Committer: Ronald S. Bultje <rsbultje@gmail.com>
Date:      Tue Feb 28 10:22:28 2012 -0800

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

---

 libavcodec/indeo3.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

Patch

diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c
index 4fbbfbb..ed3535a 100644
--- a/libavcodec/indeo3.c
+++ b/libavcodec/indeo3.c
@@ -724,6 +724,8 @@  static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
         SPLIT_CELL(ref_cell->height, curr_cell.height);
         ref_cell->ypos   += 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) {
         if (curr_cell.width > strip_width) {
             /* split strip */
@@ -732,6 +734,8 @@  static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
             SPLIT_CELL(ref_cell->width, curr_cell.width);
         ref_cell->xpos  += 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 */
@@ -887,13 +891,16 @@  static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,
         return AVERROR_INVALIDDATA;
 
     if (width != ctx->width || height != ctx->height) {
+        int res;
+
         av_dlog(avctx, "Frame dimensions changed!\n");
 
         ctx->width  = width;
         ctx->height = height;
 
         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);
     }