Commit 9ee1fab2 for libheif
commit 9ee1fab22871aa17d907b72cf796a5dcc3a847ef
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sat Sep 19 17:31:10 2026 +0200
Avoid a division in the 'pclr' entry bound to satisfy clang-analyzer
The clang-tidy CI job flagged the num_entries bound added in ba47dddc as a
possible division by zero. The analyzer does not model the size of
m_bitDepths after push_back, so it takes a path where the range-for loop
that accumulates bytes_per_entry runs zero times. In practice the divisor
is always at least 1 because NPC == 0 is rejected before the loop.
Compare num_entries * bytes_per_entry against the remaining bytes instead.
num_entries is a uint16_t and bytes_per_entry is at most 255 * 2, so the
product cannot overflow.
diff --git a/libheif/codecs/jpeg2000_boxes.cc b/libheif/codecs/jpeg2000_boxes.cc
index 739be4b0..ba7458e5 100644
--- a/libheif/codecs/jpeg2000_boxes.cc
+++ b/libheif/codecs/jpeg2000_boxes.cc
@@ -215,13 +215,15 @@ Error Box_pclr::parse(BitstreamRange& range, const heif_security_limits* limits)
// padded to a whole number of bytes (I.5.3.4). Used to bound num_entries by
// the data actually present, so a small header cannot force a large
// allocation (analogous to the 'cdef'/'j2kL' checks). The precision is at
- // least 1 bit, so every entry occupies at least one byte.
+ // least 1 bit, so every entry occupies at least one byte and the bound is
+ // never vacuous. num_entries is a uint16_t and bytes_per_entry is at most
+ // 255 * 2, so the product cannot overflow.
size_t bytes_per_entry = 0;
for (uint8_t bd : m_bitDepths) {
bytes_per_entry += (bd + 7) / 8;
}
- if (num_entries > range.get_remaining_bytes() / bytes_per_entry) {
+ if (static_cast<size_t>(num_entries) * bytes_per_entry > range.get_remaining_bytes()) {
return Error(heif_error_Invalid_input,
heif_suberror_End_of_data,
"pclr box declares more entries than the box contains");