diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/serialization/qcborstreamreader.cpp | 35 | ||||
-rw-r--r-- | src/corelib/serialization/qcborvalue.cpp | 27 | ||||
-rw-r--r-- | src/corelib/text/qbytearray_p.h | 7 |
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 |