From 7cf60da031f77bb8573ecc8610b8c4f0a5c78741 Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Sun, 19 Apr 2026 20:37:27 +0200 Subject: [PATCH] JXR: fix memory leaks --- autotests/README.md | 2 +- src/imageformats/jxr.cpp | 31 ++++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/autotests/README.md b/autotests/README.md index 36f1c4f..a2e83d0 100644 --- a/autotests/README.md +++ b/autotests/README.md @@ -48,7 +48,7 @@ Depending on the format, you can specify the following additional options. - `--help`: Displays help on commandline options. - `--fuzz `: The fuzziness. Used to add some deviation in ARGB data -(nornally used on lossy codec). +(normally used on lossy codec). - `--perceptive-fuzz`: Used to scale dynamically the fuzziness based on the alpha channel value. This is useful on images with pre-multiplied and small alphas. Qt can use different roundings based on optimizations resulting diff --git a/src/imageformats/jxr.cpp b/src/imageformats/jxr.cpp index 228b787..b78161d 100644 --- a/src/imageformats/jxr.cpp +++ b/src/imageformats/jxr.cpp @@ -123,17 +123,17 @@ public: ~JXRHandlerPrivate() { - if (pCodecFactory) { - PKCreateCodecFactory_Release(&pCodecFactory); - } - if (pFactory) { - PKCreateFactory_Release(&pFactory); - } if (pDecoder) { - PKImageDecode_Release(&pDecoder); + pDecoder->Release(&pDecoder); } if (pEncoder) { - PKImageEncode_Release(&pEncoder); + pEncoder->Release(&pEncoder); + } + if (pCodecFactory) { + pCodecFactory->Release(&pCodecFactory); + } + if (pFactory) { + pFactory->Release(&pFactory); } } @@ -556,7 +556,11 @@ public: if (device == nullptr || pEncoder == nullptr) { return false; } - if (auto err = PKImageEncode_Release(&pEncoder)) { + if (auto err = pEncoder->Terminate(pEncoder)) { + qCWarning(LOG_JXRPLUGIN) << "JXRHandlerPrivate::finalizeWriting() error while terminating the encoder:" << err; + return false; + } + if (auto err = pEncoder->Release(&pEncoder)) { qCWarning(LOG_JXRPLUGIN) << "JXRHandlerPrivate::finalizeWriting() error while releasing the encoder:" << err; return false; } @@ -999,13 +1003,13 @@ bool JXRHandler::read(QImage *outImage) return false; } if (auto err = pConverter->Initialize(pConverter, d->pDecoder, nullptr, convFmt)) { - PKFormatConverter_Release(&pConverter); + pConverter->Release(&pConverter); qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() unable to initialize the converter:" << err; return false; } if (d->pDecoder->WMP.wmiI.cBitsPerUnit == size_t(img.depth())) { // in place conversion if (auto err = pConverter->Copy(pConverter, &rect, img.bits(), img.bytesPerLine())) { - PKFormatConverter_Release(&pConverter); + pConverter->Release(&pConverter); qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() unable to copy converted data:" << err; return false; } @@ -1014,12 +1018,13 @@ bool JXRHandler::read(QImage *outImage) qint64 buffSize = convStrideSize * img.height(); qint64 limit = QImageReader::allocationLimit(); if (limit && (buffSize + img.sizeInBytes()) > limit * 1024 * 1024) { + pConverter->Release(&pConverter); qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() unable to covert due to allocation limit set:" << limit << "MiB"; return false; } QVector ba(buffSize); if (auto err = pConverter->Copy(pConverter, &rect, ba.data(), convStrideSize)) { - PKFormatConverter_Release(&pConverter); + pConverter->Release(&pConverter); qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() unable to copy converted data:" << err; return false; } @@ -1027,7 +1032,7 @@ bool JXRHandler::read(QImage *outImage) std::memcpy(img.scanLine(y), ba.data() + convStrideSize * y, (std::min)(convStrideSize, qint64(img.bytesPerLine()))); } } - PKFormatConverter_Release(&pConverter); + pConverter->Release(&pConverter); } // Metadata (e.g.: icc profile, description, etc...)