Commit adfc3c25 for libheif

commit adfc3c25fe4e7e5114a2c7b6398d3ecdf376131e
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Fri May 15 22:05:52 2026 +0200

    check all get_uvlc() calls for errors (#1785)

diff --git a/libheif/codecs/avc_boxes.cc b/libheif/codecs/avc_boxes.cc
index 16033fb6..363c11ee 100644
--- a/libheif/codecs/avc_boxes.cc
+++ b/libheif/codecs/avc_boxes.cc
@@ -362,15 +362,15 @@ Error parse_sps_for_avcC_configuration(const uint8_t* sps, size_t size,
   config->AVCLevelIndication = reader.get_bits8(8);
   config->lengthSize = 4;

-  uint32_t value;
-  reader.get_uvlc(&value); // SPS ID
-
   Error invalidUVLC{
     heif_error_Invalid_input,
     heif_suberror_Unspecified,
     "Invalid variable length code in AVC SPS header"
   };

+  uint32_t value;
+  if (!reader.get_uvlc(&value)) { return invalidUVLC; } // SPS ID
+
   if (std::set<int>{100, 110, 122, 244, 44, 83, 86}.contains(config->AVCProfileIndication)) {
     if (!reader.get_uvlc(&value)) {
       return invalidUVLC;
@@ -413,31 +413,33 @@ Error parse_sps_for_avcC_configuration(const uint8_t* sps, size_t size,
     config->bit_depth_chroma = 8;
   }

-  reader.get_uvlc(&value); // log2_max_frame_num_minus4
+  if (!reader.get_uvlc(&value)) { return invalidUVLC; } // log2_max_frame_num_minus4
   uint32_t pic_order_cnt_type;
-  reader.get_uvlc(&pic_order_cnt_type);
+  if (!reader.get_uvlc(&pic_order_cnt_type)) { return invalidUVLC; }
   if (pic_order_cnt_type == 0) {
-    reader.get_uvlc(&value);
+    if (!reader.get_uvlc(&value)) { return invalidUVLC; }
   }
   else if (pic_order_cnt_type == 1) {
     reader.get_bits(1);
     int32_t svalue;
-    reader.get_svlc(&svalue);
-    reader.get_svlc(&svalue);
+    if (!reader.get_svlc(&svalue) ||
+        !reader.get_svlc(&svalue)) { return invalidUVLC; }
     uint32_t num_ref_franes_in_pic_order_cnt_cycle;
-    reader.get_uvlc(&num_ref_franes_in_pic_order_cnt_cycle);
+    if (!reader.get_uvlc(&num_ref_franes_in_pic_order_cnt_cycle)) { return invalidUVLC; }
     for (uint32_t i = 0; i < num_ref_franes_in_pic_order_cnt_cycle; i++) {
-      reader.get_uvlc(&value);
+      if (!reader.get_uvlc(&value)) { return invalidUVLC; }
     }
   }

-  reader.get_uvlc(&value); // num_ref_frames
+  if (!reader.get_uvlc(&value)) { return invalidUVLC; } // num_ref_frames
   reader.skip_bits(1);

   uint32_t pic_width_in_mbs_minus1;
   uint32_t pic_height_in_mbs_minus1;
-  reader.get_uvlc(&pic_width_in_mbs_minus1);
-  reader.get_uvlc(&pic_height_in_mbs_minus1);
+  if (!reader.get_uvlc(&pic_width_in_mbs_minus1) ||
+      !reader.get_uvlc(&pic_height_in_mbs_minus1)) {
+    return invalidUVLC;
+  }

   *width = (pic_width_in_mbs_minus1 + 1) * 16;
   *height = (pic_height_in_mbs_minus1 + 1) * 16;
@@ -455,10 +457,12 @@ Error parse_sps_for_avcC_configuration(const uint8_t* sps, size_t size,
   uint32_t frame_cropping_flag = reader.get_bits(1);
   if (frame_cropping_flag) {
     uint32_t left, right, top, bottom;
-    reader.get_uvlc(&left);
-    reader.get_uvlc(&right);
-    reader.get_uvlc(&top);
-    reader.get_uvlc(&bottom);
+    if (!reader.get_uvlc(&left) ||
+        !reader.get_uvlc(&right) ||
+        !reader.get_uvlc(&top) ||
+        !reader.get_uvlc(&bottom)) {
+      return invalidUVLC;
+    }

     *width -= left + right;
     *height -= top + bottom;
diff --git a/libheif/codecs/hevc_boxes.cc b/libheif/codecs/hevc_boxes.cc
index 9ca1f111..0ff74e89 100644
--- a/libheif/codecs/hevc_boxes.cc
+++ b/libheif/codecs/hevc_boxes.cc
@@ -658,18 +658,27 @@ Error parse_sps_for_hvcC_configuration(const uint8_t* sps, size_t size,

   // --- SPS continued ---

-  uint32_t dummy, value;
-  reader.get_uvlc(&dummy); // skip seq_parameter_seq_id
+  Error invalidUVLC{
+    heif_error_Invalid_input,
+    heif_suberror_Invalid_parameter_value,
+    "Invalid variable length code in HEVC SPS header"
+  };

-  reader.get_uvlc(&value);
+  uint32_t dummy, value;
+  if (!reader.get_uvlc(&dummy) || // skip seq_parameter_seq_id
+      !reader.get_uvlc(&value)) {
+    return invalidUVLC;
+  }
   config->chroma_format = (uint8_t) value;

   if (config->chroma_format == 3) {
     reader.skip_bits(1);
   }

-  reader.get_uvlc(width);
-  reader.get_uvlc(height);
+  if (!reader.get_uvlc(width) ||
+      !reader.get_uvlc(height)) {
+    return invalidUVLC;
+  }

   if (coded_size) {
     coded_size->width = *width;
@@ -679,10 +688,12 @@ Error parse_sps_for_hvcC_configuration(const uint8_t* sps, size_t size,
   bool conformance_window = reader.get_bits(1);
   if (conformance_window) {
     uint32_t left, right, top, bottom;
-    reader.get_uvlc(&left);
-    reader.get_uvlc(&right);
-    reader.get_uvlc(&top);
-    reader.get_uvlc(&bottom);
+    if (!reader.get_uvlc(&left) ||
+        !reader.get_uvlc(&right) ||
+        !reader.get_uvlc(&top) ||
+        !reader.get_uvlc(&bottom)) {
+      return invalidUVLC;
+    }

     //printf("conformance borders: %u %u %u %u\n",left,right,top,bottom);

@@ -704,7 +715,9 @@ Error parse_sps_for_hvcC_configuration(const uint8_t* sps, size_t size,
     *height -= (uint32_t)crop_h;
   }

-  reader.get_uvlc(&value);
+  if (!reader.get_uvlc(&value)) {
+    return invalidUVLC;
+  }
   if (value > 8) {
     return Error{heif_error_Invalid_input,
                  heif_suberror_Invalid_parameter_value,
@@ -712,7 +725,9 @@ Error parse_sps_for_hvcC_configuration(const uint8_t* sps, size_t size,
   }
   config->bit_depth_luma = (uint8_t) (value + 8);

-  reader.get_uvlc(&value);
+  if (!reader.get_uvlc(&value)) {
+    return invalidUVLC;
+  }
   if (value > 8) {
     return Error{heif_error_Invalid_input,
                  heif_suberror_Invalid_parameter_value,
diff --git a/libheif/codecs/vvc_boxes.cc b/libheif/codecs/vvc_boxes.cc
index 0a531514..9bf300d8 100644
--- a/libheif/codecs/vvc_boxes.cc
+++ b/libheif/codecs/vvc_boxes.cc
@@ -500,14 +500,19 @@ Error parse_sps_for_vvcC_configuration(const uint8_t* sps, size_t size,
     reader.skip_bits(1); // sps_res_change_in_clvs_allowed_flag
   }

+  Error invalidUVLC{
+    heif_error_Invalid_input,
+    heif_suberror_Invalid_parameter_value,
+    "Invalid variable length code in VVC SPS header"
+  };
+
   uint32_t sps_pic_width_max_in_luma_samples;
   uint32_t sps_pic_height_max_in_luma_samples;

-  bool success;
-  success = reader.get_uvlc(&sps_pic_width_max_in_luma_samples);
-  (void)success;
-  success = reader.get_uvlc(&sps_pic_height_max_in_luma_samples);
-  (void)success;
+  if (!reader.get_uvlc(&sps_pic_width_max_in_luma_samples) ||
+      !reader.get_uvlc(&sps_pic_height_max_in_luma_samples)) {
+    return invalidUVLC;
+  }

   *width = sps_pic_width_max_in_luma_samples;
   *height = sps_pic_height_max_in_luma_samples;
@@ -530,10 +535,12 @@ Error parse_sps_for_vvcC_configuration(const uint8_t* sps, size_t size,
   int sps_conformance_window_flag = reader.get_bits(1);
   if (sps_conformance_window_flag) {
     uint32_t left, right, top, bottom;
-    reader.get_uvlc(&left);
-    reader.get_uvlc(&right);
-    reader.get_uvlc(&top);
-    reader.get_uvlc(&bottom);
+    if (!reader.get_uvlc(&left) ||
+        !reader.get_uvlc(&right) ||
+        !reader.get_uvlc(&top) ||
+        !reader.get_uvlc(&bottom)) {
+      return invalidUVLC;
+    }

     // SubWidthC / SubHeightC per ITU-T H.266 Table 5-1, indexed by chroma_format_idc.
     uint32_t subWidthC = 1, subHeightC = 1;
@@ -560,8 +567,9 @@ Error parse_sps_for_vvcC_configuration(const uint8_t* sps, size_t size,
   }

   uint32_t bitDepth_minus8;
-  success = reader.get_uvlc(&bitDepth_minus8);
-  (void)success;
+  if (!reader.get_uvlc(&bitDepth_minus8)) {
+    return invalidUVLC;
+  }

   if (bitDepth_minus8 > 0xFF - 8) {
     return {heif_error_Encoding_error, heif_suberror_Unspecified, "VCC bit depth out of range."};
diff --git a/libheif/plugins/decoder_webcodecs.cc b/libheif/plugins/decoder_webcodecs.cc
index 692180c2..bda1e562 100644
--- a/libheif/plugins/decoder_webcodecs.cc
+++ b/libheif/plugins/decoder_webcodecs.cc
@@ -269,26 +269,37 @@ Error parse_sps_for_hvcC_configuration2(const uint8_t* sps, size_t size,

   // --- SPS continued ---

-  uint32_t dummy, value;
-  reader.get_uvlc(&dummy); // skip seq_parameter_seq_id
+  Error invalidUVLC{
+    heif_error_Invalid_input,
+    heif_suberror_Invalid_parameter_value,
+    "Invalid variable length code in HEVC SPS header"
+  };

-  reader.get_uvlc(&value);
+  uint32_t dummy, value;
+  if (!reader.get_uvlc(&dummy) || // skip seq_parameter_seq_id
+      !reader.get_uvlc(&value)) {
+    return invalidUVLC;
+  }
   config->chroma_format = (uint8_t) value;

   if (config->chroma_format == 3) {
     reader.skip_bits(1);
   }

-  reader.get_uvlc(width);
-  reader.get_uvlc(height);
+  if (!reader.get_uvlc(width) ||
+      !reader.get_uvlc(height)) {
+    return invalidUVLC;
+  }

   bool conformance_window = reader.get_bits(1);
   if (conformance_window) {
     uint32_t left, right, top, bottom;
-    reader.get_uvlc(&left);
-    reader.get_uvlc(&right);
-    reader.get_uvlc(&top);
-    reader.get_uvlc(&bottom);
+    if (!reader.get_uvlc(&left) ||
+        !reader.get_uvlc(&right) ||
+        !reader.get_uvlc(&top) ||
+        !reader.get_uvlc(&bottom)) {
+      return invalidUVLC;
+    }

     //printf("conformance borders: %u %u %u %u\n",left,right,top,bottom);

@@ -310,7 +321,9 @@ Error parse_sps_for_hvcC_configuration2(const uint8_t* sps, size_t size,
     *height -= (uint32_t)crop_h;
   }

-  reader.get_uvlc(&value);
+  if (!reader.get_uvlc(&value)) {
+    return invalidUVLC;
+  }
   if (value > 8) {
     return Error{heif_error_Invalid_input,
                  heif_suberror_Invalid_parameter_value,
@@ -318,7 +331,9 @@ Error parse_sps_for_hvcC_configuration2(const uint8_t* sps, size_t size,
   }
   config->bit_depth_luma = (uint8_t) (value + 8);

-  reader.get_uvlc(&value);
+  if (!reader.get_uvlc(&value)) {
+    return invalidUVLC;
+  }
   if (value > 8) {
     return Error{heif_error_Invalid_input,
                  heif_suberror_Invalid_parameter_value,