row_mt worker should check for bit reader overflow This is the row_mt version of bug oss-fuzz:9663. The row_mt worker should also check if the entropy decoder has read beyond the end of the data buffer. Move most of the code inside the first while loop in row_mt_worker_hook() to the new parse_tile_row_mt() function. The check for bit reader overflow is performed in parse_tile_row_mt(). One reason for adding the new parse_tile_row_mt() function is to highlight its similarity to the decode_tile() function, Move the set_decode_func_pointers(td, 0x1) call in row_mt_worker_hook() from inside the first while loop to the outside, so that it is called only once. BUG=oss-fuzz:10646,oss-fuzz:9663 Change-Id: I39735bb7dd8b879985e6cf87e8a24b9dbcd01a34 (cherry picked from commit fe9ce8d6c9a26057d77def3e8dde4d87c63b642c)
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 81cd879..04e9d63 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -3436,13 +3436,53 @@ #endif } +// This function is very similar to decode_tile(). It would be good to figure +// out how to share code. +static void parse_tile_row_mt(AV1Decoder *pbi, ThreadData *const td, + TileDataDec *const tile_data) { + AV1_COMMON *const cm = &pbi->common; + const int sb_mi_size = mi_size_wide[cm->seq_params.sb_size]; + const int num_planes = av1_num_planes(cm); + TileInfo tile_info = tile_data->tile_info; + int tile_row = tile_info.tile_row; + + av1_zero_above_context(cm, &td->xd, tile_info.mi_col_start, + tile_info.mi_col_end, tile_row); + av1_reset_loop_filter_delta(&td->xd, num_planes); + av1_reset_loop_restoration(&td->xd, num_planes); + + for (int mi_row = tile_info.mi_row_start; mi_row < tile_info.mi_row_end; + mi_row += cm->seq_params.mib_size) { + av1_zero_left_context(&td->xd); + + for (int mi_col = tile_info.mi_col_start; mi_col < tile_info.mi_col_end; + mi_col += cm->seq_params.mib_size) { + set_cb_buffer(pbi, &td->xd, pbi->cb_buffer_base, num_planes, mi_row, + mi_col); + + // Bit-stream parsing of the superblock + decode_partition(pbi, td, mi_row, mi_col, td->bit_reader, + cm->seq_params.sb_size, 0x1); + + if (aom_reader_has_overflowed(td->bit_reader)) { + aom_merge_corrupted_flag(&td->xd.corrupted, 1); + return; + } + } + signal_parse_sb_row_done(pbi, tile_data, sb_mi_size); + } + + int corrupted = + (check_trailing_bits_after_symbol_coder(td->bit_reader)) ? 1 : 0; + aom_merge_corrupted_flag(&td->xd.corrupted, corrupted); +} + static int row_mt_worker_hook(void *arg1, void *arg2) { DecWorkerData *const thread_data = (DecWorkerData *)arg1; AV1Decoder *const pbi = (AV1Decoder *)arg2; AV1_COMMON *cm = &pbi->common; ThreadData *const td = thread_data->td; uint8_t allow_update_cdf; - const int sb_mi_size = mi_size_wide[cm->seq_params.sb_size]; AV1DecRowMTInfo *frame_row_mt_info = &pbi->frame_row_mt_info; td->xd.corrupted = 0; @@ -3464,10 +3504,11 @@ } thread_data->error_info.setjmp = 1; - const int num_planes = av1_num_planes(cm); allow_update_cdf = cm->large_scale_tile ? 0 : 1; allow_update_cdf = allow_update_cdf && !cm->disable_cdf_update; + set_decode_func_pointers(td, 0x1); + assert(cm->tile_cols > 0); while (1) { TileJobsDec *cur_job_info = get_dec_job_info(&pbi->tile_mt_info); @@ -3478,36 +3519,8 @@ tile_worker_hook_init(pbi, thread_data, tile_buffer, tile_data, allow_update_cdf); - set_decode_func_pointers(td, 0x1); - // decode tile - TileInfo tile_info = tile_data->tile_info; - int tile_row = tile_info.tile_row; - - av1_zero_above_context(cm, &td->xd, tile_info.mi_col_start, - tile_info.mi_col_end, tile_row); - av1_reset_loop_filter_delta(&td->xd, num_planes); - av1_reset_loop_restoration(&td->xd, num_planes); - - for (int mi_row = tile_info.mi_row_start; mi_row < tile_info.mi_row_end; - mi_row += cm->seq_params.mib_size) { - av1_zero_left_context(&td->xd); - - for (int mi_col = tile_info.mi_col_start; mi_col < tile_info.mi_col_end; - mi_col += cm->seq_params.mib_size) { - set_cb_buffer(pbi, &td->xd, pbi->cb_buffer_base, num_planes, mi_row, - mi_col); - - // Bit-stream parsing of the superblock - decode_partition(pbi, td, mi_row, mi_col, td->bit_reader, - cm->seq_params.sb_size, 0x1); - } - signal_parse_sb_row_done(pbi, tile_data, sb_mi_size); - } - - int corrupted = - (check_trailing_bits_after_symbol_coder(td->bit_reader)) ? 1 : 0; - aom_merge_corrupted_flag(&td->xd.corrupted, corrupted); + parse_tile_row_mt(pbi, td, tile_data); } else { break; }