diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2020-08-27 12:53:20 +0200 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2020-08-29 14:20:05 +0200 |
commit | 7f3c0d8a050c20d822f92cb3f2489c53f966087f (patch) | |
tree | c736b1ca26861d5f5d48a80fe23f6ee1de6c11e4 /src/corelib | |
parent | 5911335756dff5a917e4a7ccf025816c08ddd656 (diff) |
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 <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
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 <QtCore/private/qtools_p.h> #include <QtCore/qmath.h> +#include <QtCore/qbytearray.h> // QBA::value_type +#include <QtCore/qstring.h> // QString::value_type + #include <stdlib.h> 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<char *>(dataPointer) - reinterpret_cast<char *>(data) : headerSize; + + allocSize = reserveExtraBytes(allocSize); + if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot reallocate reliably + return qMakePair(data, dataPointer); + QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize))); if (header) { header->flags = options; |