decode_tiles(): validate buffer reads
authorJohn Koleszar <jkoleszar@google.com>
Tue, 11 Jun 2013 17:06:31 +0000 (10:06 -0700)
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>
Tue, 11 Jun 2013 21:52:32 +0000 (14:52 -0700)
Previous code indexed using the tile length coded in the bitstream
without checking that the read would be valid.

Change-Id: Ia5047762223a4f80d75016dd546dc2ef18b6887d

vp9/decoder/vp9_decodframe.c

index fa1f8a4..f65d7c7 100644 (file)
@@ -539,21 +539,19 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mi_row, int mi_col,
 }
 
 static void setup_token_decoder(VP9D_COMP *pbi,
-                                const uint8_t *data,
+                                const uint8_t *data, size_t read_size,
                                 vp9_reader *r) {
   VP9_COMMON *pc = &pbi->common;
   const uint8_t *data_end = pbi->source + pbi->source_sz;
-  const size_t partition_size = data_end - data;
 
   // Validate the calculated partition length. If the buffer
   // described by the partition can't be fully read, then restrict
   // it to the portion that can be (for EC mode) or throw an error.
-  if (!read_is_valid(data, partition_size, data_end))
+  if (!read_is_valid(data, read_size, data_end))
     vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                       "Truncated packet or corrupt partition "
-                       "%d length", 1);
+                       "Truncated packet or corrupt tile length");
 
-  if (vp9_reader_init(r, data, partition_size))
+  if (vp9_reader_init(r, data, read_size))
     vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate bool decoder %d", 1);
 }
@@ -889,6 +887,7 @@ static void decode_tiles(VP9D_COMP *pbi,
   VP9_COMMON *const pc = &pbi->common;
 
   const uint8_t *data_ptr = data + first_partition_size;
+  const uint8_t* const data_end = pbi->source + pbi->source_sz;
   int tile_row, tile_col;
 
   // Note: this memset assumes above_context[0], [1] and [2]
@@ -925,7 +924,9 @@ static void decode_tiles(VP9D_COMP *pbi,
       vp9_get_tile_row_offsets(pc, tile_row);
       for (tile_col = n_cols - 1; tile_col >= 0; tile_col--) {
         vp9_get_tile_col_offsets(pc, tile_col);
-        setup_token_decoder(pbi, data_ptr2[tile_row][tile_col], residual_bc);
+        setup_token_decoder(pbi, data_ptr2[tile_row][tile_col],
+                            data_end - data_ptr2[tile_row][tile_col],
+                            residual_bc);
         decode_tile(pbi, residual_bc);
         if (tile_row == pc->tile_rows - 1 && tile_col == n_cols - 1)
           bc_bak = *residual_bc;
@@ -938,18 +939,26 @@ static void decode_tiles(VP9D_COMP *pbi,
     for (tile_row = 0; tile_row < pc->tile_rows; tile_row++) {
       vp9_get_tile_row_offsets(pc, tile_row);
       for (tile_col = 0; tile_col < pc->tile_columns; tile_col++) {
+        size_t size;
+
         vp9_get_tile_col_offsets(pc, tile_col);
 
         has_more = tile_col < pc->tile_columns - 1 ||
                    tile_row < pc->tile_rows - 1;
-
-        setup_token_decoder(pbi, data_ptr + (has_more ? 4 : 0), residual_bc);
-        decode_tile(pbi, residual_bc);
-
         if (has_more) {
-          const int size = read_be32(data_ptr);
-          data_ptr += 4 + size;
+          if (!read_is_valid(data_ptr, 4, data_end))
+            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                         "Truncated packet or corrupt tile length");
+
+          size = read_be32(data_ptr);
+          data_ptr += 4;
+        } else {
+          size = data_end - data_ptr;
         }
+
+        setup_token_decoder(pbi, data_ptr, size, residual_bc);
+        decode_tile(pbi, residual_bc);
+        data_ptr += size;
       }
     }
   }
@@ -1146,7 +1155,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
 
   if (!read_is_valid(data, first_partition_size, data_end))
     vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                       "Truncated packet or corrupt partition 0 length");
+                       "Truncated packet or corrupt header length");
 
   xd->mode_info_context = pc->mi;
   xd->prev_mode_info_context = pc->prev_mi;