Commit abc39f61 for libheif
commit abc39f6121805dd7eeee03cf90d2ea911775aedf
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sun Oct 25 17:04:40 2026 +0100
Avoid re-adding color profiles while reading HEIF files [GHSA-hhg3-fxg7-3gxw]
diff --git a/libheif/context.cc b/libheif/context.cc
index f3cad89f..623634ed 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -786,8 +786,16 @@ Error HeifContext::interpret_heif_file_images()
for (const auto& prop : properties) {
auto colr = std::dynamic_pointer_cast<Box_colr>(prop);
if (colr) {
+ // The ImageItem color-profile setters also add 'colr' properties for
+ // encoding. On read, only populate the description: this property is
+ // already associated with the item in the file.
auto profile = colr->get_color_profile();
- image->set_color_profile(profile);
+ if (auto icc = std::dynamic_pointer_cast<const color_profile_raw>(profile)) {
+ image->ImageDescription::set_color_profile_icc(icc);
+ }
+ else if (auto nclx = std::dynamic_pointer_cast<const color_profile_nclx>(profile)) {
+ image->ImageDescription::set_color_profile_nclx(nclx->get_nclx_color_profile());
+ }
continue;
}
@@ -1109,11 +1117,11 @@ Error HeifContext::interpret_heif_file_images()
auto tile_img = iter->second;
if (image->get_color_profile_icc() == nullptr && tile_img->get_color_profile_icc()) {
- image->set_color_profile(tile_img->get_color_profile_icc());
+ image->ImageDescription::set_color_profile_icc(tile_img->get_color_profile_icc());
}
if (!image->has_nclx_color_profile() && tile_img->has_nclx_color_profile()) {
- image->set_color_profile_nclx(tile_img->get_color_profile_nclx());
+ image->ImageDescription::set_color_profile_nclx(tile_img->get_color_profile_nclx());
}
}
}
diff --git a/libheif/image/image_description.h b/libheif/image/image_description.h
index 9c2c8180..d3e5a6d2 100644
--- a/libheif/image/image_description.h
+++ b/libheif/image/image_description.h
@@ -184,6 +184,9 @@ public:
const std::shared_ptr<const color_profile_raw>& get_color_profile_icc() const { return m_color_profile_icc; }
+ // This wrapper calls the virtual setters. On an ImageItem, those setters
+ // also add 'colr' properties for encoding. When reading an existing 'colr'
+ // property, use the qualified ImageDescription setters instead.
void set_color_profile(const std::shared_ptr<const color_profile>& profile)
{
auto icc = std::dynamic_pointer_cast<const color_profile_raw>(profile);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 98bd28dc..10f0e2dc 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -79,6 +79,7 @@ add_libheif_test(sdtp_sample_limit)
add_libheif_test(hevc_brands)
add_libheif_test(file_layout)
add_libheif_test(image_description_metadata)
+ add_libheif_test(read_color_profile_properties)
add_libheif_test(exception_guard)
# decompression_bomb builds the bomb payload with the library-internal
diff --git a/tests/read_color_profile_properties.cc b/tests/read_color_profile_properties.cc
new file mode 100644
index 00000000..6ed16a70
--- /dev/null
+++ b/tests/read_color_profile_properties.cc
@@ -0,0 +1,48 @@
+/*
+ libheif unit tests
+
+ MIT License
+
+ Copyright (c) 2026 Dirk Farin <dirk.farin@gmail.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#include "catch_amalgamated.hpp"
+#include "context.h"
+#include "image-items/image_item.h"
+#include "test-config.h"
+
+
+TEST_CASE("reading a file does not add color profile properties")
+{
+ // This file associates one nclx 'colr' property with its primary item.
+ HeifContext ctx;
+ Error err = ctx.read_from_file((tests_data_directory + "/clap_cropped.avif").c_str());
+ INFO("read error: " << err.message);
+ REQUIRE(!err);
+
+ auto image = ctx.get_primary_image(false);
+ REQUIRE(image);
+ REQUIRE(image->get_all_properties<Box_colr>().size() == 1);
+
+ // Reading still assigns the profile to the image description.
+ REQUIRE(image->has_nclx_color_profile());
+ REQUIRE(image->get_color_profile_icc() == nullptr);
+}