QVarLengthArray: fix UBs in insert(it, n, v) ([basic.life], invariants)

In the same vein as e24df8bc72 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.

Pick-to: 6.5 6.4 6.2 5.15
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>
This commit is contained in:
Marc Mutz 2023-02-16 08:42:27 +01:00
parent 147dd6e82f
commit fed5f24454

View File

@ -925,28 +925,12 @@ Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::insert_impl(qsizetype prealloc, void *arr
{
Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
qsizetype offset = qsizetype(before - cbegin());
if (n != 0) {
const T copy(t); // `t` could alias an element in [begin(), end()[
resize_impl(prealloc, array, size() + n);
if constexpr (!QTypeInfo<T>::isRelocatable) {
T *b = begin() + offset;
T *j = end();
T *i = j - n;
while (i != b)
*--j = *--i;
i = b + n;
while (i != b)
*--i = copy;
} else {
T *b = begin() + offset;
T *i = b + n;
memmove(static_cast<void *>(i), static_cast<const void *>(b), (size() - offset - n) * sizeof(T));
while (i != b)
q20::construct_at(--i, copy);
}
}
return data() + offset;
const qsizetype offset = qsizetype(before - cbegin());
resize_impl(prealloc, array, size() + n, t);
const auto b = begin() + offset;
const auto e = end();
QtPrivate::q_rotate(b, e - n, e);
return b;
}
template <class T>