summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qarraydata.cpp
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2020-08-27 12:53:20 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2020-08-29 14:20:05 +0200
commit7f3c0d8a050c20d822f92cb3f2489c53f966087f (patch)
treec736b1ca26861d5f5d48a80fe23f6ee1de6c11e4 /src/corelib/tools/qarraydata.cpp
parent5911335756dff5a917e4a7ccf025816c08ddd656 (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/tools/qarraydata.cpp')
-rw-r--r--src/corelib/tools/qarraydata.cpp30
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;