diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2021-11-11 15:45:46 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-02-15 17:00:03 -0800 |
commit | 3531f578d3b55fb151ae99112acdfd20228855fa (patch) | |
tree | 7f9775efefa6d991dabee5adfcc51689e57b6df7 | |
parent | 800f60657d28ad96e0021b4dcd812e3a3be4dcb1 (diff) |
QCborArray: allow large but in-range keys
The 0x10000 limit should not apply if the key is a valid index in the
array.
Change-Id: I5e52dc5b093c43a3b678fffd16b6a2a5a69acd61
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
-rw-r--r-- | src/corelib/serialization/qcborvalue.cpp | 19 | ||||
-rw-r--r-- | tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp | 25 |
2 files changed, 42 insertions, 2 deletions
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 8edcbfec1c..c0f8a9a40d 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2215,6 +2215,21 @@ const QCborValue QCborValue::operator[](qint64 key) const return QCborValue(); } +static bool shouldArrayRemainArray(qint64 key, QCborValue::Type t, QCborContainerPrivate *container) +{ + constexpr qint64 LargeKey = 0x10000; + if (t != QCborValue::Array) + return false; + if (key < 0) + return false; // negative keys can't be an array index + if (key < LargeKey) + return true; + + // Only convert to map if key is greater than array size + 1 + qsizetype currentSize = container ? container->elements.size() : 0; + return key <= currentSize; +} + /*! \internal */ @@ -2369,7 +2384,7 @@ QCborValueRef QCborValue::operator[](QLatin1String key) */ QCborValueRef QCborValue::operator[](qint64 key) { - if (isArray() && key >= 0 && key < 0x10000) { + if (shouldArrayRemainArray(key, t, container)) { container = maybeGrow(container, key); return { container, qsizetype(key) }; } @@ -2898,7 +2913,7 @@ QCborValueRef QCborValueRef::operator[](QLatin1String key) QCborValueRef QCborValueRef::operator[](qint64 key) { auto &e = d->elements[i]; - if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) { + if (shouldArrayRemainArray(key, e.type, e.container)) { e.container = maybeGrow(e.container, key); e.flags |= QtCbor::Element::IsContainer; return { e.container, qsizetype(key) }; diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index fcbe739a39..16884987f4 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -74,6 +74,7 @@ private slots: void arrayPrepend(); void arrayValueRef_data() { basics_data(); } void arrayValueRef(); + void arrayValueRefLargeKey(); void arrayInsertRemove_data() { basics_data(); } void arrayInsertRemove(); void arrayInsertTagged_data() { basics_data(); } @@ -1320,6 +1321,30 @@ void tst_QCborValue::arrayValueRef() iteratorCheck(a.constBegin()); } +void tst_QCborValue::arrayValueRefLargeKey() +{ + // make sure the access via QCborValue & QCborValueRef don't convert this + // array to a map + constexpr qsizetype LargeKey = 0x10000; + QCborArray a; + a[LargeKey + 1] = 123; + + QCborValue v(a); + QCOMPARE(qAsConst(v)[LargeKey], QCborValue()); + QCOMPARE(qAsConst(v)[LargeKey + 1], 123); + QCOMPARE(v[LargeKey], QCborValue()); + QCOMPARE(v[LargeKey + 1], 123); + QCOMPARE(v.type(), QCborValue::Array); + + QCborArray outer = { QCborValue(a) }; + QCborValueRef ref = outer[0]; + QCOMPARE(qAsConst(ref)[LargeKey], QCborValue()); + QCOMPARE(qAsConst(ref)[LargeKey + 1], 123); + QCOMPARE(ref[LargeKey], QCborValue()); + QCOMPARE(ref[LargeKey + 1], 123); + QCOMPARE(ref.type(), QCborValue::Array); +} + void tst_QCborValue::mapValueRef() { QFETCH(QCborValue, v); |