]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blobdiff - libavcodec/indeo3.c
Started attempt to fix seek handling - still not completed
[frescor/ffmpeg.git] / libavcodec / indeo3.c
index 533057d46f8a1c4ff74965891285a5fe0c30a6c4..b5a9a4dba78dd07fc96885d23785ae67de3459ff 100644 (file)
@@ -147,7 +147,7 @@ static av_cold void iv_free_func(Indeo3DecodeContext *s)
     av_free(s->corrector_type);
 }
 
-typedef struct {
+struct ustr {
     long xpos;
     long ypos;
     long width;
@@ -155,7 +155,7 @@ typedef struct {
     long split_flag;
     long split_direction;
     long usl7;
-} ustr_t;
+};
 
 
 #define LV1_CHECK(buf1,rle_v3,lv1,lp2)  \
@@ -213,7 +213,7 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
     uint32_t *cur_lp, *ref_lp;
     const uint32_t *correction_lp[2], *correctionloworder_lp[2], *correctionhighorder_lp[2];
     uint8_t *correction_type_sp[2];
-    ustr_t strip_tbl[20], *strip;
+    struct ustr strip_tbl[20], *strip;
     int i, j, k, lp1, lp2, flag1, cmd, blks_width, blks_height, region_160_width,
         rle_v1, rle_v2, rle_v3;
     unsigned short res;
@@ -252,14 +252,22 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
 
         if(cmd == 0) {
             strip++;
-            memcpy(strip, strip-1, sizeof(ustr_t));
+            if(strip >= strip_tbl + FF_ARRAY_ELEMS(strip_tbl)) {
+                av_log(s->avctx, AV_LOG_WARNING, "out of range strip\n");
+                break;
+            }
+            memcpy(strip, strip-1, sizeof(*strip));
             strip->split_flag = 1;
             strip->split_direction = 0;
             strip->height = (strip->height > 8 ? ((strip->height+8)>>4)<<3 : 4);
             continue;
         } else if(cmd == 1) {
             strip++;
-            memcpy(strip, strip-1, sizeof(ustr_t));
+            if(strip >= strip_tbl + FF_ARRAY_ELEMS(strip_tbl)) {
+                av_log(s->avctx, AV_LOG_WARNING, "out of range strip\n");
+                break;
+            }
+            memcpy(strip, strip-1, sizeof(*strip));
             strip->split_flag = 1;
             strip->split_direction = 1;
             strip->width = (strip->width > 8 ? ((strip->width+8)>>4)<<3 : 4);
@@ -929,9 +937,6 @@ static void iv_Decode_Chunk(Indeo3DecodeContext *s,
             }
         }
 
-        if(strip < strip_tbl)
-            return;
-
         for( ; strip >= strip_tbl; strip--) {
             if(strip->split_flag != 0) {
                 strip->split_flag = 0;
@@ -970,8 +975,8 @@ static av_cold int indeo3_decode_init(AVCodecContext *avctx)
     return ret;
 }
 
-static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
-                                     const uint8_t *buf, int buf_size)
+static int iv_decode_frame(Indeo3DecodeContext *s,
+                           const uint8_t *buf, int buf_size)
 {
     unsigned int image_width, image_height,
                  chroma_width, chroma_height;
@@ -1001,6 +1006,11 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
     hdr_pos = buf_pos;
     if(data_size == 0x80) return 4;
 
+    if(FFMAX3(y_offset, v_offset, u_offset) >= buf_size-16) {
+        av_log(s->avctx, AV_LOG_ERROR, "y/u/v offset outside buffer\n");
+        return -1;
+    }
+
     if(flags & 0x200) {
         s->cur_frame = s->iv_frame + 1;
         s->ref_frame = s->iv_frame;
@@ -1011,6 +1021,10 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
 
     buf_pos = buf + 16 + y_offset;
     mc_vector_count = bytestream_get_le32(&buf_pos);
+    if(2LL*mc_vector_count >= buf_size-16-y_offset) {
+        av_log(s->avctx, AV_LOG_ERROR, "mc_vector_count too large\n");
+        return -1;
+    }
 
     iv_Decode_Chunk(s, s->cur_frame->Ybuf, s->ref_frame->Ybuf, image_width,
                     image_height, buf_pos + mc_vector_count * 2, cb_offset, hdr_pos, buf_pos,
@@ -1021,6 +1035,10 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
 
         buf_pos = buf + 16 + v_offset;
         mc_vector_count = bytestream_get_le32(&buf_pos);
+        if(2LL*mc_vector_count >= buf_size-16-v_offset) {
+            av_log(s->avctx, AV_LOG_ERROR, "mc_vector_count too large\n");
+            return -1;
+        }
 
         iv_Decode_Chunk(s, s->cur_frame->Vbuf, s->ref_frame->Vbuf, chroma_width,
                 chroma_height, buf_pos + mc_vector_count * 2, cb_offset, hdr_pos, buf_pos,
@@ -1028,6 +1046,10 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
 
         buf_pos = buf + 16 + u_offset;
         mc_vector_count = bytestream_get_le32(&buf_pos);
+        if(2LL*mc_vector_count >= buf_size-16-u_offset) {
+            av_log(s->avctx, AV_LOG_ERROR, "mc_vector_count too large\n");
+            return -1;
+        }
 
         iv_Decode_Chunk(s, s->cur_frame->Ubuf, s->ref_frame->Ubuf, chroma_width,
                 chroma_height, buf_pos + mc_vector_count * 2, cb_offset, hdr_pos, buf_pos,
@@ -1040,13 +1062,16 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
 
 static int indeo3_decode_frame(AVCodecContext *avctx,
                                void *data, int *data_size,
-                               const uint8_t *buf, int buf_size)
+                               AVPacket *avpkt)
 {
+    const uint8_t *buf = avpkt->data;
+    int buf_size = avpkt->size;
     Indeo3DecodeContext *s=avctx->priv_data;
     uint8_t *src, *dest;
     int y;
 
-    iv_decode_frame(s, buf, buf_size);
+    if (iv_decode_frame(s, buf, buf_size) < 0)
+        return -1;
 
     if(s->frame.data[0])
         avctx->release_buffer(avctx, &s->frame);