Commit 748656fb for libheif
commit 748656fb74e3ed60e2a1a429574af9b2cb15e63c
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Thu Aug 27 02:53:12 2026 +0200
make Result<T> and Error operator bool explicit
An implicit operator bool() lets `id = result;` and `return err;` from an
int-returning function compile silently and yield 0/1. This is the root cause of
the bug fixed piecemeal in #1885 (and twice before): three item writers stored
the boolean value of a Result<heif_item_id> instead of the ID.
With 'explicit', only contextual conversions (if/!/&&/assert) compile. Rebuilding
all targets flagged the remaining copies of the bug, fixed here:
- heif_context_add_pyramid_entity_group stored `*out_group_id = result;` and
always reported group ID 1.
- ImageItem::get_luma_bits_per_pixel / get_chroma_bits_per_pixel returned
`decoderResult.error()`, i.e. 1 instead of the documented -1.
diff --git a/libheif/api/libheif/heif_experimental.cc b/libheif/api/libheif/heif_experimental.cc
index e83a0301..0dc96df2 100644
--- a/libheif/api/libheif/heif_experimental.cc
+++ b/libheif/api/libheif/heif_experimental.cc
@@ -286,7 +286,7 @@ heif_error heif_context_add_pyramid_entity_group(struct heif_context* ctx,
if (result) {
if (out_group_id) {
- *out_group_id = result;
+ *out_group_id = *result;
}
return heif_error_success;
}
diff --git a/libheif/error.h b/libheif/error.h
index 607605e0..2ea36f4d 100644
--- a/libheif/error.h
+++ b/libheif/error.h
@@ -111,7 +111,10 @@ public:
}
}
- operator bool() const { return error_code != heif_error_Ok; }
+ // 'explicit' so that an Error can only be tested in a boolean context (if/!/&&/...).
+ // Without it, `int x = err;` or `return err;` from an int function silently compile
+ // and yield 0/1 instead of the intended value.
+ explicit operator bool() const { return error_code != heif_error_Ok; }
static const char* get_error_string(heif_error_code err);
@@ -137,7 +140,11 @@ public:
Result(const Error& e) : m_data(e) {}
- operator bool() const { return std::holds_alternative<T>(m_data); }
+ // True if the Result holds a value, false if it holds an error.
+ // 'explicit' so that the value can only be extracted with operator*: `id = result;` must
+ // not compile, because it would store the boolean (this bug shipped several times, see
+ // https://github.com/strukturag/libheif/pull/1885).
+ explicit operator bool() const { return std::holds_alternative<T>(m_data); }
//void set(const T& v) { m_data = v; }
diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc
index d5624bab..98f76f61 100644
--- a/libheif/image-items/image_item.cc
+++ b/libheif/image-items/image_item.cc
@@ -523,7 +523,7 @@ int ImageItem::get_luma_bits_per_pixel() const
{
auto decoderResult = get_decoder();
if (!decoderResult) {
- return decoderResult.error();
+ return -1;
}
auto decoder = *decoderResult;
@@ -536,7 +536,7 @@ int ImageItem::get_chroma_bits_per_pixel() const
{
auto decoderResult = get_decoder();
if (!decoderResult) {
- return decoderResult.error();
+ return -1;
}
auto decoder = *decoderResult;