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);