Revision control

++ // Copyright (C) 2018 Intel Corporation.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:critical reason:data-parser
++
++ #ifndef QCBORSTREAMREADER_H
++ #define QCBORSTREAMREADER_H
++
++ #include <QtCore/qbytearray.h>
++ #include <QtCore/qcborcommon.h>
++ #include <QtCore/qfloat16.h>
++ #include <QtCore/qscopedpointer.h>
++ #include <QtCore/qstring.h>
++ #include <QtCore/qstringview.h>
++
++ #ifdef __cpp_lib_bit_cast
++ #include <bit>
++ #endif
++ #include <memory>
++
++ QT_REQUIRE_CONFIG(cborstreamreader);
++
++ /* X11 headers use these values too, but as defines */
++ #if defined(False) && defined(True)
++ # undef True
++ # undef False
++ #endif
++
++ QT_BEGIN_NAMESPACE
++
++ class QIODevice;
++
++ class QCborStreamReaderPrivate;
++ class Q_CORE_EXPORT QCborStreamReader
++ {
++ Q_GADGET
++ public:
++ enum Type : quint8 {
++ UnsignedInteger = 0x00,
++ NegativeInteger = 0x20,
++ ByteString = 0x40,
++ ByteArray = ByteString,
++ TextString = 0x60,
++ String = TextString,
++ Array = 0x80,
++ Map = 0xa0,
++ Tag = 0xc0,
++ SimpleType = 0xe0,
++ HalfFloat = 0xf9,
++ Float16 = HalfFloat,
++ Float = 0xfa,
++ Double = 0xfb,
++
++ Invalid = 0xff
++ };
++ Q_ENUM(Type)
++
++ enum StringResultCode {
++ EndOfString = 0,
++ Ok = 1,
++ Error = -1
++ };
++ template <typename Container> struct StringResult {
++ Container data;
++ StringResultCode status = Error;
++ };
++ Q_ENUM(StringResultCode)
++
++ QCborStreamReader();
++ QCborStreamReader(const char *data, qsizetype len);
++ QCborStreamReader(const quint8 *data, qsizetype len);
++ explicit QCborStreamReader(const QByteArray &data);
++ explicit QCborStreamReader(QIODevice *device);
++ ~QCborStreamReader();
++ Q_DISABLE_COPY(QCborStreamReader)
++
++ void setDevice(QIODevice *device);
++ QIODevice *device() const;
++ void addData(const QByteArray &data);
++ void addData(const char *data, qsizetype len);
++ void addData(const quint8 *data, qsizetype len)
++ { addData(reinterpret_cast<const char *>(data), len); }
++ void reparse();
++ void clear();
++ void reset();
++
++ #if QT_CORE_REMOVED_SINCE(6, 7)
++ QCborError lastError();
++ #endif
++ QCborError lastError() const;
++
++ qint64 bytesAvailable() const;
++ qint64 currentOffset() const;
++
++ bool isValid() const { return !isInvalid(); }
++
++ int containerDepth() const;
++ QCborStreamReader::Type parentContainerType() const;
++ Q_DECL_PURE_FUNCTION bool hasNext() const noexcept;
++ bool next(int maxRecursion = 10000);
++
++ Type type() const { return QCborStreamReader::Type(type_); }
++ bool isUnsignedInteger() const { return type() == UnsignedInteger; }
++ bool isNegativeInteger() const { return type() == NegativeInteger; }
++ bool isInteger() const { return quint8(type()) <= quint8(NegativeInteger); }
++ bool isByteArray() const { return type() == ByteArray; }
++ bool isString() const { return type() == String; }
++ bool isArray() const { return type() == Array; }
++ bool isMap() const { return type() == Map; }
++ bool isTag() const { return type() == Tag; }
++ bool isSimpleType() const { return type() == SimpleType; }
++ bool isFloat16() const { return type() == Float16; }
++ bool isFloat() const { return type() == Float; }
++ bool isDouble() const { return type() == Double; }
++ bool isNumber() const { return isInteger() || isFloat16() || isFloat() || isDouble(); }
++ bool isInvalid() const { return type() == Invalid; }
++
++ bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
++ bool isFalse() const { return isSimpleType(QCborSimpleType::False); }
++ bool isTrue() const { return isSimpleType(QCborSimpleType::True); }
++ bool isBool() const { return isFalse() || isTrue(); }
++ bool isNull() const { return isSimpleType(QCborSimpleType::Null); }
++ bool isUndefined() const { return isSimpleType(QCborSimpleType::Undefined); }
++
++ Q_DECL_PURE_FUNCTION bool isLengthKnown() const noexcept;
++ quint64 length() const;
++
++ bool isContainer() const { return isMap() || isArray(); }
++ bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
++ bool leaveContainer();
++
++ bool readAndAppendToString(QString &dst)
++ { Q_ASSERT(isString()); return _readAndAppendToString_helper(dst); }
++ bool readAndAppendToUtf8String(QByteArray &dst)
++ { Q_ASSERT(isString()); return _readAndAppendToUtf8String_helper(dst); }
++ bool readAndAppendToByteArray(QByteArray &dst)
++ { Q_ASSERT(isByteArray()); return _readAndAppendToByteArray_helper(dst); }
++ StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
++ StringResult<QByteArray> readUtf8String() { Q_ASSERT(isString()); return _readUtf8String_helper(); }
++ StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
++ qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
++ StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
++
++ bool toBool() const { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
++ QCborTag toTag() const { Q_ASSERT(isTag()); return QCborTag(value64); }
++ quint64 toUnsignedInteger() const { Q_ASSERT(isUnsignedInteger()); return value64; }
++ QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
++ QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
++ qfloat16 toFloat16() const { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
++ float toFloat() const { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
++ double toDouble() const { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
++
++ qint64 toInteger() const
++ {
++ Q_ASSERT(isInteger());
++ qint64 v = qint64(value64);
++ if (isNegativeInteger())
++ return -v - 1;
++ return v;
++ }
++ double toNumber() const
++ {
++ Q_ASSERT(isNumber());
++ if (isDouble())
++ return _toFloatingPoint<double>();
++ if (isFloat())
++ return _toFloatingPoint<float>();
++ if (isFloat16())
++ return _toFloatingPoint<qfloat16>();
++
++ // integer
++ double val = value64;
++ if (isNegativeInteger())
++ return -val - 1;
++ return val;
++ }
++ QString readAllString()
++ {
++ QString dst;
++ if (!readAndAppendToString(dst))
++ dst = QString{};
++ return dst;
++ }
++ QByteArray readAllUtf8String()
++ {
++ QByteArray dst;
++ if (!readAndAppendToUtf8String(dst))
++ dst = QByteArray{};
++ return dst;
++ }
++ QByteArray readAllByteArray()
++ {
++ QByteArray dst;
++ if (!readAndAppendToByteArray(dst))
++ dst = QByteArray{};
++ return dst;
++ }
++
++ private:
++ void preparse();
++ bool _enterContainer_helper();
++ StringResult<QString> _readString_helper();
++ StringResult<QByteArray> _readUtf8String_helper();
++ StringResult<QByteArray> _readByteArray_helper();
++ qsizetype _currentStringChunkSize() const;
++ bool _readAndAppendToString_helper(QString &);
++ bool _readAndAppendToUtf8String_helper(QByteArray &);
++ bool _readAndAppendToByteArray_helper(QByteArray &);
++
++ template <typename FP> FP _toFloatingPoint() const noexcept
++ {
++ using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
++ UIntFP u = UIntFP(value64);
++ #ifdef __cpp_lib_bit_cast
++ return std::bit_cast<FP>(u);
++ #else
++ FP f;
++ memcpy(static_cast<void *>(&f), &u, sizeof(f));
++ return f;
++ #endif
++ }
++
++ friend QCborStreamReaderPrivate;
++ friend class QCborContainerPrivate;
++ quint64 value64;
++ std::unique_ptr<QCborStreamReaderPrivate> d;
++ quint8 type_;
++ quint8 reserved[3] = {};
++ };
++
++ QT_END_NAMESPACE
++
++ #endif // QCBORSTREAMREADER_H