Make qdecompresshelper archive bomb check only trigger for large files
This is to avoid false positives. By default files are large if uncompressed size > 10 MB. Only configurable internally. Also add auto tests. Task-number: QTBUG-91392 Change-Id: I32258cb7c957f2a23a05157ba4ed5c0af2ba585e Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> (cherry picked from commit be73ca7eb1cebcc15064666e647bc337b5c2baa2) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
218b7c8a5b
commit
03332d8a00
@ -405,6 +405,11 @@ void QDecompressHelper::setArchiveBombDetectionEnabled(bool enable)
|
||||
countHelper->setArchiveBombDetectionEnabled(enable);
|
||||
}
|
||||
|
||||
void QDecompressHelper::setMinimumArchiveBombSize(qint64 threshold)
|
||||
{
|
||||
minimumArchiveBombSize = threshold;
|
||||
}
|
||||
|
||||
bool QDecompressHelper::isPotentialArchiveBomb() const
|
||||
{
|
||||
if (!archiveBombDetectionEnabled)
|
||||
@ -413,6 +418,9 @@ bool QDecompressHelper::isPotentialArchiveBomb() const
|
||||
if (totalCompressedBytes == 0)
|
||||
return false;
|
||||
|
||||
if (totalUncompressedBytes <= minimumArchiveBombSize)
|
||||
return false;
|
||||
|
||||
// Some protection against malicious or corrupted compressed files that expand far more than
|
||||
// is reasonable.
|
||||
double ratio = double(totalUncompressedBytes) / double(totalCompressedBytes);
|
||||
|
@ -92,6 +92,7 @@ public:
|
||||
void clear();
|
||||
|
||||
void setArchiveBombDetectionEnabled(bool enable);
|
||||
void setMinimumArchiveBombSize(qint64 threshold);
|
||||
|
||||
static bool isSupportedEncoding(const QByteArray &encoding);
|
||||
static QByteArrayList acceptedEncoding();
|
||||
@ -119,6 +120,7 @@ private:
|
||||
|
||||
// Used for calculating the ratio
|
||||
bool archiveBombDetectionEnabled = true;
|
||||
qint64 minimumArchiveBombSize = 10 * 1024 * 1024;
|
||||
qint64 totalUncompressedBytes = 0;
|
||||
qint64 totalCompressedBytes = 0;
|
||||
|
||||
|
BIN
tests/auto/network/access/qdecompresshelper/10K.gz
Normal file
BIN
tests/auto/network/access/qdecompresshelper/10K.gz
Normal file
Binary file not shown.
@ -64,6 +64,9 @@ private Q_SLOTS:
|
||||
void decompressBigData_data();
|
||||
void decompressBigData();
|
||||
|
||||
void archiveBomb_data();
|
||||
void archiveBomb();
|
||||
|
||||
#if QT_POINTER_SIZE >= 8
|
||||
void bigZlib();
|
||||
#endif
|
||||
@ -392,6 +395,43 @@ void tst_QDecompressHelper::decompressBigData()
|
||||
QTEST(totalSize, "size");
|
||||
}
|
||||
|
||||
void tst_QDecompressHelper::archiveBomb_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("encoding");
|
||||
QTest::addColumn<QString>("path");
|
||||
QTest::addColumn<bool>("shouldFail");
|
||||
|
||||
QTest::newRow("gzip-10K") << QByteArray("gzip") << (srcDir + "/10K.gz") << false;
|
||||
QTest::newRow("gzip-4G") << QByteArray("gzip") << QString(":/4G.gz") << true;
|
||||
}
|
||||
|
||||
void tst_QDecompressHelper::archiveBomb()
|
||||
{
|
||||
QFETCH(bool, shouldFail);
|
||||
QFETCH(QString, path);
|
||||
QFile file(path);
|
||||
QVERIFY(file.open(QIODevice::ReadOnly));
|
||||
|
||||
QDecompressHelper helper;
|
||||
QFETCH(QByteArray, encoding);
|
||||
helper.setEncoding(encoding);
|
||||
QVERIFY(helper.isValid());
|
||||
|
||||
constexpr qint64 SafeSizeLimit = 10 * 1024 * 1024;
|
||||
constexpr qint64 RatioLimit = 40;
|
||||
qint64 bytesToRead = std::min(SafeSizeLimit / RatioLimit, file.bytesAvailable());
|
||||
QByteArray output(1 + bytesToRead * RatioLimit, Qt::Uninitialized);
|
||||
helper.feed(file.read(bytesToRead));
|
||||
qsizetype bytesRead = helper.read(output.data(), output.size());
|
||||
QVERIFY(bytesRead <= output.size());
|
||||
QVERIFY(helper.isValid());
|
||||
|
||||
if (shouldFail)
|
||||
QCOMPARE(bytesRead, -1);
|
||||
else
|
||||
QVERIFY(bytesRead > 0);
|
||||
}
|
||||
|
||||
#if QT_POINTER_SIZE >= 8
|
||||
void tst_QDecompressHelper::bigZlib()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user