summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-03-27 01:00:18 +0100
committerEdward Welbourne <edward.welbourne@qt.io>2020-03-27 09:23:33 +0100
commit4752bd7718250dec5b725b9ba2c6f4bc88743ba6 (patch)
tree6563c20d69c982d476b1b25366cb550f3ef42354 /src/corelib/serialization
parent96de59d7c1068022dbb590d7abbdcf6eaf5d0566 (diff)
parentf581b041199ba7c825fbffd9110727360d1f2668 (diff)
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts: src/corelib/serialization/qcborvalue.cpp Change-Id: I539d8cae5fd413b8a6c9c5d8a6364c79c8133a0a
Diffstat (limited to 'src/corelib/serialization')
-rw-r--r--src/corelib/serialization/qcborvalue.cpp109
-rw-r--r--src/corelib/serialization/qcborvalue_p.h4
2 files changed, 67 insertions, 46 deletions
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index db2840704c..98161094ae 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -844,11 +844,6 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
return QCborValue::Tag;
}
-#if QT_CONFIG(cborstreamreader)
-// in qcborstream.cpp
-extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
-#endif
-
#if QT_CONFIG(cborstreamwriter)
static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt)
{
@@ -1462,23 +1457,59 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
return e;
}
-static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader)
+static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
{
- auto d = new QCborContainerPrivate;
- d->ref.storeRelaxed(1);
- d->decodeFromCbor(reader);
+ if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
+ QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
+ return nullptr;
+ }
+
+ QCborContainerPrivate *d = nullptr;
+ int mapShift = reader.isMap() ? 1 : 0;
+ if (reader.isLengthKnown()) {
+ quint64 len = reader.length();
+
+ // Clamp allocation to 1M elements (avoids crashing due to corrupt
+ // stream or loss of precision when converting from quint64 to
+ // QVector::size_type).
+ len = qMin(len, quint64(1024 * 1024 - 1));
+ if (len) {
+ d = new QCborContainerPrivate;
+ d->ref.storeRelaxed(1);
+ d->elements.reserve(qsizetype(len) << mapShift);
+ }
+ } else {
+ d = new QCborContainerPrivate;
+ d->ref.storeRelaxed(1);
+ }
+
+ reader.enterContainer();
+ if (reader.lastError() != QCborError::NoError)
+ return d;
+
+ while (reader.hasNext() && reader.lastError() == QCborError::NoError)
+ d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
+
+ if (reader.lastError() == QCborError::NoError)
+ reader.leaveContainer();
+
return d;
}
-static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
+static QCborValue taggedValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
{
+ if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
+ QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
+ return QCborValue::Invalid;
+ }
+
auto d = new QCborContainerPrivate;
d->append(reader.toTag());
reader.next();
if (reader.lastError() == QCborError::NoError) {
// decode tagged value
- d->decodeValueFromCbor(reader);
+ d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
}
QCborValue::Type type;
@@ -1494,6 +1525,13 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
return QCborContainerPrivate::makeValue(type, -1, d);
}
+// in qcborstream.cpp
+extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
+inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, QCborError error)
+{
+ qt_cbor_stream_set_error(reader.d.data(), error);
+}
+
void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
{
auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
@@ -1538,7 +1576,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
return; // error
if (len != rawlen) {
// truncation
- qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
+ setErrorInReader(reader, { QCborError::DataTooLarge });
return;
}
@@ -1548,7 +1586,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
e.value = addByteData_local(len);
if (e.value < 0) {
// overflow
- qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
+ setErrorInReader(reader, { QCborError::DataTooLarge });
return;
}
}
@@ -1562,7 +1600,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
if (!utf8result.isValidUtf8) {
r.status = QCborStreamReader::Error;
- qt_cbor_stream_set_error(reader.d.data(), { QCborError::InvalidUtf8String });
+ setErrorInReader(reader, { QCborError::InvalidUtf8String });
break;
}
isAscii = isAscii && utf8result.isValidAscii;
@@ -1586,7 +1624,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
// error
r.status = QCborStreamReader::Error;
- qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
+ setErrorInReader(reader, { QCborError::DataTooLarge });
}
if (r.status == QCborStreamReader::Error) {
@@ -1612,9 +1650,10 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
elements.append(e);
}
-void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader)
+void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
{
- switch (reader.type()) {
+ QCborStreamReader::Type t = reader.type();
+ switch (t) {
case QCborStreamReader::UnsignedInteger:
case QCborStreamReader::NegativeInteger:
case QCborStreamReader::SimpleType:
@@ -1631,37 +1670,17 @@ void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader)
case QCborStreamReader::Array:
case QCborStreamReader::Map:
+ return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1,
+ createContainerFromCbor(reader, remainingRecursionDepth),
+ MoveContainer));
+
case QCborStreamReader::Tag:
- return append(QCborValue::fromCbor(reader));
+ return append(taggedValueFromCbor(reader, remainingRecursionDepth));
case QCborStreamReader::Invalid:
return; // probably a decode error
}
}
-
-void QCborContainerPrivate::decodeFromCbor(QCborStreamReader &reader)
-{
- int mapShift = reader.isMap() ? 1 : 0;
- if (reader.isLengthKnown()) {
- quint64 len = reader.length();
-
- // Clamp allocation to 1M elements (avoids crashing due to corrupt
- // stream or loss of precision when converting from quint64 to
- // QVector::size_type).
- len = qMin(len, quint64(1024 * 1024 - 1));
- elements.reserve(qsizetype(len) << mapShift);
- }
-
- reader.enterContainer();
- if (reader.lastError() != QCborError::NoError)
- return;
-
- while (reader.hasNext() && reader.lastError() == QCborError::NoError)
- decodeValueFromCbor(reader);
-
- if (reader.lastError() == QCborError::NoError)
- reader.leaveContainer();
-}
#endif // QT_CONFIG(cborstreamreader)
/*!
@@ -2363,6 +2382,8 @@ QCborValueRef QCborValue::operator[](qint64 key)
}
#if QT_CONFIG(cborstreamreader)
+enum { MaximumRecursionDepth = 1024 };
+
/*!
Decodes one item from the CBOR stream found in \a reader and returns the
equivalent representation. This function is recursive: if the item is a map
@@ -2423,12 +2444,12 @@ QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
case QCborStreamReader::Map:
result.n = -1;
result.t = reader.isArray() ? Array : Map;
- result.container = createContainerFromCbor(reader);
+ result.container = createContainerFromCbor(reader, MaximumRecursionDepth);
break;
// tag
case QCborStreamReader::Tag:
- result = taggedValueFromCbor(reader);
+ result = taggedValueFromCbor(reader, MaximumRecursionDepth);
break;
}
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
index a74ac2ba10..041a20e746 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -405,9 +405,9 @@ public:
elements.remove(idx);
}
- void decodeValueFromCbor(QCborStreamReader &reader);
- void decodeFromCbor(QCborStreamReader &reader);
+ void decodeValueFromCbor(QCborStreamReader &reader, int remainiingStackDepth);
void decodeStringFromCbor(QCborStreamReader &reader);
+ static inline void setErrorInReader(QCborStreamReader &reader, QCborError error);
};
QT_END_NAMESPACE