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;