]> granicus.if.org Git - libvpx/commitdiff
Fix: check cx_data buffer prior to write
authorJames Berry <jamesberry@google.com>
Wed, 12 Oct 2011 15:18:50 +0000 (11:18 -0400)
committerJames Berry <jamesberry@google.com>
Thu, 20 Oct 2011 19:55:00 +0000 (15:55 -0400)
check to make sure that cx_data buffer has enough room before
writting to it, prior behavior did not which could result in a crash.

Change-Id: I3fab6f2bc4a96d7c675ea81acd39ece121738b28

vp8/common/onyx.h
vp8/encoder/bitstream.c
vp8/encoder/bitstream.h
vp8/encoder/boolhuff.c
vp8/encoder/boolhuff.h
vp8/encoder/onyx_if.c
vp8/encoder/onyx_int.h
vp8/vp8_cx_iface.c

index e911ea0f4e181d57afdf2684bd6f5213ff734ea6..28cbaed98611b78bf3ab5f367d29d798372490db 100644 (file)
@@ -221,7 +221,7 @@ extern "C"
 // receive a frames worth of data caller can assume that a copy of this frame is made
 // and not just a copy of the pointer..
     int vp8_receive_raw_frame(VP8_PTR comp, unsigned int frame_flags, YV12_BUFFER_CONFIG *sd, int64_t time_stamp, int64_t end_time_stamp);
-    int vp8_get_compressed_data(VP8_PTR comp, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, int64_t *time_stamp, int64_t *time_end, int flush);
+    int vp8_get_compressed_data(VP8_PTR comp, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, unsigned char *dest_end, int64_t *time_stamp, int64_t *time_end, int flush);
     int vp8_get_preview_raw_frame(VP8_PTR comp, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *flags);
 
     int vp8_use_as_reference(VP8_PTR comp, int ref_frame_flags);
index cea8e1232a095fcd36c9b385290fdff786f0ef67..1dda22f1c0583a6ac1ec74a8ad1b495b1d1e7b02 100644 (file)
@@ -358,11 +358,12 @@ static void write_partition_size(unsigned char *cx_data, int size)
 
 }
 
-static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data, int num_part, int *size)
+static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data, unsigned char * cx_data_end, int num_part, int *size)
 {
 
     int i;
     unsigned char *ptr = cx_data;
+    unsigned char *ptr_end = cx_data_end;
     unsigned int shift;
     vp8_writer *w = &cpi->bc2;
     *size = 3 * (num_part - 1);
@@ -371,7 +372,7 @@ static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data,
 
     for (i = 0; i < num_part; i++)
     {
-        vp8_start_encode(w, ptr);
+        vp8_start_encode(w, ptr, ptr_end);
         {
             unsigned int split;
             int count = w->count;
@@ -437,7 +438,13 @@ static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data,
                                 w->buffer[x] += 1;
                             }
 
+                            validate_buffer(w->buffer + w->pos,
+                                            1,
+                                            cx_data_end,
+                                            &cpi->common.error);
+
                             w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+
                             lowvalue <<= offset;
                             shift = count;
                             lowvalue &= 0xffffff;
@@ -497,7 +504,14 @@ static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data,
                                         w->buffer[x] += 1;
                                     }
 
-                                    w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                                    validate_buffer(w->buffer + w->pos,
+                                                    1,
+                                                    cx_data_end,
+                                                    &cpi->common.error);
+
+                                    w->buffer[w->pos++] =
+                                        (lowvalue >> (24 - offset));
+
                                     lowvalue <<= offset;
                                     shift = count;
                                     lowvalue &= 0xffffff;
@@ -543,7 +557,13 @@ static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data,
                             if (!++count)
                             {
                                 count = -8;
+                                validate_buffer(w->buffer + w->pos,
+                                                1,
+                                                cx_data_end,
+                                                &cpi->common.error);
+
                                 w->buffer[w->pos++] = (lowvalue >> 24);
+
                                 lowvalue &= 0xffffff;
                             }
                         }
@@ -1526,7 +1546,7 @@ static void put_delta_q(vp8_writer *bc, int delta_q)
         vp8_write_bit(bc, 0);
 }
 
-void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
+void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned char * dest_end, unsigned long *size)
 {
     int i, j;
     VP8_HEADER oh;
@@ -1536,6 +1556,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     int extra_bytes_packed = 0;
 
     unsigned char *cx_data = dest;
+    unsigned char *cx_data_end = dest_end;
     const int *mb_feature_data_bits;
 
     oh.show_frame = (int) pc->show_frame;
@@ -1544,6 +1565,8 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     oh.first_partition_length_in_bytes = 0;
 
     mb_feature_data_bits = vp8_mb_feature_data_bits;
+
+    validate_buffer(cx_data, 3, cx_data_end, &cpi->common.error);
     cx_data += 3;
 
 #if defined(SECTIONBITS_OUTPUT)
@@ -1560,6 +1583,8 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     {
         int v;
 
+        validate_buffer(cx_data, 7, cx_data_end, &cpi->common.error);
+
         // Start / synch code
         cx_data[0] = 0x9D;
         cx_data[1] = 0x01;
@@ -1573,10 +1598,11 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
         cx_data[5] = v;
         cx_data[6] = v >> 8;
 
+
         extra_bytes_packed = 7;
         cx_data += extra_bytes_packed ;
 
-        vp8_start_encode(bc, cx_data);
+        vp8_start_encode(bc, cx_data, cx_data_end);
 
         // signal clr type
         vp8_write_bit(bc, pc->clr_type);
@@ -1584,7 +1610,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
 
     }
     else
-        vp8_start_encode(bc, cx_data);
+        vp8_start_encode(bc, cx_data, cx_data_end);
 
 
     // Signal whether or not Segmentation is enabled
@@ -1841,13 +1867,13 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
         int asize;
         num_part = 1 << pc->multi_token_partition;
 
-        pack_tokens_into_partitions(cpi, cx_data + bc->pos, num_part, &asize);
+        pack_tokens_into_partitions(cpi, cx_data + bc->pos, cx_data_end, num_part, &asize);
 
         *size += asize;
     }
     else
     {
-        vp8_start_encode(&cpi->bc2, cx_data + bc->pos);
+        vp8_start_encode(&cpi->bc2, cx_data + bc->pos, cx_data_end);
 
 #if CONFIG_MULTITHREAD
         if (cpi->b_multi_threaded)
index f5d148ea477482d2833324ea191a0c14526b58bc..8a875a5bdfc94414de23ca0f75404a92c63647d0 100644 (file)
@@ -27,13 +27,13 @@ void vp8cx_pack_mb_row_tokens_armv5(VP8_COMP *cpi, vp8_writer *w,
                                     const vp8_tree_index *);
 # define pack_tokens(a,b,c)                  \
     vp8cx_pack_tokens_armv5(a,b,c,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
-# define pack_tokens_into_partitions(a,b,c,d)  \
+# define pack_tokens_into_partitions(a,b,unused,c,d)  \
     vp8cx_pack_tokens_into_partitions_armv5(a,b,c,d,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
 # define pack_mb_row_tokens(a,b)               \
     vp8cx_pack_mb_row_tokens_armv5(a,b,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
 #else
 # define pack_tokens(a,b,c)                  pack_tokens_c(a,b,c)
-# define pack_tokens_into_partitions(a,b,c,d)  pack_tokens_into_partitions_c(a,b,c,d)
+# define pack_tokens_into_partitions(a,b,c,d,e)  pack_tokens_into_partitions_c(a,b,c,d,e)
 # define pack_mb_row_tokens(a,b)               pack_mb_row_tokens_c(a,b)
 #endif
 #endif
index 08ae66b8da04bcd59915d1c04ee2650c0df3243a..d8ff5f93380b22eb5a9560ea723099251ae144ab 100644 (file)
@@ -40,15 +40,16 @@ const unsigned int vp8_prob_cost[256] =
     22,   21,   19,   18,   16,   15,   13,   12,   10,    9,    7,    6,    4,    3,    1,   1
 };
 
-void vp8_start_encode(BOOL_CODER *br, unsigned char *source)
+void vp8_start_encode(BOOL_CODER *br, unsigned char *source, unsigned char *source_end)
 {
 
-    br->lowvalue = 0;
-    br->range    = 255;
-    br->value    = 0;
-    br->count    = -24;
-    br->buffer   = source;
-    br->pos      = 0;
+    br->lowvalue   = 0;
+    br->range      = 255;
+    br->value      = 0;
+    br->count      = -24;
+    br->buffer     = source;
+    br->buffer_end = source_end;
+    br->pos        = 0;
 }
 
 void vp8_stop_encode(BOOL_CODER *br)
index 04755f5329bb53f6885504d26d07ceace329edb2..569b7791fb9dda739217bbaee8886c2782b6424a 100644 (file)
@@ -20,6 +20,7 @@
 #define __INC_BOOLHUFF_H
 
 #include "vpx_ports/mem.h"
+#include "vpx/internal/vpx_codec_internal.h"
 
 typedef struct
 {
@@ -29,13 +30,15 @@ typedef struct
     int count;
     unsigned int pos;
     unsigned char *buffer;
+    unsigned char *buffer_end;
+    struct vpx_internal_error_info *error;
 
     // Variables used to track bit costs without outputing to the bitstream
     unsigned int  measure_cost;
     unsigned long bit_counter;
 } BOOL_CODER;
 
-extern void vp8_start_encode(BOOL_CODER *bc, unsigned char *buffer);
+extern void vp8_start_encode(BOOL_CODER *bc, unsigned char *buffer, unsigned char *buffer_end);
 
 extern void vp8_encode_value(BOOL_CODER *br, int data, int bits);
 extern void vp8_stop_encode(BOOL_CODER *bc);
@@ -44,7 +47,19 @@ extern const unsigned int vp8_prob_cost[256];
 
 DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
 
+static int validate_buffer(const unsigned char *start,
+                           size_t               len,
+                           const unsigned char *end,
+                           struct vpx_internal_error_info *error)
+{
+    if (start + len > start && start + len < end)
+        return 1;
+    else
+        vpx_internal_error(error, VPX_CODEC_CORRUPT_FRAME,
+            "Truncated packet or corrupt partition ");
 
+    return 0;
+}
 static void vp8_encode_bool(BOOL_CODER *br, int bit, int probability)
 {
     unsigned int split;
@@ -96,7 +111,9 @@ static void vp8_encode_bool(BOOL_CODER *br, int bit, int probability)
             br->buffer[x] += 1;
         }
 
+        validate_buffer(br->buffer + br->pos, 1, br->buffer_end, br->error);
         br->buffer[br->pos++] = (lowvalue >> (24 - offset));
+
         lowvalue <<= offset;
         shift = count;
         lowvalue &= 0xffffff;
index 43c971480a8170e518910985cc9fd2ecac5c3850..5a1cf1f9f5cac1415b4408854988d5cf7127f542 100644 (file)
@@ -3447,6 +3447,7 @@ static void encode_frame_to_data_rate
     VP8_COMP *cpi,
     unsigned long *size,
     unsigned char *dest,
+    unsigned char* dest_end,
     unsigned int *frame_flags
 )
 {
@@ -4414,7 +4415,7 @@ static void encode_frame_to_data_rate
 #endif
 
     // build the bitstream
-    vp8_pack_bitstream(cpi, dest, size);
+    vp8_pack_bitstream(cpi, dest, dest_end, size);
 
 #if CONFIG_MULTITHREAD
     /* if PSNR packets are generated we have to wait for the lpf */
@@ -4827,13 +4828,13 @@ static void check_gf_quality(VP8_COMP *cpi)
 }
 
 #if !(CONFIG_REALTIME_ONLY)
-static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
+static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned char * dest_end, unsigned int *frame_flags)
 {
 
     if (!cpi->common.refresh_alt_ref_frame)
         vp8_second_pass(cpi);
 
-    encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+    encode_frame_to_data_rate(cpi, size, dest, dest_end, frame_flags);
     cpi->twopass.bits_left -= 8 * *size;
 
     if (!cpi->common.refresh_alt_ref_frame)
@@ -4906,7 +4907,7 @@ static int frame_is_reference(const VP8_COMP *cpi)
 }
 
 
-int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, int64_t *time_stamp, int64_t *time_end, int flush)
+int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, unsigned char *dest_end, int64_t *time_stamp, int64_t *time_end, int flush)
 {
 #if HAVE_ARMV7
     int64_t store_reg[8];
@@ -4921,6 +4922,14 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
     if (!cpi)
         return -1;
 
+    if (setjmp(cpi->common.error.jmp)){
+        cpi->common.error.setjmp = 0;
+        return VPX_CODEC_CORRUPT_FRAME;
+    }
+
+    cpi->bc.error = &cpi->common.error;
+    cpi->common.error.setjmp = 1;
+
 #if HAVE_ARMV7
 #if CONFIG_RUNTIME_CPU_DETECT
     if (cm->rtcd.flags & HAS_NEON)
@@ -5134,11 +5143,11 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
     }
     else if (cpi->pass == 2)
     {
-        Pass2Encode(cpi, size, dest, frame_flags);
+        Pass2Encode(cpi, size, dest, dest_end, frame_flags);
     }
     else
 #endif
-        encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+        encode_frame_to_data_rate(cpi, size, dest, dest_end, frame_flags);
 
     if (cpi->compressor_speed == 2)
     {
@@ -5371,6 +5380,8 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
     }
 #endif
 
+    cpi->common.error.setjmp = 0;
+
     return 0;
 }
 
index 6678c15fb6f87fd53efa3d45b491af9fee1e5b5c..0686a108aeb3c374d4ae908bedf1571eb11737c1 100644 (file)
@@ -683,7 +683,7 @@ void control_data_rate(VP8_COMP *cpi);
 
 void vp8_encode_frame(VP8_COMP *cpi);
 
-void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size);
+void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned char *dest_end, unsigned long *size);
 
 void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x);
 
index f8336240cae659bfb2c7cec5af204e2ffa3d17d0..1be7e337fc59592ca9f6eaae7cd560fcade6adbe 100644 (file)
@@ -761,6 +761,8 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
         int64_t dst_time_stamp, dst_end_time_stamp;
         unsigned long size, cx_data_sz;
         unsigned char *cx_data;
+        unsigned char *cx_data_end;
+        int comp_data_state = 0;
 
         /* Set up internal flags */
         if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
@@ -793,11 +795,25 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
 
         cx_data = ctx->cx_data;
         cx_data_sz = ctx->cx_data_sz;
+        cx_data_end = ctx->cx_data + cx_data_sz;
         lib_flags = 0;
 
-        while (cx_data_sz >= ctx->cx_data_sz / 2
-               && -1 != vp8_get_compressed_data(ctx->cpi, &lib_flags, &size, cx_data, &dst_time_stamp, &dst_end_time_stamp, !img))
+        while (cx_data_sz >= ctx->cx_data_sz / 2)
         {
+            comp_data_state = vp8_get_compressed_data(ctx->cpi,
+                                                  &lib_flags,
+                                                  &size,
+                                                  cx_data,
+                                                  cx_data_end,
+                                                  &dst_time_stamp,
+                                                  &dst_end_time_stamp,
+                                                  !img);
+
+            if(comp_data_state == VPX_CODEC_CORRUPT_FRAME)
+                return VPX_CODEC_CORRUPT_FRAME;
+            else if(comp_data_state == -1)
+                break;
+
             if (size)
             {
                 vpx_codec_pts_t    round, delta;