summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/serialization/qcborstreamreader.cpp35
-rw-r--r--src/corelib/serialization/qcborvalue.cpp27
-rw-r--r--src/corelib/text/qbytearray_p.h7
3 files changed, 48 insertions, 21 deletions
diff --git a/src/corelib/serialization/qcborstreamreader.cpp b/src/corelib/serialization/qcborstreamreader.cpp
index c983436606..ec385e0629 100644
--- a/src/corelib/serialization/qcborstreamreader.cpp
+++ b/src/corelib/serialization/qcborstreamreader.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2020 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -42,6 +42,7 @@
#define CBOR_NO_ENCODER_API
#include <private/qcborcommon_p.h>
+#include <private/qbytearray_p.h>
#include <private/qnumeric_p.h>
#include <private/qutfcodec_p.h>
#include <qdebug.h>
@@ -1055,6 +1056,10 @@ bool QCborStreamReader::next(int maxRecursion)
} else if (isString() || isByteArray()) {
auto r = _readByteArray_helper();
while (r.status == Ok) {
+ if (isString() && r.data.size() > MaxStringSize) {
+ d->handleError(CborErrorDataTooLarge);
+ break;
+ }
if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) {
d->handleError(CborErrorInvalidUtf8TextString);
break;
@@ -1337,15 +1342,23 @@ QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
result.status = r.status;
if (r.status == Ok) {
- QTextCodec::ConverterState cs;
- result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
- if (cs.invalidChars == 0 && cs.remainingChars == 0)
- return result;
+ // See QUtf8::convertToUnicode() a detailed explanation of why this
+ // conversion uses the same number of words or less.
+ CborError err = CborNoError;
+ if (r.data.size() > MaxStringSize) {
+ err = CborErrorDataTooLarge;
+ } else {
+ QTextCodec::ConverterState cs;
+ result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
+ if (cs.invalidChars != 0 || cs.remainingChars != 0)
+ err = CborErrorInvalidUtf8TextString;
+ }
- d->handleError(CborErrorInvalidUtf8TextString);
- result.data.clear();
- result.status = Error;
- return result;
+ if (err) {
+ d->handleError(err);
+ result.data.clear();
+ result.status = Error;
+ }
}
return result;
}
@@ -1373,6 +1386,10 @@ QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_he
qsizetype len = _currentStringChunkSize();
if (len < 0)
return result;
+ if (len > MaxByteArraySize) {
+ d->handleError(CborErrorDataTooLarge);
+ return result;
+ }
result.data.resize(len);
auto r = readStringChunk(result.data.data(), len);
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 98161094ae..63ee5f3158 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2020 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -53,6 +53,7 @@
#include <qendian.h>
#include <qlocale.h>
+#include <private/qbytearray_p.h>
#include <private/qnumeric_p.h>
#include <private/qsimd_p.h>
@@ -1553,6 +1554,8 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
// and calculate the final size
if (add_overflow(offset, increment, &newSize))
return -1;
+ if (newSize > MaxByteArraySize)
+ return -1;
// since usedData <= data.size(), this can't overflow
usedData += increment;
@@ -1627,13 +1630,6 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
setErrorInReader(reader, { QCborError::DataTooLarge });
}
- if (r.status == QCborStreamReader::Error) {
- // There can only be errors if there was data to be read.
- Q_ASSERT(e.flags & Element::HasByteData);
- data.truncate(e.value);
- return;
- }
-
// update size
if (e.flags & Element::HasByteData) {
auto b = new (dataPtr() + e.value) ByteData;
@@ -1645,6 +1641,21 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
Q_ASSERT(e.type == QCborValue::String);
e.flags |= Element::StringIsAscii;
}
+
+ // check that this UTF-8 text string can be loaded onto a QString
+ if (e.type == QCborValue::String) {
+ if (Q_UNLIKELY(b->len > MaxStringSize)) {
+ setErrorInReader(reader, { QCborError::DataTooLarge });
+ r.status = QCborStreamReader::Error;
+ }
+ }
+ }
+
+ if (r.status == QCborStreamReader::Error) {
+ // There can only be errors if there was data to be read.
+ Q_ASSERT(e.flags & Element::HasByteData);
+ data.truncate(e.value);
+ return;
}
elements.append(e);
diff --git a/src/corelib/text/qbytearray_p.h b/src/corelib/text/qbytearray_p.h
index 3c6257f786..ffec6dca22 100644
--- a/src/corelib/text/qbytearray_p.h
+++ b/src/corelib/text/qbytearray_p.h
@@ -56,10 +56,9 @@
QT_BEGIN_NAMESPACE
-enum {
- // Define as enum to force inlining. Don't expose MaxAllocSize in a public header.
- MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type)
-};
+// -1 because of the terminating NUL
+constexpr qsizetype MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type) - 1;
+constexpr qsizetype MaxStringSize = (MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type)) / 2 - 1;
QT_END_NAMESPACE