Fix an edge case in tile group decoding As of patch https://aomedia-review.googlesource.com/c/20220 , it is no longer always the case that tile_rows == (1 << log2_tile_rows) and tile_cols == (1 << log2_tile_cols). This exposed an inconsistency in the tile-group decoding: When reading the first tile group in a frame, we read (log2_tile_rows + log2_tile_cols) bits each for the tile group start and length, but when reading later tile groups we read get_msb(tile_rows * tile_cols) bits. But now there are edge cases where those values differ! Since the encoder always uses (log2_tile_rows + log2_tile_cols) bits, this leads to mis-parsing the bitstream. Fix this by moving the decode logic to one function, which always reads (log2_tile_rows + log2_tile_cols) bits. As a bonus, this gives us one place to check other invariants, eg. that tile groups can't run off the end of the frame. Change-Id: I83b24314526b6055300b70b0f1cdce038e6b23dc
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 8efb3c4..d63ae59 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -3240,6 +3240,19 @@ pool->frame_bufs[cm->new_fb_idx].buf.render_height = cm->render_height; } +static void read_tile_group_range(AV1Decoder *pbi, + struct aom_read_bit_buffer *const rb) { + AV1_COMMON *const cm = &pbi->common; + const int num_bits = cm->log2_tile_rows + cm->log2_tile_cols; + const int num_tiles = + cm->tile_rows * cm->tile_cols; // Note: May be < (1<<num_bits) + pbi->tg_start = aom_rb_read_literal(rb, num_bits); + pbi->tg_size = 1 + aom_rb_read_literal(rb, num_bits); + if (pbi->tg_start + pbi->tg_size > num_tiles) + aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME, + "Tile group extends past last tile in frame"); +} + static void read_tile_info(AV1Decoder *const pbi, struct aom_read_bit_buffer *const rb) { AV1_COMMON *const cm = &pbi->common; @@ -3333,13 +3346,7 @@ // Store an index to the location of the tile group information pbi->tg_size_bit_offset = rb->bit_offset; - pbi->tg_size = 1 << (cm->log2_tile_rows + cm->log2_tile_cols); - if (cm->log2_tile_rows + cm->log2_tile_cols > 0) { - pbi->tg_start = - aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols); - pbi->tg_size = - 1 + aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols); - } + read_tile_group_range(pbi, rb); } static int mem_get_varsize(const uint8_t *src, int sz) { @@ -3547,8 +3554,6 @@ int first_tile_in_tg = 0; struct aom_read_bit_buffer rb_tg_hdr; uint8_t clear_data[MAX_AV1_HEADER_SIZE]; - const int num_tiles = tile_rows * tile_cols; - const int num_bits = OD_ILOG(num_tiles) - 1; const size_t hdr_size = pbi->uncomp_hdr_size + pbi->first_partition_size; const int tg_size_bit_offset = pbi->tg_size_bit_offset; #if CONFIG_DEPENDENT_HORZTILES @@ -3569,14 +3574,11 @@ if (hdr_offset) { init_read_bit_buffer(pbi, &rb_tg_hdr, data, data_end, clear_data); rb_tg_hdr.bit_offset = tg_size_bit_offset; - if (num_tiles) { - pbi->tg_start = aom_rb_read_literal(&rb_tg_hdr, num_bits); - pbi->tg_size = 1 + aom_rb_read_literal(&rb_tg_hdr, num_bits); + read_tile_group_range(pbi, &rb_tg_hdr); #if CONFIG_DEPENDENT_HORZTILES - tile_group_start_row = r; - tile_group_start_col = c; + tile_group_start_row = r; + tile_group_start_col = c; #endif - } } first_tile_in_tg += tc == first_tile_in_tg ? pbi->tg_size : 0; data += hdr_offset;