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 "qimage_p.h"
|
||||
|
||||
#include <qbytearray.h>
|
||||
#include <qimage.h>
|
||||
#include <qimagereader.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -552,6 +553,45 @@ int QImageIOHandler::nextImageDelay() const
|
||||
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
|
||||
|
||||
/*!
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define QIMAGEIOHANDLER_H
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtGui/qimage.h>
|
||||
#include <QtCore/qiodevice.h>
|
||||
#include <QtCore/qplugin.h>
|
||||
#include <QtCore/qfactoryinterface.h>
|
||||
@ -123,6 +124,8 @@ public:
|
||||
virtual int currentImageNumber() const;
|
||||
virtual QRect currentImageRect() const;
|
||||
|
||||
static bool allocateImage(QSize size, QImage::Format format, QImage *image);
|
||||
|
||||
protected:
|
||||
QImageIOHandler(QImageIOHandlerPrivate &dd);
|
||||
QScopedPointer<QImageIOHandlerPrivate> d_ptr;
|
||||
|
@ -492,8 +492,12 @@ public:
|
||||
QString errorString;
|
||||
|
||||
QImageReader *q;
|
||||
|
||||
static int maxAlloc;
|
||||
};
|
||||
|
||||
int QImageReaderPrivate::maxAlloc = 128; // 128 MB is enough for an 8K 32bpp image
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@ -1575,4 +1579,34 @@ QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeTy
|
||||
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
|
||||
|
@ -142,6 +142,8 @@ public:
|
||||
static QList<QByteArray> supportedImageFormats();
|
||||
static QList<QByteArray> supportedMimeTypes();
|
||||
static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType);
|
||||
static int allocationLimit();
|
||||
static void setAllocationLimit(int mbLimit);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QImageReader)
|
||||
|
Loading…
Reference in New Issue
Block a user