Commit 7538a4f3 for libheif

commit 7538a4f3f13a26a948f083610016e527f9b12fb5
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Sat Sep 5 21:54:15 2026 +0200

    Cap the number of 'iref' reference entries to max_items

    Box_iref::parse capped only the per-entry reference count (nRefs), not the total number of entries, so the entry count was bounded only by the file size. Add a total-entry cap against max_items, matching the item-count caps already applied in Box_iloc, Box_iinf and Box_ipma.

    This is a consistency limit, not a security fix: with the reference-cycle recursion removed (GHSA-xrp2-63fq-jm8q), a large 'iref' is only a linear, file-bounded allocation, not an amplification. The cap rejects a pathological box early with a clear error instead of parsing it in full.

diff --git a/libheif/box.cc b/libheif/box.cc
index d3bdb580..504e26e6 100644
--- a/libheif/box.cc
+++ b/libheif/box.cc
@@ -3978,6 +3978,29 @@ Error Box_iref::parse(BitstreamRange& range, const heif_security_limits* limits)
   }

   while (!range.eof()) {
+    // Cap the total number of reference entries, matching the item-count caps in
+    // Box_iloc/Box_iinf/Box_ipma (and the per-entry nRefs cap below). Without it
+    // the entry count is bounded only by the file size. That is a linear,
+    // file-bounded allocation rather than an amplification, so this is a
+    // consistency limit and not a security fix, but it rejects a pathological
+    // 'iref' early with a clear error instead of parsing it in full.
+    //
+    // max_items is a heuristic ceiling here, not a semantically exact bound: the
+    // number of entries is not strictly limited by the number of items, because
+    // one item may be the source (from_item_ID) of several entries, one per
+    // reference type (e.g. 'dimg', 'thmb', 'cdsc'). A well-formed file stays far
+    // below max_items (default 1000) regardless, so the generous ceiling is fine
+    // as a sanity limit; raise max_items if a legitimate file ever exceeds it.
+    if (limits->max_items && m_references.size() >= limits->max_items) {
+      std::stringstream sstr;
+      sstr << "'iref' box contains more than " << limits->max_items
+           << " reference entries, which exceeds the security limit.";
+
+      return {heif_error_Invalid_input,
+              heif_suberror_Security_limit_exceeded,
+              sstr.str()};
+    }
+
     Reference ref;

     Error err = ref.header.parse_header(range);