diff --git a/media/parsers/h264_parser.cc b/media/parsers/h264_parser.cc index 8ae6bb03d9a9a..7370725c85593 100644 --- a/media/parsers/h264_parser.cc +++ b/media/parsers/h264_parser.cc @@ -1419,6 +1419,23 @@ H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu, } } + // H.264 spec 7.4.3: first_mb_in_slice shall be in [0, PicSizeInMbs - 1]. + // Without this check the value flows unvalidated into + // VASliceParameterBufferH264.first_mb_in_slice and is used by the VA-API + // driver as a write offset into the decode surface. + { + const int pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1; + const int frame_height_in_mbs = (2 - sps->frame_mbs_only_flag) * + (sps->pic_height_in_map_units_minus1 + 1); + const int pic_height_in_mbs = + frame_height_in_mbs / (1 + shdr->field_pic_flag); + base::CheckedNumeric pic_size_in_mbs_checked = pic_width_in_mbs; + pic_size_in_mbs_checked *= pic_height_in_mbs; + TRUE_OR_RETURN(pic_size_in_mbs_checked.IsValid()); + const int pic_size_in_mbs = pic_size_in_mbs_checked.ValueOrDie(); + IN_RANGE_OR_RETURN(shdr->first_mb_in_slice, 0, pic_size_in_mbs - 1); + } + if (shdr->idr_pic_flag) { READ_UE_OR_RETURN(&shdr->idr_pic_id); IN_RANGE_OR_RETURN(shdr->idr_pic_id, 0, 65535);