From f450e5c9a9c31ed0b49f0f6fe3d38b7864013222 Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Fri, 22 May 2026 10:35:22 +0200 Subject: [PATCH] JXR: add a memory allocation barrier in jxrlib --- README.md | 8 +++-- src/imageformats/jxr.cpp | 64 +++++++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 86dadff..5cab81a 100644 --- a/README.md +++ b/README.md @@ -449,8 +449,13 @@ plugin: > [!caution] > The plugin disabled by default due to security issues in [jxrlib](https://github.com/4creators/jxrlib): > the upstream jxrlib is dead and there is no "hope" they will fix the issues. +> > **You should not enable it unless you know what you are doing.** +> [!note] +> Security issues in the jxrlib discovered by the [KImageFormats OSS-Fuzz project](https://github.com/google/oss-fuzz/tree/master/projects/kimageformats) +> should be fixed in this [jxrlib fork](https://github.com/mircomir/jxrlib). + The following defines can be defined in cmake to modify the behavior of the plugin: - `JXR_DENY_FLOAT_IMAGE`: disables the use of float images and consequently @@ -463,9 +468,6 @@ plugin: it only wants (P)BGRA32bpp files (a format not supported by Qt). Only for this format an hack is activated to guarantee total compatibility of the plugin with Windows. -- `JXR_ENABLE_ADVANCED_METADATA`: enable metadata support (e.g. XMP). Some - distributions use an incomplete JXR library that does not allow reading - metadata, causing compilation errors. ### The KRA plugin diff --git a/src/imageformats/jxr.cpp b/src/imageformats/jxr.cpp index 01a12d6..c9473f5 100644 --- a/src/imageformats/jxr.cpp +++ b/src/imageformats/jxr.cpp @@ -43,41 +43,39 @@ Q_LOGGING_CATEGORY(LOG_JXRPLUGIN, "kf.imageformats.plugins.jxr", QtWarningMsg) #endif /*! - * Support for float images + * \brief JXR_DENY_FLOAT_IMAGE * - * NOTE: Float images have values greater than 1 so they need an additional in place conversion. + * When defined, disables the support for float images. + * \note Float images have values greater than 1 so they need an additional in place conversion. */ +#ifndef JXR_DENY_FLOAT_IMAGE // #define JXR_DENY_FLOAT_IMAGE // default commented +#endif /*! - * Remove the needs of additional memory by disabling the conversion between - * different color depths (e.g. RGBA64bpp to RGBA32bpp). + * \brief JXR_DISABLE_DEPTH_CONVERSION * - * NOTE: Leaving deptch conversion enabled (default) ensures maximum read compatibility. + * When defined, removes the needs of additional memory by disabling the conversion between + * different color depths (e.g. RGBA64bpp to RGBA32bpp). + * \note Leaving depth conversion enabled (default) ensures maximum read compatibility. */ +#ifndef JXR_DISABLE_DEPTH_CONVERSION // #define JXR_DISABLE_DEPTH_CONVERSION // default commented +#endif /*! + * \brief JXR_DISABLE_BGRA_HACK + * + * When defined, disables Windows compatibility for BGRs. + * * Windows displays and opens JXR files correctly out of the box. Unfortunately it doesn't * seem to open (P)RGBA @32bpp files as it only wants (P)BGRA32bpp files (a format not supported by Qt). - * Only for this format an hack is activated to guarantee total compatibility of the plugin with Windows. + * Only for this format, an hack is activated to guarantee total compatibility of the plugin with Windows, + * at the cost of some overhead. */ +#ifndef JXR_DISABLE_BGRA_HACK // #define JXR_DISABLE_BGRA_HACK // default commented - -/*! - * The following functions are present in the Debian headers but not in the SUSE ones even if the source version is 1.0.1 on both. - * - * - ERR PKImageDecode_GetXMPMetadata_WMP(PKImageDecode *pID, U8 *pbXMPMetadata, U32 *pcbXMPMetadata); - * - ERR PKImageDecode_GetEXIFMetadata_WMP(PKImageDecode *pID, U8 *pbEXIFMetadata, U32 *pcbEXIFMetadata); - * - ERR PKImageDecode_GetGPSInfoMetadata_WMP(PKImageDecode *pID, U8 *pbGPSInfoMetadata, U32 *pcbGPSInfoMetadata); - * - ERR PKImageDecode_GetIPTCNAAMetadata_WMP(PKImageDecode *pID, U8 *pbIPTCNAAMetadata, U32 *pcbIPTCNAAMetadata); - * - ERR PKImageDecode_GetPhotoshopMetadata_WMP(PKImageDecode *pID, U8 *pbPhotoshopMetadata, U32 *pcbPhotoshopMetadata); - * - * As a result, their use is disabled by default. It is possible to activate their use by defining the - * JXR_ENABLE_ADVANCED_METADATA preprocessor directive - */ - -// #define JXR_ENABLE_ADVANCED_METADATA +#endif /* *** JXR_MAX_IMAGE_WIDTH and JXR_MAX_IMAGE_HEIGHT *** * The maximum size in pixel allowed by the plugin. @@ -89,13 +87,25 @@ Q_LOGGING_CATEGORY(LOG_JXRPLUGIN, "kf.imageformats.plugins.jxr", QtWarningMsg) #define JXR_MAX_IMAGE_HEIGHT JXR_MAX_IMAGE_WIDTH #endif -#ifndef JXR_MAX_METADATA_SIZE /*! - * XMP and EXIF maximum size. + * \brief JXR_MAX_METADATA_SIZE + * + * XMP and EXIF maximum size in bytes. */ +#ifndef JXR_MAX_METADATA_SIZE #define JXR_MAX_METADATA_SIZE (4 * 1024 * 1024) #endif +/* + * Compatibility with older libraries + */ +#ifndef JXR_MAKEVERSION +#define JXR_MAKEVERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch)) +#endif +#ifndef JXR_VERSION +#define JXR_VERSION JXR_MAKEVERSION(1, 1, 0) +#endif + class JXRHandlerPrivate : public QSharedData { private: @@ -461,7 +471,7 @@ public: if (pDecoder == nullptr) { return xmp; } -#ifdef JXR_ENABLE_ADVANCED_METADATA +#if JXR_VERSION >= JXR_MAKEVERSION(1, 4, 0) quint32 size = 0; if (!PKImageDecode_GetXMPMetadata_WMP(pDecoder, nullptr, &size) && size > 0 && size < JXR_MAX_METADATA_SIZE) { QByteArray ba(size, 0); @@ -963,6 +973,12 @@ private: if (pCodecFactory == nullptr) { return false; } + +#if JXR_VERSION >= JXR_MAKEVERSION(1, 4, 0) + // Prevents the library from making single large memory allocations. + // Note that it may still exceed it with multiple allocations. + PKAlloc_SetLimit(size_t(QImageReader::allocationLimit()) * 1024 * 1024); +#endif if (auto err = pCodecFactory->CreateDecoderFromFile(qUtf8Printable(fileName()), &pDecoder)) { qCWarning(LOG_JXRPLUGIN) << "JXRHandlerPrivate::initDecoder() unable to create decoder:" << err; return false;