From 9ddad1676718f8c12f72a8ac7357552586f1a9a7 Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Thu, 14 May 2026 14:53:29 +0200 Subject: [PATCH] Improve size limits for AVIF, HEIF, and RAW plugins --- README.md | 7 ++++--- src/imageformats/avif.cpp | 16 +++++++++++++--- src/imageformats/heif.cpp | 22 ++++++++++++++++++++-- src/imageformats/pcx.cpp | 4 ++-- src/imageformats/raw.cpp | 6 +++--- src/imageformats/util_p.h | 8 ++++++++ 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d27d796..86dadff 100644 --- a/README.md +++ b/README.md @@ -248,18 +248,19 @@ Anyway, all plugins are also limited by the > [!note] > You can change the maximum limit of 300000 pixels by setting the constant -> `KIF_LARGE_IMAGE_PIXEL_LIMIT` to the desired value in the cmake file. +> `KIF_LARGE_IMAGE_PIXEL_LIMIT` to the desired value in the cmake file. It +> cannot be less than 65536. Below are the maximum sizes for each plugin ('n/a' means no limit, i.e. the limit depends on the format encoding). -- ANI: n/a +- ANI: same size as Qt's ICO plugin - AVIF: 32,768 x 32,768 pixels, in any case no larger than 256 megapixels - DDS: 300,000 x 300,000 pixels - EXR: 300,000 x 300,000 pixels - EPS: same size as Qt's JPG plugin - FF: 300,000 x 300,000 pixels - HDR: 300,000 x 300,000 pixels -- HEIF: n/a +- HEIF: 65,535 x 65,535 pixels - IFF: 65,535 x 65,535 pixels - JP2: 300,000 x 300,000 pixels, in any case no larger than 2 gigapixels - JXL: 262,144 x 262,144 pixels, in any case no larger than 256 megapixels diff --git a/src/imageformats/avif.cpp b/src/imageformats/avif.cpp index 04f3f77..3a55657 100644 --- a/src/imageformats/avif.cpp +++ b/src/imageformats/avif.cpp @@ -49,6 +49,16 @@ Quality range - compression/subsampling #define KIMG_AVIF_QUALITY_LOW 51 #endif +/* *** AVIF_MAX_IMAGE_WIDTH and AVIF_MAX_IMAGE_HEIGHT *** + * The maximum size in pixel allowed by the plugin. + */ +#ifndef AVIF_MAX_IMAGE_WIDTH +#define AVIF_MAX_IMAGE_WIDTH KIF_64K_IMAGE_PIXEL_LIMIT +#endif +#ifndef AVIF_MAX_IMAGE_HEIGHT +#define AVIF_MAX_IMAGE_HEIGHT AVIF_MAX_IMAGE_WIDTH +#endif + QAVIFHandler::QAVIFHandler() : m_parseState(ParseAvifNotParsed) , m_quality(KIMG_AVIF_DEFAULT_QUALITY) @@ -168,7 +178,7 @@ bool QAVIFHandler::ensureDecoder() #endif #if AVIF_VERSION >= 110000 - m_decoder->imageDimensionLimit = 65535; + m_decoder->imageDimensionLimit = std::max(AVIF_MAX_IMAGE_WIDTH, AVIF_MAX_IMAGE_HEIGHT) - 1; #endif avifResult decodeResult; @@ -196,7 +206,7 @@ bool QAVIFHandler::ensureDecoder() m_container_width = m_decoder->image->width; m_container_height = m_decoder->image->height; - if ((m_container_width > 65535) || (m_container_height > 65535)) { + if ((m_container_width >= AVIF_MAX_IMAGE_WIDTH) || (m_container_height >= AVIF_MAX_IMAGE_HEIGHT)) { qCWarning(LOG_AVIFPLUGIN, "AVIF image (%dx%d) is too large!", m_container_width, m_container_height); m_parseState = ParseAvifError; return false; @@ -605,7 +615,7 @@ bool QAVIFHandler::write(const QImage &image) } if ((image.width() > 0) && (image.height() > 0)) { - if ((image.width() > 65535) || (image.height() > 65535)) { + if ((image.width() >= AVIF_MAX_IMAGE_WIDTH) || (image.height() >= AVIF_MAX_IMAGE_HEIGHT)) { qCWarning(LOG_AVIFPLUGIN, "Image (%dx%d) is too large to save!", image.width(), image.height()); return false; } diff --git a/src/imageformats/heif.cpp b/src/imageformats/heif.cpp index 922a644..8f4c9d4 100644 --- a/src/imageformats/heif.cpp +++ b/src/imageformats/heif.cpp @@ -46,6 +46,16 @@ Q_LOGGING_CATEGORY(LOG_HEIFPLUGIN, "kf.imageformats.plugins.heif", QtWarningMsg) // #define HEIF_DISABLE_QT_TRANSFORMATION #endif +/* *** HEIF_MAX_IMAGE_WIDTH and HEIF_MAX_IMAGE_HEIGHT *** + * The maximum size in pixel allowed by the plugin. + */ +#ifndef HEIF_MAX_IMAGE_WIDTH +#define HEIF_MAX_IMAGE_WIDTH KIF_64K_IMAGE_PIXEL_LIMIT +#endif +#ifndef HEIF_MAX_IMAGE_HEIGHT +#define HEIF_MAX_IMAGE_HEIGHT HEIF_MAX_IMAGE_WIDTH +#endif + size_t HEIFHandler::m_initialized_count = 0; bool HEIFHandler::m_plugins_queried = false; bool HEIFHandler::m_heif_decoder_available = false; @@ -137,6 +147,11 @@ bool HEIFHandler::write(const QImage &image) return false; } + if (image.width() >= HEIF_MAX_IMAGE_WIDTH || image.height() >= HEIF_MAX_IMAGE_HEIGHT) { + qCWarning(LOG_HEIFPLUGIN) << "Image size invalid:" << image.width() << "x" << image.height(); + return false; + } + startHeifLib(); bool success = write_helper(image); @@ -714,14 +729,17 @@ bool HEIFHandler::ensureDecoder() const int imageWidth = heif_image_get_width(img, heif_channel_interleaved); const int imageHeight = heif_image_get_height(img, heif_channel_interleaved); - QSize imageSize(imageWidth, imageHeight); + QSize imageSize; + if (imageWidth < HEIF_MAX_IMAGE_WIDTH && imageHeight < HEIF_MAX_IMAGE_HEIGHT) { + imageSize = QSize(imageWidth, imageHeight); + } if (!imageSize.isValid()) { heif_image_release(img); heif_image_handle_release(handle); heif_context_free(ctx); m_parseState = ParseHeicError; - qCWarning(LOG_HEIFPLUGIN) << "HEIC image size invalid:" << imageSize; + qCWarning(LOG_HEIFPLUGIN) << "HEIC image size invalid:" << imageWidth << "x" << imageHeight; return false; } diff --git a/src/imageformats/pcx.cpp b/src/imageformats/pcx.cpp index 769129b..af453a3 100644 --- a/src/imageformats/pcx.cpp +++ b/src/imageformats/pcx.cpp @@ -65,11 +65,11 @@ public: inline int width() const { - return (XMax - XMin) + 1; + return int(XMax - XMin) + 1; } inline int height() const { - return (YMax - YMin) + 1; + return int(YMax - YMin) + 1; } inline bool isCompressed() const { diff --git a/src/imageformats/raw.cpp b/src/imageformats/raw.cpp index f1cfcca..fcfbe94 100644 --- a/src/imageformats/raw.cpp +++ b/src/imageformats/raw.cpp @@ -35,7 +35,7 @@ * The maximum size in pixel allowed by the plugin. */ #ifndef RAW_MAX_IMAGE_WIDTH -#define RAW_MAX_IMAGE_WIDTH std::min(65535, KIF_LARGE_IMAGE_PIXEL_LIMIT) +#define RAW_MAX_IMAGE_WIDTH KIF_64K_IMAGE_PIXEL_LIMIT #endif #ifndef RAW_MAX_IMAGE_HEIGHT #define RAW_MAX_IMAGE_HEIGHT RAW_MAX_IMAGE_WIDTH @@ -759,8 +759,8 @@ bool LoadRAW(QImageIOHandler *handler, QImage &img) // *** Limiting the maximum image size on a reasonable size auto size = rawImageSize(rawProcessor.get()); - if (size.width() > RAW_MAX_IMAGE_WIDTH || size.height() > RAW_MAX_IMAGE_HEIGHT) { - qCWarning(LOG_RAWPLUGIN) << "The maximum image size is limited to" << RAW_MAX_IMAGE_WIDTH << "x" << RAW_MAX_IMAGE_HEIGHT << "px"; + if (size.width() >= RAW_MAX_IMAGE_WIDTH || size.height() >= RAW_MAX_IMAGE_HEIGHT) { + qCWarning(LOG_RAWPLUGIN) << "The maximum image size is limited to" << (RAW_MAX_IMAGE_WIDTH - 1) << "x" << (RAW_MAX_IMAGE_HEIGHT - 1) << "px"; return false; } diff --git a/src/imageformats/util_p.h b/src/imageformats/util_p.h index 4dc02ac..24c0d68 100644 --- a/src/imageformats/util_p.h +++ b/src/imageformats/util_p.h @@ -20,6 +20,14 @@ #define KIF_LARGE_IMAGE_PIXEL_LIMIT 300000 #endif +// Maximum size for legacy image formats. +#define KIF_64K_IMAGE_PIXEL_LIMIT 65536 + +#if KIF_LARGE_IMAGE_PIXEL_LIMIT < KIF_64K_IMAGE_PIXEL_LIMIT +#undef KIF_LARGE_IMAGE_PIXEL_LIMIT +#define KIF_LARGE_IMAGE_PIXEL_LIMIT KIF_64K_IMAGE_PIXEL_LIMIT +#endif + // Image metadata keys to use in plugins (so they are consistent) #define META_KEY_ALTITUDE "Altitude" #define META_KEY_AUTHOR "Author"