From 3cb00e415d72f466a1f235490cfae029169ce7ae Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 17 Sep 2022 10:48:18 +0200 Subject: [PATCH] DRY qCompress/qUncompress: introduce CompressedSizeHint_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... and use it to remove the associated magic number 4 from the code base. As a drive-by, replace a naked qWarning() with the existing invalidCompressedData() helper function, and a C-style cast with reinterpret_cast. Pick-to: 6.4 6.3 6.2 Task-number: QTBUG-106542 Change-Id: I35004757e01bfc0747f7cc65bdf6eb243225caad Reviewed-by: MÃ¥rten Nordheim --- src/corelib/text/qbytearray.cpp | 34 ++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index f5b468ad6e..53ce3f66e2 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -517,7 +517,9 @@ quint16 qChecksum(QByteArrayView data, Qt::ChecksumType standard) \sa qUncompress(const QByteArray &data) */ -/*! \relates QByteArray +/*! + \fn QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel) + \relates QByteArray \overload @@ -528,10 +530,13 @@ quint16 qChecksum(QByteArrayView data, Qt::ChecksumType standard) */ #ifndef QT_NO_COMPRESS +using CompressSizeHint_t = quint32; // 32-bit BE, historically + QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel) { + constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t); if (nbytes == 0) { - return QByteArray(4, '\0'); + return QByteArray(HeaderSize, '\0'); } if (!data) { qWarning("qCompress: Data is null"); @@ -544,13 +549,15 @@ QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel) QByteArray bazip; int res; do { - bazip.resize(len + 4); - res = ::compress2((uchar*)bazip.data()+4, &len, data, nbytes, compressionLevel); + bazip.resize(len + HeaderSize); + res = ::compress2(reinterpret_cast(bazip.data()) + HeaderSize, &len, + data, nbytes, + compressionLevel); switch (res) { case Z_OK: - bazip.resize(len + 4); - qToBigEndian(quint32(nbytes), bazip.data()); // 4 octets, historically + bazip.resize(len + HeaderSize); + qToBigEndian(CompressSizeHint_t(nbytes), bazip.data()); break; case Z_MEM_ERROR: qWarning("qCompress: Z_MEM_ERROR: Not enough memory"); @@ -621,12 +628,17 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes) qWarning("qUncompress: Data is null"); return QByteArray(); } - if (nbytes <= 4) { - if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0)) - qWarning("qUncompress: Input data is corrupted"); + + constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t); + if (nbytes < HeaderSize) + return invalidCompressedData(); + + const auto expectedSize = qFromBigEndian(data); + if (nbytes == HeaderSize) { + if (expectedSize != 0) + return invalidCompressedData(); return QByteArray(); } - const auto expectedSize = qFromBigEndian(data); uLong len = qMax(expectedSize, 1u); constexpr size_t MaxZLibSize = (std::numeric_limits::max)(); constexpr size_t MaxDecompressedSize = (std::min)(size_t(MaxByteArraySize), MaxZLibSize); @@ -641,7 +653,7 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes) forever { const auto alloc = len; int res = ::uncompress(reinterpret_cast(d.data()), &len, - data+4, nbytes-4); + data + HeaderSize, nbytes - HeaderSize); switch (res) { case Z_OK: {