Commit 4bf902df for libheif

commit 4bf902dfec3ac89a2bd92c2c364137bc3c974a40
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Fri Mar 27 16:26:50 2026 +0100

    fix: Null pointer dereference in HeifFile::get_item_data() via crafted HEIF file with non-pict handler type

diff --git a/libheif/file.cc b/libheif/file.cc
index 3800e83b..f4c70dd9 100644
--- a/libheif/file.cc
+++ b/libheif/file.cc
@@ -471,41 +471,37 @@ Error HeifFile::parse_heif_images()
   }


-  if (m_hdlr_box &&
-      m_hdlr_box->get_handler_type() != fourcc("pict")) {
-    return {};
-  }
-
-
-  // --- find mandatory boxes needed for image decoding
+  if (has_images()) {
+    // --- find mandatory boxes needed for image decoding

-  m_pitm_box = m_meta_box->get_child_box<Box_pitm>();
-  if (!m_pitm_box) {
-    return Error(heif_error_Invalid_input,
-                 heif_suberror_No_pitm_box);
-  }
+    m_pitm_box = m_meta_box->get_child_box<Box_pitm>();
+    if (!m_pitm_box) {
+      return Error(heif_error_Invalid_input,
+                   heif_suberror_No_pitm_box);
+    }

-  m_iprp_box = m_meta_box->get_child_box<Box_iprp>();
-  if (!m_iprp_box) {
-    return Error(heif_error_Invalid_input,
-                 heif_suberror_No_iprp_box);
-  }
+    m_iprp_box = m_meta_box->get_child_box<Box_iprp>();
+    if (!m_iprp_box) {
+      return Error(heif_error_Invalid_input,
+                   heif_suberror_No_iprp_box);
+    }

-  m_ipco_box = m_iprp_box->get_child_box<Box_ipco>();
-  if (!m_ipco_box) {
-    return Error(heif_error_Invalid_input,
-                 heif_suberror_No_ipco_box);
-  }
+    m_ipco_box = m_iprp_box->get_child_box<Box_ipco>();
+    if (!m_ipco_box) {
+      return Error(heif_error_Invalid_input,
+                   heif_suberror_No_ipco_box);
+    }

-  auto ipma_boxes = m_iprp_box->get_child_boxes<Box_ipma>();
-  if (ipma_boxes.empty()) {
-    return Error(heif_error_Invalid_input,
-                 heif_suberror_No_ipma_box);
-  }
-  for (size_t i=1;i<ipma_boxes.size();i++) {
-    ipma_boxes[0]->insert_entries_from_other_ipma_box(*ipma_boxes[i]);
+    auto ipma_boxes = m_iprp_box->get_child_boxes<Box_ipma>();
+    if (ipma_boxes.empty()) {
+      return Error(heif_error_Invalid_input,
+                   heif_suberror_No_ipma_box);
+    }
+    for (size_t i=1;i<ipma_boxes.size();i++) {
+      ipma_boxes[0]->insert_entries_from_other_ipma_box(*ipma_boxes[i]);
+    }
+    m_ipma_box = ipma_boxes[0];
   }
-  m_ipma_box = ipma_boxes[0];

   m_iloc_box = m_meta_box->get_child_box<Box_iloc>();
   if (!m_iloc_box) {
@@ -516,7 +512,7 @@ Error HeifFile::parse_heif_images()
   m_idat_box = m_meta_box->get_child_box<Box_idat>();

   m_iref_box = m_meta_box->get_child_box<Box_iref>();
-  if (m_iref_box) {
+  if (m_iref_box && m_pitm_box) {
     Error error = check_for_ref_cycle(get_primary_image_ID(), m_iref_box);
     if (error) {
       return error;
@@ -644,6 +640,10 @@ Result<std::vector<uint8_t>> HeifFile::get_uncompressed_item_data(heif_item_id I
   // std::lock_guard<std::mutex> guard(m_read_mutex);   // TODO: I think that this is not needed anymore because this function is not used for image data anymore.
 #endif

+  if (!m_iloc_box) {
+    return Error(heif_error_Invalid_input, heif_suberror_No_iloc_box);
+  }
+
   if (!item_exists(ID)) {
     return Error(heif_error_Usage_error,
                  heif_suberror_Nonexisting_item_referenced);
@@ -748,6 +748,10 @@ Error HeifFile::append_data_from_file_range(std::vector<uint8_t>& out_data, uint

 Error HeifFile::append_data_from_iloc(heif_item_id ID, std::vector<uint8_t>& out_data, uint64_t offset, uint64_t size) const
 {
+  if (!m_iloc_box) {
+    return Error(heif_error_Invalid_input, heif_suberror_No_iloc_box);
+  }
+
   const auto& items = m_iloc_box->get_items();
   const Box_iloc::Item* item = nullptr;
   for (const auto& i : items) {
@@ -775,6 +779,10 @@ Result<std::vector<uint8_t>> HeifFile::get_item_data(heif_item_id ID, heif_metad

   assert(m_limits);

+  if (!m_iloc_box) {
+    return Error(heif_error_Invalid_input, heif_suberror_No_iloc_box);
+  }
+
   auto infe_box = get_infe_box(ID);
   if (!infe_box) {
     return Error{heif_error_Usage_error,
diff --git a/libheif/file.h b/libheif/file.h
index a76bc962..4790a364 100644
--- a/libheif/file.h
+++ b/libheif/file.h
@@ -270,16 +270,16 @@ private:
   std::shared_ptr<Box_mini> m_mini_box; // meta alternative
 #endif

-  std::shared_ptr<Box_ipco> m_ipco_box;
-  std::shared_ptr<Box_ipma> m_ipma_box;
   std::shared_ptr<Box_iloc> m_iloc_box;
   std::shared_ptr<Box_idat> m_idat_box;
   std::shared_ptr<Box_iref> m_iref_box;
-  std::shared_ptr<Box_pitm> m_pitm_box;
   std::shared_ptr<Box_iinf> m_iinf_box;
   std::shared_ptr<Box_grpl> m_grpl_box;
+  std::shared_ptr<Box_pitm> m_pitm_box; // only non-null if has_images()==true
+  std::shared_ptr<Box_iprp> m_iprp_box; // only non-null if has_images()==true
+  std::shared_ptr<Box_ipco> m_ipco_box; // only non-null if has_images()==true
+  std::shared_ptr<Box_ipma> m_ipma_box; // only non-null if has_images()==true

-  std::shared_ptr<Box_iprp> m_iprp_box;

   std::map<heif_item_id, std::shared_ptr<Box_infe> > m_infe_boxes;