From 347d94b016ff337e0312527d10c4768a6f951919 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 15 Sep 2022 15:29:34 +0200 Subject: [PATCH] qUncompress(): introduce more functions a la invalidCompressedData() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... and use them consistently instead of naked qWarning()s. As a drive-by, fix the warnings we generate on failures, which all-too-often was "invalid data". Code for minimal size by DRYing what the compiler can't, and using Q_DECL_COLD_FUNCTION to avoid excessive inlining. Left the one qWarning() in qCompress(), for now, because that would have changed the return value from an empty to a null byte array. Move invalidCompressedData() to where the others are defined, too, because it's required by a follow-up commit. Task-number: QTBUG-104972 Change-Id: Ia43aa315960b06530e98c1d7525ccf0e7f71bb5c Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne Reviewed-by: MÃ¥rten Nordheim (cherry picked from commit 6472616e6c98efe7b983ce2f1677dcada9c50321) --- src/corelib/text/qbytearray.cpp | 72 ++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 6e21d1e9383..e461167ff3e 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -532,16 +532,53 @@ quint16 qChecksum(QByteArrayView data, Qt::ChecksumType standard) #ifndef QT_NO_COMPRESS using CompressSizeHint_t = quint32; // 32-bit BE, historically +enum class ZLibOp : bool { Compression, Decompression }; + +Q_DECL_COLD_FUNCTION +static const char *zlibOpAsString(ZLibOp op) +{ + switch (op) { + case ZLibOp::Compression: return "qCompress"; + case ZLibOp::Decompression: return "qUncompress"; + } + Q_UNREACHABLE(); + return nullptr; +} + +Q_DECL_COLD_FUNCTION +static QByteArray zlibError(ZLibOp op, const char *what) +{ + qWarning("%s: %s", zlibOpAsString(op), what); + return QByteArray(); +} + +Q_DECL_COLD_FUNCTION +static QByteArray dataIsNull(ZLibOp op) +{ + return zlibError(op, "Data is null"); +} + +Q_DECL_COLD_FUNCTION +static QByteArray tooMuchData(ZLibOp op) +{ + return zlibError(op, "Not enough memory"); +} + +Q_DECL_COLD_FUNCTION +static QByteArray invalidCompressedData() +{ + return zlibError(ZLibOp::Decompression, "Input data is corrupted"); +} + QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel) { constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t); if (nbytes == 0) { return QByteArray(HeaderSize, '\0'); } - if (!data) { - qWarning("qCompress: Data is null"); - return QByteArray(); - } + if (!data) + return dataIsNull(ZLibOp::Compression); + if (compressionLevel < -1 || compressionLevel > 9) compressionLevel = -1; @@ -606,13 +643,6 @@ QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel) */ #ifndef QT_NO_COMPRESS -Q_DECL_COLD_FUNCTION -static QByteArray invalidCompressedData() -{ - qWarning("qUncompress: Input data is corrupted"); - return QByteArray(); -} - /*! \relates QByteArray \overload @@ -624,10 +654,8 @@ static QByteArray invalidCompressedData() */ QByteArray qUncompress(const uchar* data, qsizetype nbytes) { - if (!data) { - qWarning("qUncompress: Data is null"); - return QByteArray(); - } + if (!data) + return dataIsNull(ZLibOp::Decompression); constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t); if (nbytes < HeaderSize) @@ -643,12 +671,12 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes) constexpr size_t MaxZLibSize = (std::numeric_limits::max)(); constexpr size_t MaxDecompressedSize = (std::min)(size_t(MaxByteArraySize), MaxZLibSize); if (len > MaxDecompressedSize) - return invalidCompressedData(); + return tooMuchData(ZLibOp::Decompression); Q_ASSERT(len <= size_t((std::numeric_limits::max)())); QByteArray::DataPointer d(QByteArray::Data::allocate(qsizetype(len))); if (d.data() == nullptr) // allocation failed - return invalidCompressedData(); + return tooMuchData(ZLibOp::Decompression); forever { const auto alloc = len; @@ -665,23 +693,21 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes) } case Z_MEM_ERROR: - qWarning("qUncompress: Z_MEM_ERROR: Not enough memory"); - return QByteArray(); + return tooMuchData(ZLibOp::Decompression); case Z_BUF_ERROR: if (len == MaxDecompressedSize) // can't grow further - return invalidCompressedData(); + return tooMuchData(ZLibOp::Decompression); if (qMulOverflow<2>(len, &len)) len = MaxDecompressedSize; d->reallocate(qsizetype(len), QArrayData::Grow); // cannot overflow! if (d.data() == nullptr) // reallocation failed - return invalidCompressedData(); + return tooMuchData(ZLibOp::Decompression); continue; case Z_DATA_ERROR: - qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted"); - return QByteArray(); + return invalidCompressedData(); } } }