PSD: limit memory usage on corrupted files

This commit is contained in:
Mirco Miranda
2025-11-07 14:31:29 +01:00
parent cfbeb397a8
commit d3d4bea2f1
2 changed files with 46 additions and 3 deletions

View File

@ -384,9 +384,7 @@ static PSDImageResourceSection readImageResourceSection(QDataStream &s, bool *ok
*ok = false;
break;
}
// NOTE: Qt device::read() and QDataStream::readRawData() could read less data than specified.
// The read code should be improved.
irb.data = dev->read(dataSize);
irb.data = deviceRead(dev, dataSize);
}
auto read = irb.data.size();
if (read > 0) {

View File

@ -12,6 +12,7 @@
#include <QImage>
#include <QImageIOHandler>
#include <QIODevice>
// Default maximum width and height for the large image plugins.
#ifndef KIF_LARGE_IMAGE_PIXEL_LIMIT
@ -132,4 +133,48 @@ inline float fppm2dpi(qint32 ppm, bool *ok = nullptr)
return ppm2dpi_T<float>(ppm, ok);
}
/*!
* \brief deviceRead
* A function for reading from devices.
*
* Similar to QIODevice::read(qint64) but limits the initial memory allocation. Useful for reading corrupted streams.
* \param d The device.
* \param maxSize The maximum size to read.
* \return The byte array read.
*/
static QByteArray deviceRead(QIODevice *d, qint64 maxSize)
{
if (d == nullptr) {
return{};
}
const qint64 blockSize = 32 * 1024 * 1024;
auto devSize = d->isSequential() ? qint64() : d->size();
if (devSize > 0) {
// random access device
maxSize = std::min(maxSize, devSize - d->pos());
return d->read(maxSize);
} else if (maxSize < blockSize) {
// small read
return d->read(maxSize);
}
// sequential device
QByteArray ba;
while (ba.size() < maxSize) {
auto toRead = std::min(blockSize, maxSize - ba.size());
if (toRead + ba.size() > QByteArray::maxSize()) {
break;
}
auto tmp = d->read(toRead);
if (tmp.isEmpty()) {
break;
}
ba.append(tmp);
}
return ba;
}
#endif // UTIL_P_H