Commit 3d4b5022 for libheif
commit 3d4b5022381c50e29838f9b32a433ed1c9f616cf
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sun Dec 28 11:23:00 2025 +0100
also follow 'auxl' links when checking for cyclic references
diff --git a/libheif/box.cc b/libheif/box.cc
index ed38b3a9..f4467f9d 100644
--- a/libheif/box.cc
+++ b/libheif/box.cc
@@ -3719,14 +3719,27 @@ Error Box_iref::parse(BitstreamRange& range, const heif_security_limits* limits)
// --- check for cyclic references
for (const auto& ref : m_references) {
- if (ref.header.get_short_type() != fourcc("dimg")) {
+ if (ref.header.get_short_type() != fourcc("dimg") &&
+ ref.header.get_short_type() != fourcc("auxl")) {
continue;
}
std::set<heif_item_id> reached_ids; // IDs that we have already reached in the DAG
std::set<heif_item_id> todo; // IDs that still need to be followed
- todo.insert(ref.from_item_ID); // start at base item
+ bool reverse = (ref.header.get_short_type() != fourcc("auxl"));
+
+ if (!reverse) {
+ todo.insert(ref.from_item_ID); // start at base item
+ }
+ else {
+ if (ref.to_item_ID.empty()) {
+ continue;
+ }
+
+ // TODO: what if aux image is assigned to multiple images?
+ todo.insert(ref.to_item_ID[0]); // start at base item
+ }
while (!todo.empty()) {
// transfer ID into set of reached IDs
@@ -3737,20 +3750,37 @@ Error Box_iref::parse(BitstreamRange& range, const heif_security_limits* limits)
// if this ID refers to another 'iref', follow it
for (const auto& succ_ref : m_references) {
- if (succ_ref.header.get_short_type() != fourcc("dimg")) {
+ if (succ_ref.header.get_short_type() != fourcc("dimg") &&
+ succ_ref.header.get_short_type() != fourcc("auxl")) {
continue;
}
- if (succ_ref.from_item_ID == id) {
+ heif_item_id from;
+ std::vector<heif_item_id> to;
+
+ if (succ_ref.header.get_short_type() == fourcc("auxl")) {
+ if (succ_ref.to_item_ID.empty()) {
+ continue;
+ }
+
+ from = succ_ref.to_item_ID[0];
+ to = {succ_ref.from_item_ID};
+ }
+ else {
+ from = succ_ref.from_item_ID;
+ to = succ_ref.to_item_ID;
+ }
+
+ if (from == id) {
// Check whether any successor IDs has been visited yet, which would be an error.
// Otherwise, put that ID into the 'todo' set.
- for (const auto& succ_ref_id : succ_ref.to_item_ID) {
+ for (const auto& succ_ref_id : to) {
if (reached_ids.find(succ_ref_id) != reached_ids.end()) {
return Error(heif_error_Invalid_input,
heif_suberror_Unspecified,
- "'iref' has cyclic 'dimg' references");
+ "'iref' has cyclic references");
}
todo.insert(succ_ref_id);