Commit 0b73cfdf for libheif
commit 0b73cfdf739f4f697cbc166cb1ce871144772d2b
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Mon May 18 22:06:02 2026 +0200
tili: prevent int overflow (thanks to @m1-llie for reporting this)
diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc
index 76718974..688fb09b 100644
--- a/libheif/image-items/image_item.cc
+++ b/libheif/image-items/image_item.cc
@@ -201,9 +201,11 @@ std::shared_ptr<ImageItem> ImageItem::alloc_for_infe_box(HeifContext* ctx, const
else if (item_type == fourcc("iden")) {
return std::make_shared<ImageItem_iden>(ctx, id);
}
+#if HEIF_ENABLE_EXPERIMENTAL_FEATURES
else if (item_type == fourcc("tili")) {
return std::make_shared<ImageItem_Tiled>(ctx, id);
}
+#endif
else {
// This item has an unknown type. It could be an image or anything else.
// Do not process the item.
diff --git a/libheif/image-items/tiled.cc b/libheif/image-items/tiled.cc
index 67768264..217fc2f8 100644
--- a/libheif/image-items/tiled.cc
+++ b/libheif/image-items/tiled.cc
@@ -47,21 +47,22 @@ Result<uint64_t> number_of_tiles(const heif_tiled_image_parameters& params, cons
{
uint64_t nTiles = nTiles_h(params) * static_cast<uint64_t>(nTiles_v(params));
+ // Enforce the limit before the extra-dimensions loop so it is checked
+ // even when number_of_extra_dimensions == 0.
+ if (limits && limits->max_number_of_tiles && nTiles > limits->max_number_of_tiles) {
+ return Error{
+ heif_error_Unsupported_filetype,
+ heif_suberror_Security_limit_exceeded,
+ "Number of tiles exceeds security limit"
+ };
+ }
+
for (int i = 0; i < params.number_of_extra_dimensions; i++) {
// We only support up to 8 extra dimensions
if (i == 8) {
break;
}
- if (params.extra_dimensions[i] != 0 &&
- nTiles > UINT64_MAX / params.extra_dimensions[i]) {
- return Error{
- heif_error_Unsupported_filetype,
- heif_suberror_Unspecified,
- "Number of tiles exceeds uint64 maximum."
- };
- }
-
if (params.extra_dimensions[i] == 0) {
return Error{
heif_error_Unsupported_filetype,
@@ -70,9 +71,17 @@ Result<uint64_t> number_of_tiles(const heif_tiled_image_parameters& params, cons
};
}
+ if (nTiles > UINT64_MAX / params.extra_dimensions[i]) {
+ return Error{
+ heif_error_Unsupported_filetype,
+ heif_suberror_Unspecified,
+ "Number of tiles exceeds uint64 maximum."
+ };
+ }
+
nTiles *= params.extra_dimensions[i];
- if (limits && nTiles > limits->max_number_of_tiles) {
+ if (limits && limits->max_number_of_tiles && nTiles > limits->max_number_of_tiles) {
return Error{
heif_error_Unsupported_filetype,
heif_suberror_Security_limit_exceeded,
@@ -87,13 +96,18 @@ Result<uint64_t> number_of_tiles(const heif_tiled_image_parameters& params, cons
uint32_t nTiles_h(const heif_tiled_image_parameters& params)
{
- return (params.image_width + params.tile_width - 1) / params.tile_width;
+ // 64-bit arithmetic prevents wrap-around when image_width + tile_width - 1
+ // exceeds UINT32_MAX. The quotient is bounded by image_width, so the
+ // narrowing cast is safe. Callers are responsible for ensuring tile_width > 0.
+ return static_cast<uint32_t>(
+ (static_cast<uint64_t>(params.image_width) + params.tile_width - 1) / params.tile_width);
}
uint32_t nTiles_v(const heif_tiled_image_parameters& params)
{
- return (params.image_height + params.tile_height - 1) / params.tile_height;
+ return static_cast<uint32_t>(
+ (static_cast<uint64_t>(params.image_height) + params.tile_height - 1) / params.tile_height);
}