Commit b453ecc0 for libheif

commit b453ecc023a069ec2692b6e428123fd89967cee8
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Thu Jul 2 12:19:14 2026 +0200

    Fix bisect_filesize integer overflow when probing file size (#1857)

    StreamReader_CApi::bisect_filesize() computed its probe position as
    (mini + maxi) / 2, which overflows uint64_t when 'maxi' is large. This
    path is now reachable because file_layout.cc resolves a 'meta' box of
    size 0 by calling request_range(start, UINT64_MAX) to obtain the file
    size, and the version-1 reader fallback bisects the size.

    Two problems are fixed:

    - Use the overflow-safe midpoint mini + (maxi - mini) / 2.

    - wait_for_file_size() takes a signed int64_t. Probing a position beyond
      INT64_MAX wraps to a negative value, which a reader compares as "below
      the file size" and reports as size_reached, driving the search to a
      bogus multi-exabyte result. Clamp the probe range to INT64_MAX (no file
      handled through this API can be larger) so both the initial
      wait_for_file_size() call and the bisection stay in the valid range.

    Behaviour is unchanged for all existing callers, which pass an end
    position well below INT64_MAX.

diff --git a/libheif/bitstream.h b/libheif/bitstream.h
index c04de251..da6acf1e 100644
--- a/libheif/bitstream.h
+++ b/libheif/bitstream.h
@@ -206,13 +206,20 @@ public:
       }
     }
     else {
-      auto result = m_func_table->wait_for_file_size(end_pos, m_userdata);
+      // wait_for_file_size() takes a signed int64_t, so we cannot probe a position
+      // beyond INT64_MAX: it would wrap to a negative value and the reader would
+      // misreport the size. No file accessed through this API can be that large,
+      // so clamp the search range to INT64_MAX. (Callers may pass UINT64_MAX to
+      // ask for the total file size.)
+      uint64_t hi = std::min<uint64_t>(end_pos, std::numeric_limits<int64_t>::max());
+
+      auto result = m_func_table->wait_for_file_size(static_cast<int64_t>(hi), m_userdata);
       if (result == heif_reader_grow_status_size_reached) {
-        return end_pos;
+        return hi;
       }
       else {
         uint64_t pos = m_func_table->get_position(m_userdata);
-        return bisect_filesize(pos,end_pos);
+        return bisect_filesize(pos, hi);
       }
     }
   }
@@ -225,8 +232,10 @@ public:
       return mini;
     }

-    uint64_t pos = (mini + maxi) / 2;
-    auto result = m_func_table->wait_for_file_size(pos, m_userdata);
+    // Overflow-safe midpoint. 'maxi' is bounded by INT64_MAX (see request_range),
+    // but computing (mini + maxi) directly could still overflow uint64_t.
+    uint64_t pos = mini + (maxi - mini) / 2;
+    auto result = m_func_table->wait_for_file_size(static_cast<int64_t>(pos), m_userdata);
     if (result == heif_reader_grow_status_size_reached) {
       return bisect_filesize(pos, maxi);
     }