QCborValue: attempt a bit of exception-safety around QList::reserve

We don't promise we're very good at handling exceptions.

Pick-to: 6.4
Task-number: QTBUG-104718
Change-Id: I89c4eb48af38408daa7cfffd16fdcc171db437bd
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Thiago Macieira 2022-07-01 12:43:57 -07:00
parent f6e6ae092d
commit b483c67e0f

View File

@ -933,11 +933,16 @@ QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qs
if (!d) { if (!d) {
d = new QCborContainerPrivate; d = new QCborContainerPrivate;
} else { } else {
d = new QCborContainerPrivate(*d); // in case QList::reserve throws
QExplicitlySharedDataPointer u(new QCborContainerPrivate(*d));
if (reserved >= 0) { if (reserved >= 0) {
d->elements.reserve(reserved); u->elements.reserve(reserved);
d->compact(reserved); u->compact(reserved);
} }
d = u.take();
d->ref.storeRelaxed(0);
for (auto &e : qAsConst(d->elements)) { for (auto &e : qAsConst(d->elements)) {
if (e.flags & Element::IsContainer) if (e.flags & Element::IsContainer)
e.container->ref.ref(); e.container->ref.ref();
@ -1478,6 +1483,8 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
// entries to account for key-value pairs. // entries to account for key-value pairs.
static qsizetype clampedContainerLength(const QCborStreamReader &reader) static qsizetype clampedContainerLength(const QCborStreamReader &reader)
{ {
if (!reader.isLengthKnown())
return 0;
int mapShift = reader.isMap() ? 1 : 0; int mapShift = reader.isMap() ? 1 : 0;
quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift; quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift;
qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements)); qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements));
@ -1492,15 +1499,12 @@ static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &
} }
QCborContainerPrivate *d = nullptr; QCborContainerPrivate *d = nullptr;
if (reader.isLengthKnown()) { {
if (qsizetype len = clampedContainerLength(reader)) { // in case QList::reserve throws
d = new QCborContainerPrivate; QExplicitlySharedDataPointer u(new QCborContainerPrivate);
d->ref.storeRelaxed(1); if (qsizetype len = clampedContainerLength(reader))
d->elements.reserve(len); u->elements.reserve(len);
} d = u.take();
} else {
d = new QCborContainerPrivate;
d->ref.storeRelaxed(1);
} }
reader.enterContainer(); reader.enterContainer();