summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-02-16 08:42:27 +0100
committerMarc Mutz <marc.mutz@qt.io>2023-03-09 16:44:47 +0100
commitefa81e7bc9d148030123ce3cd96d599b26797cd8 (patch)
tree224316edf6b01b7091a09c1711398ff6a4eb4b37 /src
parentb0d3f5df53486fde39fd4ed03606f987efd32874 (diff)
QVarLengthArray: fix UBs in insert(it, n, v) ([basic.life], invariants)
In the same vein as e24df8bc726d12e80f3f1d14834f9305586fcc98 for emplace(it, v) and insert(it, rv), this patch addresses the identical issues in insert(it, n, v). The solution is unsurprisingly the same: q_rotate() after a resize(size() + n, v). The 6.2- code will need to look different, because resize(n, v) didn't exist there. Manual conflict resolutions: - ↑ that - no resize_impl() in this branch, so wrote one as a private method Change-Id: I1ce91969abc20f2a1e5d05a8545b009a2e0994f6 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> (cherry picked from commit fed5f2445480f7cf045e93761dc902f771cbf3da) Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qvarlengtharray.h42
1 files changed, 20 insertions, 22 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index 64a29f4cf1..1a24048592 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -373,6 +373,20 @@ public:
private:
void reallocate(qsizetype size, qsizetype alloc);
+ void resize_impl(qsizetype newSize, const T &t)
+ {
+ const auto increment = newSize - size();
+ if (increment > 0 && QtPrivate::q_points_into_range(&t, cbegin(), cend())) {
+ resize_impl(newSize, T(t));
+ return;
+ }
+ reallocate(qMin(size(), newSize), qMax(newSize, capacity()));
+
+ if (increment > 0)
+ std::uninitialized_fill_n(end(), increment, t);
+ s = newSize;
+ }
+
qsizetype a; // capacity
qsizetype s; // size
T *ptr; // data
@@ -643,28 +657,12 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
{
Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
- qsizetype offset = qsizetype(before - ptr);
- if (n != 0) {
- const T copy(t); // `t` could alias an element in [begin(), end()[
- resize(s + n);
- if (!QTypeInfo<T>::isRelocatable) {
- T *b = ptr + offset;
- T *j = ptr + s;
- T *i = j - n;
- while (i != b)
- *--j = *--i;
- i = b + n;
- while (i != b)
- *--i = copy;
- } else {
- T *b = ptr + offset;
- T *i = b + n;
- memmove(static_cast<void *>(i), static_cast<const void *>(b), (s - offset - n) * sizeof(T));
- while (i != b)
- new (--i) T(copy);
- }
- }
- return ptr + offset;
+ const qsizetype offset = qsizetype(before - cbegin());
+ resize_impl(size() + n, t);
+ const auto b = begin() + offset;
+ const auto e = end();
+ QtPrivate::q_rotate(b, e - n, e);
+ return b;
}
template <class T, qsizetype Prealloc>