Commit 2bcc4736 authored by John Koleszar's avatar John Koleszar Committed by Gerrit Code Review
Browse files

decode_tiles(): validate buffer reads

Previous code indexed using the tile length coded in the bitstream
without checking that the read would be valid.

Change-Id: Ia5047762223a4f80d75016dd546dc2ef18b6887d
Showing with 23 additions and 14 deletions
...@@ -539,21 +539,19 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mi_row, int mi_col, ...@@ -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, static void setup_token_decoder(VP9D_COMP *pbi,
const uint8_t *data, const uint8_t *data, size_t read_size,
vp9_reader *r) { vp9_reader *r) {
VP9_COMMON *pc = &pbi->common; VP9_COMMON *pc = &pbi->common;
const uint8_t *data_end = pbi->source + pbi->source_sz; 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 // Validate the calculated partition length. If the buffer
// described by the partition can't be fully read, then restrict // 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. // 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, vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition " "Truncated packet or corrupt tile length");
"%d length", 1);
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, vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d", 1); "Failed to allocate bool decoder %d", 1);
} }
...@@ -889,6 +887,7 @@ static void decode_tiles(VP9D_COMP *pbi, ...@@ -889,6 +887,7 @@ static void decode_tiles(VP9D_COMP *pbi,
VP9_COMMON *const pc = &pbi->common; VP9_COMMON *const pc = &pbi->common;
const uint8_t *data_ptr = data + first_partition_size; 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; int tile_row, tile_col;
// Note: this memset assumes above_context[0], [1] and [2] // Note: this memset assumes above_context[0], [1] and [2]
...@@ -925,7 +924,9 @@ static void decode_tiles(VP9D_COMP *pbi, ...@@ -925,7 +924,9 @@ static void decode_tiles(VP9D_COMP *pbi,
vp9_get_tile_row_offsets(pc, tile_row); vp9_get_tile_row_offsets(pc, tile_row);
for (tile_col = n_cols - 1; tile_col >= 0; tile_col--) { for (tile_col = n_cols - 1; tile_col >= 0; tile_col--) {
vp9_get_tile_col_offsets(pc, 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); decode_tile(pbi, residual_bc);
if (tile_row == pc->tile_rows - 1 && tile_col == n_cols - 1) if (tile_row == pc->tile_rows - 1 && tile_col == n_cols - 1)
bc_bak = *residual_bc; bc_bak = *residual_bc;
...@@ -938,18 +939,26 @@ static void decode_tiles(VP9D_COMP *pbi, ...@@ -938,18 +939,26 @@ static void decode_tiles(VP9D_COMP *pbi,
for (tile_row = 0; tile_row < pc->tile_rows; tile_row++) { for (tile_row = 0; tile_row < pc->tile_rows; tile_row++) {
vp9_get_tile_row_offsets(pc, tile_row); vp9_get_tile_row_offsets(pc, tile_row);
for (tile_col = 0; tile_col < pc->tile_columns; tile_col++) { for (tile_col = 0; tile_col < pc->tile_columns; tile_col++) {
size_t size;
vp9_get_tile_col_offsets(pc, tile_col); vp9_get_tile_col_offsets(pc, tile_col);
has_more = tile_col < pc->tile_columns - 1 || has_more = tile_col < pc->tile_columns - 1 ||
tile_row < pc->tile_rows - 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) { if (has_more) {
const int size = read_be32(data_ptr); if (!read_is_valid(data_ptr, 4, data_end))
data_ptr += 4 + size; 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) { ...@@ -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)) if (!read_is_valid(data, first_partition_size, data_end))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, 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->mode_info_context = pc->mi;
xd->prev_mode_info_context = pc->prev_mi; xd->prev_mode_info_context = pc->prev_mi;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment