Fix fuzzing issue reported by Chromium fuzzing test

Bug: chromium:1475195, chromium:1475944, chromium:1475909
Change-Id: Iaa9dc6570a8b70ec58efe0a64d468e1cae4cb484
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/317504
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40696}
diff --git a/common_video/h265/h265_bitstream_parser.cc b/common_video/h265/h265_bitstream_parser.cc
index 2509398..ee77166 100644
--- a/common_video/h265/h265_bitstream_parser.cc
+++ b/common_video/h265/h265_bitstream_parser.cc
@@ -151,8 +151,6 @@
     }
     uint32_t num_long_term_sps = 0;
     uint32_t num_long_term_pics = 0;
-    std::vector<uint32_t> lt_idx_sps;
-    std::vector<uint32_t> poc_lsb_lt;
     std::vector<bool> used_by_curr_pic_lt_flag;
     bool short_term_ref_pic_set_sps_flag = false;
     uint32_t short_term_ref_pic_set_idx = 0;
@@ -188,6 +186,8 @@
         if (short_term_ref_pic_set_idx_bits > 0) {
           short_term_ref_pic_set_idx =
               slice_reader.ReadBits(short_term_ref_pic_set_idx_bits);
+          IN_RANGE_OR_RETURN(short_term_ref_pic_set_idx, 0,
+                             sps->num_short_term_ref_pic_sets - 1);
         }
       }
       if (sps->long_term_ref_pics_present_flag) {
@@ -201,27 +201,26 @@
         num_long_term_pics = slice_reader.ReadExponentialGolomb();
         IN_RANGE_OR_RETURN(num_long_term_pics, 0,
                            kMaxLongTermRefPicSets - num_long_term_sps);
-        lt_idx_sps.resize(num_long_term_sps + num_long_term_pics, 0);
         used_by_curr_pic_lt_flag.resize(num_long_term_sps + num_long_term_pics,
                                         0);
-        poc_lsb_lt.resize(num_long_term_sps + num_long_term_pics, 0);
         for (uint32_t i = 0; i < num_long_term_sps + num_long_term_pics; i++) {
           if (i < num_long_term_sps) {
-            uint32_t lt_idx_sps_bits = 0;
+            uint32_t lt_idx_sps = 0;
             if (sps->num_long_term_ref_pics_sps > 1) {
               // lt_idx_sps: u(v)
-              lt_idx_sps_bits =
+              uint32_t lt_idx_sps_bits =
                   H265::Log2Ceiling(sps->num_long_term_ref_pics_sps);
-              lt_idx_sps[i] = slice_reader.ReadBits(lt_idx_sps_bits);
+              lt_idx_sps = slice_reader.ReadBits(lt_idx_sps_bits);
+              IN_RANGE_OR_RETURN(lt_idx_sps, 0,
+                                 sps->num_long_term_ref_pics_sps - 1);
             }
-            poc_lsb_lt[i] = sps->lt_ref_pic_poc_lsb_sps[lt_idx_sps_bits];
             used_by_curr_pic_lt_flag[i] =
-                sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps_bits];
+                sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps];
           } else {
             // poc_lsb_lt: u(v)
             uint32_t poc_lsb_lt_bits =
                 sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
-            poc_lsb_lt[i] = slice_reader.ReadBits(poc_lsb_lt_bits);
+            slice_reader.ConsumeBits(poc_lsb_lt_bits);
             // used_by_curr_pic_lt_flag: u(1)
             used_by_curr_pic_lt_flag[i] = slice_reader.Read<bool>();
           }
@@ -375,20 +374,22 @@
         return kUnsupportedStream;
       }
       // five_minus_max_num_merge_cand: ue(v)
-      int five_minus_max_num_merge_cand = slice_reader.ReadExponentialGolomb();
+      uint32_t five_minus_max_num_merge_cand =
+          slice_reader.ReadExponentialGolomb();
       IN_RANGE_OR_RETURN(5 - five_minus_max_num_merge_cand, 1, 5);
     }
   }
 
   // slice_qp_delta: se(v)
   int32_t last_slice_qp_delta = slice_reader.ReadSignedExponentialGolomb();
-  IN_RANGE_OR_RETURN(26 + pps->init_qp_minus26 + last_slice_qp_delta,
-                     -pps->qp_bd_offset_y, 51);
   if (!slice_reader.Ok() || (abs(last_slice_qp_delta) > kMaxAbsQpDeltaValue)) {
     // Something has gone wrong, and the parsed value is invalid.
-    RTC_LOG(LS_WARNING) << "Parsed QP value out of range.";
+    RTC_LOG(LS_ERROR) << "Parsed QP value out of range.";
     return kInvalidStream;
   }
+  // 7-54 in H265 spec.
+  IN_RANGE_OR_RETURN(26 + pps->init_qp_minus26 + last_slice_qp_delta,
+                     -pps->qp_bd_offset_y, 51);
 
   last_slice_qp_delta_ = last_slice_qp_delta;
   last_slice_pps_id_ = pps_id;
diff --git a/common_video/h265/h265_bitstream_parser_unittest.cc b/common_video/h265/h265_bitstream_parser_unittest.cc
index 34986e6..7ca9794 100644
--- a/common_video/h265/h265_bitstream_parser_unittest.cc
+++ b/common_video/h265/h265_bitstream_parser_unittest.cc
@@ -67,6 +67,30 @@
     0xbe, 0x6b, 0x15, 0x48, 0x59, 0x1f, 0xf7, 0xc1, 0x7c, 0xe2, 0xe8, 0x10,
 };
 
+// Contains enough of the image slice to contain invalid slice QP -52.
+const uint8_t kH265BitstreamInvalidQPChunk[] = {
+    0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08,
+    0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78,
+    0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08,
+    0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78,
+    0xb0, 0x03, 0xc0, 0x80, 0x10, 0xe5, 0x96, 0x56, 0x69, 0x24, 0xca, 0xe0,
+    0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x80,
+    0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, 0x00,
+    0x00, 0x01, 0x26, 0x01, 0xaf, 0x03, 0x4c,
+};
+
+// Contains enough of the image slice to contain invalid slice QP 52.
+const uint8_t kH265BitstreamInvalidQPChunk52[] = {
+    0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x04, 0x08,
+    0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78,
+    0x95, 0x98, 0x09, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08,
+    0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78,
+    0xb0, 0x03, 0xc0, 0x80, 0x10, 0xe5, 0x96, 0x56, 0x69, 0x24, 0xca, 0xe0,
+    0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x80,
+    0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, 0x00,
+    0x00, 0x01, 0x26, 0x01, 0xaf, 0x03, 0x44,
+};
+
 TEST(H265BitstreamParserTest, ReportsNoQpWithoutParsedSlices) {
   H265BitstreamParser h265_parser;
   EXPECT_FALSE(h265_parser.GetLastSliceQp().has_value());
@@ -109,4 +133,15 @@
   EXPECT_EQ(1u, *pps_id);
 }
 
+TEST(H265BitstreamParserTest, ReportsLastSliceQpInvalidQPSlices) {
+  H265BitstreamParser h265_parser;
+  h265_parser.ParseBitstream(kH265BitstreamInvalidQPChunk);
+  absl::optional<int> qp = h265_parser.GetLastSliceQp();
+  ASSERT_FALSE(qp.has_value());
+
+  h265_parser.ParseBitstream(kH265BitstreamInvalidQPChunk52);
+  qp = h265_parser.GetLastSliceQp();
+  ASSERT_FALSE(qp.has_value());
+}
+
 }  // namespace webrtc
diff --git a/common_video/h265/h265_pps_parser.cc b/common_video/h265/h265_pps_parser.cc
index 419fe31..1cc9abd 100644
--- a/common_video/h265/h265_pps_parser.cc
+++ b/common_video/h265/h265_pps_parser.cc
@@ -228,12 +228,6 @@
   }
   // lists_modification_present_flag: u(1)
   pps.lists_modification_present_flag = reader.Read<bool>();
-  // log2_parallel_merge_level_minus2: ue(v)
-  uint32_t log2_parallel_merge_level_minus2 = reader.ReadExponentialGolomb();
-  IN_RANGE_OR_RETURN_NULL(log2_parallel_merge_level_minus2, 0,
-                          sps->ctb_log2_size_y - 2);
-  // slice_segment_header_extension_present_flag: u(1)
-  reader.ConsumeBits(1);
 
   if (!reader.Ok()) {
     return absl::nullopt;
diff --git a/common_video/h265/h265_sps_parser.cc b/common_video/h265/h265_sps_parser.cc
index 4dcfa1f..96aee7c 100644
--- a/common_video/h265/h265_sps_parser.cc
+++ b/common_video/h265/h265_sps_parser.cc
@@ -63,8 +63,6 @@
 
 namespace webrtc {
 
-H265SpsParser::SpsState::SpsState() = default;
-
 H265SpsParser::ShortTermRefPicSet::ShortTermRefPicSet() = default;
 
 H265SpsParser::ProfileTierLevel::ProfileTierLevel() = default;
@@ -113,30 +111,23 @@
 }
 
 bool H265SpsParser::ParseScalingListData(BitstreamReader& reader) {
-  uint32_t scaling_list_pred_mode_flag[kMaxNumSizeIds][kMaxNumMatrixIds];
-  int scaling_list_pred_matrix_id_delta[kMaxNumSizeIds][kMaxNumMatrixIds];
   int32_t scaling_list_dc_coef_minus8[kMaxNumSizeIds][kMaxNumMatrixIds];
-  int32_t scaling_list[kMaxNumSizeIds][kMaxNumMatrixIds][kMaxNumCoefs];
   for (int size_id = 0; size_id < kMaxNumSizeIds; size_id++) {
     for (int matrix_id = 0; matrix_id < kMaxNumMatrixIds;
          matrix_id += (size_id == 3) ? 3 : 1) {
       // scaling_list_pred_mode_flag: u(1)
-      scaling_list_pred_mode_flag[size_id][matrix_id] = reader.Read<bool>();
-      if (!scaling_list_pred_mode_flag[size_id][matrix_id]) {
+      bool scaling_list_pred_mode_flag = reader.Read<bool>();
+      if (!scaling_list_pred_mode_flag) {
         // scaling_list_pred_matrix_id_delta: ue(v)
-        scaling_list_pred_matrix_id_delta[size_id][matrix_id] =
-            reader.ReadExponentialGolomb();
+        int scaling_list_pred_matrix_id_delta = reader.ReadExponentialGolomb();
         if (size_id <= 2) {
-          IN_RANGE_OR_RETURN_FALSE(
-              scaling_list_pred_matrix_id_delta[size_id][matrix_id], 0,
-              matrix_id);
+          IN_RANGE_OR_RETURN_FALSE(scaling_list_pred_matrix_id_delta, 0,
+                                   matrix_id);
         } else {  // size_id == 3
-          IN_RANGE_OR_RETURN_FALSE(
-              scaling_list_pred_matrix_id_delta[size_id][matrix_id], 0,
-              matrix_id / 3);
+          IN_RANGE_OR_RETURN_FALSE(scaling_list_pred_matrix_id_delta, 0,
+                                   matrix_id / 3);
         }
       } else {
-        int32_t next_coef = 8;
         uint32_t coef_num = std::min(kMaxNumCoefs, 1 << (4 + (size_id << 1)));
         if (size_id > 1) {
           // scaling_list_dc_coef_minus8: se(v)
@@ -144,15 +135,12 @@
               reader.ReadSignedExponentialGolomb();
           IN_RANGE_OR_RETURN_FALSE(
               scaling_list_dc_coef_minus8[size_id - 2][matrix_id], -7, 247);
-          next_coef = scaling_list_dc_coef_minus8[size_id - 2][matrix_id] + 8;
         }
         for (uint32_t i = 0; i < coef_num; i++) {
           // scaling_list_delta_coef: se(v)
           int32_t scaling_list_delta_coef =
               reader.ReadSignedExponentialGolomb();
           IN_RANGE_OR_RETURN_FALSE(scaling_list_delta_coef, -128, 127);
-          next_coef = (next_coef + scaling_list_delta_coef + 256) % 256;
-          scaling_list[size_id][matrix_id][i] = next_coef;
         }
       }
     }
@@ -192,7 +180,7 @@
     uint32_t ref_rps_idx = st_rps_idx - (delta_idx_minus1 + 1);
     uint32_t num_delta_pocs =
         short_term_ref_pic_set[ref_rps_idx].num_delta_pocs;
-    RTC_CHECK_LT(num_delta_pocs, kMaxShortTermRefPicSets);
+    IN_RANGE_OR_RETURN_NULL(num_delta_pocs, 0, kMaxShortTermRefPicSets);
     const ShortTermRefPicSet& ref_set = short_term_ref_pic_set[ref_rps_idx];
     bool used_by_curr_pic_flag[kMaxShortTermRefPicSets];
     bool use_delta_flag[kMaxShortTermRefPicSets];
@@ -212,8 +200,9 @@
     // and num_positive_pics.
     // Equation 7-61
     int i = 0;
-    RTC_CHECK_LE(ref_set.num_negative_pics + ref_set.num_positive_pics,
-                 kMaxShortTermRefPicSets);
+    IN_RANGE_OR_RETURN_NULL(
+        ref_set.num_negative_pics + ref_set.num_positive_pics, 0,
+        kMaxShortTermRefPicSets);
     for (int j = ref_set.num_positive_pics - 1; j >= 0; --j) {
       int d_poc = ref_set.delta_poc_s1[j] + delta_rps;
       if (d_poc < 0 && use_delta_flag[ref_set.num_negative_pics + j]) {
@@ -258,6 +247,11 @@
       }
     }
     st_ref_pic_set.num_positive_pics = i;
+    IN_RANGE_OR_RETURN_NULL(st_ref_pic_set.num_negative_pics, 0,
+                            sps_max_dec_pic_buffering_minus1);
+    IN_RANGE_OR_RETURN_NULL(
+        st_ref_pic_set.num_positive_pics, 0,
+        sps_max_dec_pic_buffering_minus1 - st_ref_pic_set.num_negative_pics);
 
   } else {
     // num_negative_pics: ue(v)
@@ -643,14 +637,12 @@
     sps.num_long_term_ref_pics_sps = reader.ReadExponentialGolomb();
     IN_RANGE_OR_RETURN_NULL(sps.num_long_term_ref_pics_sps, 0,
                             kMaxLongTermRefPicSets);
-    sps.lt_ref_pic_poc_lsb_sps.resize(sps.num_long_term_ref_pics_sps, 0);
     sps.used_by_curr_pic_lt_sps_flag.resize(sps.num_long_term_ref_pics_sps, 0);
     for (uint32_t i = 0; i < sps.num_long_term_ref_pics_sps; i++) {
       // lt_ref_pic_poc_lsb_sps: u(v)
       uint32_t lt_ref_pic_poc_lsb_sps_bits =
           sps.log2_max_pic_order_cnt_lsb_minus4 + 4;
-      sps.lt_ref_pic_poc_lsb_sps[i] =
-          reader.ReadBits(lt_ref_pic_poc_lsb_sps_bits);
+      reader.ConsumeBits(lt_ref_pic_poc_lsb_sps_bits);
       // used_by_curr_pic_lt_sps_flag: u(1)
       sps.used_by_curr_pic_lt_sps_flag[i] = reader.Read<bool>();
     }
diff --git a/common_video/h265/h265_sps_parser.h b/common_video/h265/h265_sps_parser.h
index c3ac04c..2dece2b 100644
--- a/common_video/h265/h265_sps_parser.h
+++ b/common_video/h265/h265_sps_parser.h
@@ -75,15 +75,15 @@
   // The parsed state of the SPS. Only some select values are stored.
   // Add more as they are actually needed.
   struct SpsState {
-    SpsState();
+    SpsState() = default;
 
-    uint32_t sps_max_sub_layers_minus1;
+    uint32_t sps_max_sub_layers_minus1 = 0;
     uint32_t chroma_format_idc = 0;
     uint32_t separate_colour_plane_flag = 0;
     uint32_t pic_width_in_luma_samples = 0;
     uint32_t pic_height_in_luma_samples = 0;
     uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0;
-    uint32_t sps_max_dec_pic_buffering_minus1[kMaxSubLayers];
+    uint32_t sps_max_dec_pic_buffering_minus1[kMaxSubLayers] = {};
     uint32_t log2_min_luma_coding_block_size_minus3 = 0;
     uint32_t log2_diff_max_min_luma_coding_block_size = 0;
     uint32_t sample_adaptive_offset_enabled_flag = 0;
@@ -91,7 +91,6 @@
     std::vector<H265SpsParser::ShortTermRefPicSet> short_term_ref_pic_set;
     uint32_t long_term_ref_pics_present_flag = 0;
     uint32_t num_long_term_ref_pics_sps = 0;
-    std::vector<uint32_t> lt_ref_pic_poc_lsb_sps;
     std::vector<uint32_t> used_by_curr_pic_lt_sps_flag;
     uint32_t sps_temporal_mvp_enabled_flag = 0;
     uint32_t width = 0;
@@ -100,7 +99,6 @@
     uint32_t vps_id = 0;
     uint32_t pic_width_in_ctbs_y = 0;
     uint32_t pic_height_in_ctbs_y = 0;
-    uint32_t ctb_log2_size_y = 0;
     uint32_t bit_depth_luma_minus8 = 0;
   };