From 7f3c0d8a050c20d822f92cb3f2489c53f966087f Mon Sep 17 00:00:00 2001 From: Andrei Golubev Date: Thu, 27 Aug 2020 12:53:20 +0200 Subject: Reserve extra space for '\0' in QArrayData::allocate Added implicit space reservation for '\0' in allocation functions used by containers. In current setting, this means sizeof(char16_t) bytes extra memory is allocated each time and implicitly exists. The extra memory is uninitialized by default Task-number: QTBUG-84320 Change-Id: Ia3cc268183c00ea24ea9d326db3f392f71868d52 Reviewed-by: Lars Knoll --- src/corelib/tools/qarraydata.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src/corelib/tools/qarraydata.cpp') diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 03465238b8..ab4a0f8af6 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -43,6 +43,9 @@ #include #include +#include // QBA::value_type +#include // QString::value_type + #include QT_BEGIN_NAMESPACE @@ -140,6 +143,22 @@ qCalculateGrowingBlockSize(qsizetype elementCount, qsizetype elementSize, qsizet return result; } +/*! + \internal + + Returns \a allocSize plus extra reserved bytes necessary to store '\0'. + */ +static inline qsizetype reserveExtraBytes(qsizetype allocSize) +{ + // We deal with QByteArray and QString only + constexpr qsizetype extra = qMax(sizeof(QByteArray::value_type), sizeof(QString::value_type)); + if (Q_UNLIKELY(allocSize < 0)) + return -1; + if (Q_UNLIKELY(add_overflow(allocSize, extra, &allocSize))) + return -1; + return allocSize; +} + static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype objectSize, qsizetype headerSize, uint options) { // Calculate the byte size @@ -190,6 +209,12 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al Q_ASSERT(headerSize > 0); qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); + allocSize = reserveExtraBytes(allocSize); + if (Q_UNLIKELY(allocSize < 0)) { // handle overflow. cannot allocate reliably + *dptr = nullptr; + return nullptr; + } + QArrayData *header = allocateData(allocSize, options); void *data = nullptr; if (header) { @@ -211,6 +236,11 @@ QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer, qsizetype headerSize = sizeof(QArrayData); qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); qptrdiff offset = dataPointer ? reinterpret_cast(dataPointer) - reinterpret_cast(data) : headerSize; + + allocSize = reserveExtraBytes(allocSize); + if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot reallocate reliably + return qMakePair(data, dataPointer); + QArrayData *header = static_cast(::realloc(data, size_t(allocSize))); if (header) { header->flags = options; -- cgit v1.2.3