]> granicus.if.org Git - libvpx/commitdiff
Improve handling of invalid frames.
authorTimothy B. Terriberry <tterribe@xiph.org>
Tue, 19 Oct 2010 22:40:46 +0000 (15:40 -0700)
committerJohn Koleszar <jkoleszar@google.com>
Fri, 22 Oct 2010 15:50:56 +0000 (11:50 -0400)
The code was not checking for frame sizes smaller than 3 bytes, and the
 partition size checks might have failed if the input buffer was within
 16MB of the top of the heap.
In addition, the reference count on the current frame buffer was not
 being decremented on error, so after a small number of errors, no new
 frame buffer could be found and it would run off the list of them.

Change-Id: I0c60dba6adb1e2a29df39754f72a56ab6c776b46

vp8/decoder/decodframe.c
vp8/decoder/onyxd_if.c

index efe0ad8e2d209a917cdbc8ff9401e9db7f1ed3c5..2d81d61d5873f4d7dcd21cf090ca11d3d93b4867 100644 (file)
@@ -462,7 +462,7 @@ static void setup_token_decoder(VP8D_COMP *pbi,
             partition_size = user_data_end - partition;
         }
 
-        if (partition + partition_size > user_data_end)
+        if (user_data_end - partition < partition_size)
             vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                                "Truncated packet or corrupt partition "
                                "%d length", i + 1);
@@ -564,12 +564,15 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     MACROBLOCKD *const xd  = & pbi->mb;
     const unsigned char *data = (const unsigned char *)pbi->Source;
     const unsigned char *const data_end = data + pbi->source_sz;
-    int first_partition_length_in_bytes;
+    unsigned int first_partition_length_in_bytes;
 
     int mb_row;
     int i, j, k, l;
     const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
 
+    if (data_end - data < 3)
+        vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                           "Truncated packet");
     pc->frame_type = (FRAME_TYPE)(data[0] & 1);
     pc->version = (data[0] >> 1) & 7;
     pc->show_frame = (data[0] >> 4) & 1;
@@ -577,7 +580,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
         (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
     data += 3;
 
-    if (data + first_partition_length_in_bytes > data_end)
+    if (data_end - data < first_partition_length_in_bytes)
         vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                            "Truncated packet or corrupt partition 0 length");
     vp8_setup_version(pc);
index 7d716b0a069d7566e4fa5fe01c28088128a13fb9..884c38da0605b07d505d02e897adde2514c1c307 100644 (file)
@@ -327,9 +327,13 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
 
     pbi->common.error.error_code = VPX_CODEC_OK;
 
+    cm->new_fb_idx = get_free_fb (cm);
+
     if (setjmp(pbi->common.error.jmp))
     {
         pbi->common.error.setjmp = 0;
+        if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
+          cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
         return -1;
     }
 
@@ -345,8 +349,6 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
     pbi->Source = source;
     pbi->source_sz = size;
 
-    cm->new_fb_idx = get_free_fb (cm);
-
     retcode = vp8_decode_frame(pbi);
 
     if (retcode < 0)
@@ -356,6 +358,8 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
 #endif
         pbi->common.error.error_code = VPX_CODEC_ERROR;
         pbi->common.error.setjmp = 0;
+        if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
+          cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
         return retcode;
     }