Introduce a settable allocation limit on image loading
[ChangeLog][QtGui][QImageReader] Introduced a settable allocation limit on image loading to limit resource usage from corrupt image files. Change-Id: Ibed7b0cac32798125a060e6db80b17ebc5e70759 Task-number: QTBUG-85037 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
cc857a3c71
commit
5dea4fe956
@ -264,9 +264,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qimageiohandler.h"
|
#include "qimageiohandler.h"
|
||||||
|
#include "qimage_p.h"
|
||||||
|
|
||||||
#include <qbytearray.h>
|
#include <qbytearray.h>
|
||||||
#include <qimage.h>
|
#include <qimagereader.h>
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -552,6 +553,45 @@ int QImageIOHandler::nextImageDelay() const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.0
|
||||||
|
|
||||||
|
This is a convenience method for the reading function in subclasses. Image
|
||||||
|
format handlers must reject loading an image if the required allocation
|
||||||
|
would exceeed the current allocation limit. This function checks the
|
||||||
|
parameters and limit, and does the allocation if it is valid and required.
|
||||||
|
Upon successful return, \a image will be a valid, detached QImage of the
|
||||||
|
given \a size and \a format.
|
||||||
|
|
||||||
|
\sa QImageReader::allocationLimit()
|
||||||
|
*/
|
||||||
|
bool QImageIOHandler::allocateImage(QSize size, QImage::Format format, QImage *image)
|
||||||
|
{
|
||||||
|
Q_ASSERT(image);
|
||||||
|
if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (image->size() == size && image->format() == format) {
|
||||||
|
image->detach();
|
||||||
|
} else {
|
||||||
|
if (const int mbLimit = QImageReader::allocationLimit()) {
|
||||||
|
qsizetype depth = qt_depthForFormat(format);
|
||||||
|
QImageData::ImageSizeParameters szp =
|
||||||
|
QImageData::calculateImageParameters(size.width(), size.height(), depth);
|
||||||
|
if (!szp.isValid())
|
||||||
|
return false;
|
||||||
|
const qsizetype mb = szp.totalSize >> 20;
|
||||||
|
if (mb > mbLimit || (mb == mbLimit && szp.totalSize % (1 << 20))) {
|
||||||
|
qWarning("QImageIOHandler: Rejecting image as it exceeds the current "
|
||||||
|
"allocation limit of %i megabytes", mbLimit);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*image = QImage(size, format);
|
||||||
|
}
|
||||||
|
return !image->isNull();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_IMAGEFORMATPLUGIN
|
#ifndef QT_NO_IMAGEFORMATPLUGIN
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#define QIMAGEIOHANDLER_H
|
#define QIMAGEIOHANDLER_H
|
||||||
|
|
||||||
#include <QtGui/qtguiglobal.h>
|
#include <QtGui/qtguiglobal.h>
|
||||||
|
#include <QtGui/qimage.h>
|
||||||
#include <QtCore/qiodevice.h>
|
#include <QtCore/qiodevice.h>
|
||||||
#include <QtCore/qplugin.h>
|
#include <QtCore/qplugin.h>
|
||||||
#include <QtCore/qfactoryinterface.h>
|
#include <QtCore/qfactoryinterface.h>
|
||||||
@ -123,6 +124,8 @@ public:
|
|||||||
virtual int currentImageNumber() const;
|
virtual int currentImageNumber() const;
|
||||||
virtual QRect currentImageRect() const;
|
virtual QRect currentImageRect() const;
|
||||||
|
|
||||||
|
static bool allocateImage(QSize size, QImage::Format format, QImage *image);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QImageIOHandler(QImageIOHandlerPrivate &dd);
|
QImageIOHandler(QImageIOHandlerPrivate &dd);
|
||||||
QScopedPointer<QImageIOHandlerPrivate> d_ptr;
|
QScopedPointer<QImageIOHandlerPrivate> d_ptr;
|
||||||
|
@ -492,8 +492,12 @@ public:
|
|||||||
QString errorString;
|
QString errorString;
|
||||||
|
|
||||||
QImageReader *q;
|
QImageReader *q;
|
||||||
|
|
||||||
|
static int maxAlloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int QImageReaderPrivate::maxAlloc = 128; // 128 MB is enough for an 8K 32bpp image
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
@ -1575,4 +1579,34 @@ QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeTy
|
|||||||
QImageReaderWriterHelpers::CanRead);
|
QImageReaderWriterHelpers::CanRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.0
|
||||||
|
|
||||||
|
Returns the current allocation limit, in megabytes.
|
||||||
|
|
||||||
|
\sa setAllocationLimit()
|
||||||
|
*/
|
||||||
|
int QImageReader::allocationLimit()
|
||||||
|
{
|
||||||
|
return QImageReaderPrivate::maxAlloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.0
|
||||||
|
|
||||||
|
Sets the allocation limit to \a mbLimit megabytes. Images that would
|
||||||
|
require a QImage memory allocation above this limit will be rejected.
|
||||||
|
|
||||||
|
This limit helps applications avoid unexpectedly large memory usage from
|
||||||
|
loading corrupt image files. It is normally not needed to change it. The
|
||||||
|
default limit is large enough for all commonly used image sizes.
|
||||||
|
|
||||||
|
\sa allocationLimit()
|
||||||
|
*/
|
||||||
|
void QImageReader::setAllocationLimit(int mbLimit)
|
||||||
|
{
|
||||||
|
if (mbLimit >= 0)
|
||||||
|
QImageReaderPrivate::maxAlloc = mbLimit;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -142,6 +142,8 @@ public:
|
|||||||
static QList<QByteArray> supportedImageFormats();
|
static QList<QByteArray> supportedImageFormats();
|
||||||
static QList<QByteArray> supportedMimeTypes();
|
static QList<QByteArray> supportedMimeTypes();
|
||||||
static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType);
|
static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType);
|
||||||
|
static int allocationLimit();
|
||||||
|
static void setAllocationLimit(int mbLimit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QImageReader)
|
Q_DISABLE_COPY(QImageReader)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user