Commit 31450024 authored by Jeffrey Kardatzke's avatar Jeffrey Kardatzke Committed by Commit Bot

H265 decoder fuzzer fix for ref pic counts and others

Spec isn't clear on this, but when we are doing short term ref pic sets
that are relative to existing ones, these can keep chaining and then
grow their size without bound. Seems reasonable to constrain this value
for the delta based ones just as for the fully declared ones.

Also fixes range validation for cpb_cnt.

Also fixes zero valued NumPicTotalCurr.

Also fixes overflow in SPS parsing.

BUG=b:153111783,chromium:1148504,chromium:1148698,chromium:1148863,
chromium:1148910
TEST=Fuzzer no longer crashes

Change-Id: I430f1fe2d4e4e5affe6caea80be6d01b84896b14
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536851Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Auto-Submit: Jeffrey Kardatzke <jkardatzke@google.com>
Cr-Commit-Position: refs/heads/master@{#827449}
parent b8bcd254
...@@ -387,6 +387,16 @@ H265Decoder::H265Accelerator::Status H265Decoder::PreprocessCurrentSlice() { ...@@ -387,6 +387,16 @@ H265Decoder::H265Accelerator::Status H265Decoder::PreprocessCurrentSlice() {
DCHECK(!curr_pic_); DCHECK(!curr_pic_);
} }
// Validate that NumPicTotalCurr is non-zero for P/B slices. We do check this
// in the parser, but there's a way it can slip by when
// dependent_slice_segment_flag is set (and then we can't verify until we
// copy the defaults to the next slice in the decoder).
if ((slice_hdr->IsPSlice() || slice_hdr->IsBSlice()) &&
!slice_hdr->num_pic_total_curr) {
DVLOG(2) << "Zero valued NumPicTotalCurr for P/B slice";
return H265Accelerator::Status::kFail;
}
return H265Accelerator::Status::kOk; return H265Accelerator::Status::kOk;
} }
......
...@@ -603,20 +603,30 @@ H265Parser::Result H265Parser::ParseSPS(int* sps_id) { ...@@ -603,20 +603,30 @@ H265Parser::Result H265Parser::ParseSPS(int* sps_id) {
} }
} }
READ_UE_OR_RETURN(&sps->log2_min_luma_coding_block_size_minus3); READ_UE_OR_RETURN(&sps->log2_min_luma_coding_block_size_minus3);
// This enforces that min_cb_log2_size_y below will be <= 31 and prevents
// integer overflow math there.
TRUE_OR_RETURN(sps->log2_min_luma_coding_block_size_minus3 <= 28);
READ_UE_OR_RETURN(&sps->log2_diff_max_min_luma_coding_block_size); READ_UE_OR_RETURN(&sps->log2_diff_max_min_luma_coding_block_size);
int min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; int min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3;
sps->ctb_log2_size_y = base::CheckedNumeric<int> ctb_log2_size_y = min_cb_log2_size_y;
min_cb_log2_size_y + sps->log2_diff_max_min_luma_coding_block_size; ctb_log2_size_y += sps->log2_diff_max_min_luma_coding_block_size;
TRUE_OR_RETURN(min_cb_log2_size_y <= 31 && sps->ctb_log2_size_y <= 31); if (!ctb_log2_size_y.IsValid())
return kInvalidStream;
sps->ctb_log2_size_y = ctb_log2_size_y.ValueOrDefault(0);
TRUE_OR_RETURN(sps->ctb_log2_size_y <= 31);
int min_cb_size_y = 1 << min_cb_log2_size_y; int min_cb_size_y = 1 << min_cb_log2_size_y;
int ctb_size_y = 1 << sps->ctb_log2_size_y; int ctb_size_y = 1 << sps->ctb_log2_size_y;
sps->pic_width_in_ctbs_y = base::ClampCeil( sps->pic_width_in_ctbs_y = base::ClampCeil(
static_cast<float>(sps->pic_width_in_luma_samples) / ctb_size_y); static_cast<float>(sps->pic_width_in_luma_samples) / ctb_size_y);
sps->pic_height_in_ctbs_y = base::ClampCeil( sps->pic_height_in_ctbs_y = base::ClampCeil(
static_cast<float>(sps->pic_height_in_luma_samples) / ctb_size_y); static_cast<float>(sps->pic_height_in_luma_samples) / ctb_size_y);
sps->pic_size_in_ctbs_y = base::CheckedNumeric<int> pic_size_in_ctbs_y = sps->pic_width_in_ctbs_y;
sps->pic_width_in_ctbs_y * sps->pic_height_in_ctbs_y; pic_size_in_ctbs_y *= sps->pic_height_in_ctbs_y;
if (!pic_size_in_ctbs_y.IsValid())
return kInvalidStream;
sps->pic_size_in_ctbs_y = pic_size_in_ctbs_y.ValueOrDefault(0);
TRUE_OR_RETURN(sps->pic_width_in_luma_samples % min_cb_size_y == 0); TRUE_OR_RETURN(sps->pic_width_in_luma_samples % min_cb_size_y == 0);
TRUE_OR_RETURN(sps->pic_height_in_luma_samples % min_cb_size_y == 0); TRUE_OR_RETURN(sps->pic_height_in_luma_samples % min_cb_size_y == 0);
...@@ -1113,6 +1123,7 @@ H265Parser::Result H265Parser::ParseSliceHeader(const H265NALU& nalu, ...@@ -1113,6 +1123,7 @@ H265Parser::Result H265Parser::ParseSliceHeader(const H265NALU& nalu,
shdr->num_pic_total_curr++; shdr->num_pic_total_curr++;
} }
TRUE_OR_RETURN(shdr->num_pic_total_curr);
if (pps->lists_modification_present_flag && if (pps->lists_modification_present_flag &&
shdr->num_pic_total_curr > 1) { shdr->num_pic_total_curr > 1) {
res = ParseRefPicListsModifications(*shdr, res = ParseRefPicListsModifications(*shdr,
...@@ -1511,6 +1522,13 @@ H265Parser::Result H265Parser::ParseStRefPicSet( ...@@ -1511,6 +1522,13 @@ H265Parser::Result H265Parser::ParseStRefPicSet(
} }
} }
st_ref_pic_set->num_positive_pics = i; st_ref_pic_set->num_positive_pics = i;
IN_RANGE_OR_RETURN(
st_ref_pic_set->num_negative_pics, 0,
sps.sps_max_dec_pic_buffering_minus1[sps.sps_max_sub_layers_minus1]);
IN_RANGE_OR_RETURN(
st_ref_pic_set->num_positive_pics, 0,
sps.sps_max_dec_pic_buffering_minus1[sps.sps_max_sub_layers_minus1] -
st_ref_pic_set->num_negative_pics);
} else { } else {
READ_UE_OR_RETURN(&st_ref_pic_set->num_negative_pics); READ_UE_OR_RETURN(&st_ref_pic_set->num_negative_pics);
READ_UE_OR_RETURN(&st_ref_pic_set->num_positive_pics); READ_UE_OR_RETURN(&st_ref_pic_set->num_positive_pics);
...@@ -1683,6 +1701,7 @@ H265Parser::Result H265Parser::ParseAndIgnoreHrdParameters( ...@@ -1683,6 +1701,7 @@ H265Parser::Result H265Parser::ParseAndIgnoreHrdParameters(
int cpb_cnt = 1; int cpb_cnt = 1;
if (!low_delay_hrd_flag) { if (!low_delay_hrd_flag) {
READ_UE_OR_RETURN(&cpb_cnt); READ_UE_OR_RETURN(&cpb_cnt);
IN_RANGE_OR_RETURN(cpb_cnt, 0, 31);
cpb_cnt += 1; // parsed as minus1 cpb_cnt += 1; // parsed as minus1
} }
if (nal_hrd_parameters_present_flag) { if (nal_hrd_parameters_present_flag) {
......
Markdown is supported
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