diff options
Diffstat (limited to 'src/corelib/tools/qbytearray.cpp')
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 86 |
1 files changed, 38 insertions, 48 deletions
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 9298472305..7d9c5dc325 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -663,6 +663,20 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel) */ #ifndef QT_NO_COMPRESS +namespace { +struct QByteArrayDataDeleter +{ + static inline void cleanup(QTypedArrayData<char> *d) + { if (d) QTypedArrayData<char>::deallocate(d); } +}; +} + +static QByteArray invalidCompressedData() +{ + qWarning("qUncompress: Input data is corrupted"); + return QByteArray(); +} + QByteArray qUncompress(const uchar* data, int nbytes) { if (!data) { @@ -677,53 +691,29 @@ QByteArray qUncompress(const uchar* data, int nbytes) ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] )); ulong len = qMax(expectedSize, 1ul); - QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d; + const ulong maxPossibleSize = MaxAllocSize - sizeof(QByteArray::Data); + if (Q_UNLIKELY(len >= maxPossibleSize)) { + // QByteArray does not support that huge size anyway. + return invalidCompressedData(); + } + QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1)); + if (Q_UNLIKELY(d.data() == nullptr)) + return invalidCompressedData(); + + d->size = expectedSize; forever { ulong alloc = len; - if (len >= (1u << 31u) - sizeof(QByteArray::Data)) { - //QByteArray does not support that huge size anyway. - qWarning("qUncompress: Input data is corrupted"); - return QByteArray(); - } - QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + alloc + 1)); - if (!p) { - // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS - qWarning("qUncompress: could not allocate enough memory to uncompress data"); - return QByteArray(); - } - d.take(); // realloc was successful - d.reset(p); - d->offset = sizeof(QByteArrayData); - d->size = 0; // Shut up valgrind "uninitialized variable" warning int res = ::uncompress((uchar*)d->data(), &len, data+4, nbytes-4); switch (res) { case Z_OK: - if (len != alloc) { - if (len >= (1u << 31u) - sizeof(QByteArray::Data)) { - //QByteArray does not support that huge size anyway. - qWarning("qUncompress: Input data is corrupted"); - return QByteArray(); - } - QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + len + 1)); - if (!p) { - // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS - qWarning("qUncompress: could not allocate enough memory to uncompress data"); - return QByteArray(); - } - d.take(); // realloc was successful - d.reset(p); - } - d->ref.initializeOwned(); + Q_ASSERT(len <= alloc); + Q_UNUSED(alloc); d->size = len; - d->alloc = uint(len) + 1u; - d->capacityReserved = false; - d->offset = sizeof(QByteArrayData); d->data()[len] = 0; - { QByteArrayDataPtr dataPtr = { d.take() }; return QByteArray(dataPtr); @@ -735,6 +725,17 @@ QByteArray qUncompress(const uchar* data, int nbytes) case Z_BUF_ERROR: len *= 2; + if (Q_UNLIKELY(len >= maxPossibleSize)) { + // QByteArray does not support that huge size anyway. + return invalidCompressedData(); + } else { + // grow the block + QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), len + 1); + if (Q_UNLIKELY(p == nullptr)) + return invalidCompressedData(); + d.take(); // don't free + d.reset(p); + } continue; case Z_DATA_ERROR: @@ -1707,19 +1708,8 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { - size_t blockSize; - if (options & Data::Grow) { - auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); - blockSize = r.size; - alloc = uint(r.elementCount); - } else { - blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); - } - - Data *x = static_cast<Data *>(::realloc(d, blockSize)); + Data *x = Data::reallocateUnaligned(d, alloc, options); Q_CHECK_PTR(x); - x->alloc = alloc; - x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0; d = x; } } |