1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 Intel Corporation.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qcborstreamreader.h"
41 
42 #define CBOR_NO_ENCODER_API
43 #include <private/qcborcommon_p.h>
44 
45 #include <private/qbytearray_p.h>
46 #include <private/qnumeric_p.h>
47 #include <private/qutfcodec_p.h>
48 #include <qdebug.h>
49 #include <qstack.h>
50 
51 QT_BEGIN_NAMESPACE
52 
53 static bool qt_cbor_decoder_can_read(void *token, size_t len);
54 static void qt_cbor_decoder_advance(void *token, size_t len);
55 static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len);
56 static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len);
57 
58 #define CBOR_PARSER_READER_CONTROL              1
59 #define CBOR_PARSER_CAN_READ_BYTES_FUNCTION     qt_cbor_decoder_can_read
60 #define CBOR_PARSER_ADVANCE_BYTES_FUNCTION      qt_cbor_decoder_advance
61 #define CBOR_PARSER_TRANSFER_STRING_FUNCTION    qt_cbor_decoder_transfer_string
62 #define CBOR_PARSER_READ_BYTES_FUNCTION         qt_cbor_decoder_read
63 
64 QT_WARNING_PUSH
65 QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
66 
67 #include <cborparser.c>
68 
69 QT_WARNING_POP
70 
_cbor_value_dup_string(const CborValue *,void **,size_t *,CborValue *)71 static CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
72 {
73     Q_UNREACHABLE();
74     return CborErrorInternalError;
75 }
cbor_value_get_half_float_as_float(const CborValue *,float *)76 static CborError Q_DECL_UNUSED cbor_value_get_half_float_as_float(const CborValue *, float *)
77 {
78     Q_UNREACHABLE();
79     return CborErrorInternalError;
80 }
81 
82 // confirm our constants match TinyCBOR's
83 Q_STATIC_ASSERT(int(QCborStreamReader::UnsignedInteger) == CborIntegerType);
84 Q_STATIC_ASSERT(int(QCborStreamReader::ByteString) == CborByteStringType);
85 Q_STATIC_ASSERT(int(QCborStreamReader::TextString) == CborTextStringType);
86 Q_STATIC_ASSERT(int(QCborStreamReader::Array) == CborArrayType);
87 Q_STATIC_ASSERT(int(QCborStreamReader::Map) == CborMapType);
88 Q_STATIC_ASSERT(int(QCborStreamReader::Tag) == CborTagType);
89 Q_STATIC_ASSERT(int(QCborStreamReader::SimpleType) == CborSimpleType);
90 Q_STATIC_ASSERT(int(QCborStreamReader::HalfFloat) == CborHalfFloatType);
91 Q_STATIC_ASSERT(int(QCborStreamReader::Float) == CborFloatType);
92 Q_STATIC_ASSERT(int(QCborStreamReader::Double) == CborDoubleType);
93 Q_STATIC_ASSERT(int(QCborStreamReader::Invalid) == CborInvalidType);
94 
95 /*!
96    \class QCborStreamReader
97    \inmodule QtCore
98    \ingroup cbor
99    \reentrant
100    \since 5.12
101 
102    \brief The QCborStreamReader class is a simple CBOR stream decoder, operating
103    on either a QByteArray or QIODevice.
104 
105    This class can be used to decode a stream of CBOR content directly from
106    either a QByteArray or a QIODevice. CBOR is the Concise Binary Object
107    Representation, a very compact form of binary data encoding that is
108    compatible with JSON. It was created by the IETF Constrained RESTful
109    Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
110    be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
111    protocol}.
112 
113    QCborStreamReader provides a StAX-like API, similar to that of
114    \l{QXmlStreamReader}. Using it requires a bit of knowledge of CBOR encoding.
115    For a simpler API, see \l{QCborValue} and especially the decoding function
116    QCborValue::fromCbor().
117 
118    Typically, one creates a QCborStreamReader by passing the source QByteArray
119    or QIODevice as a parameter to the constructor, then pop elements off the
120    stream if there were no errors in decoding. There are three kinds of CBOR
121    types:
122 
123    \table
124      \header \li Kind       \li Types       \li Behavior
125      \row   \li Fixed-width \li Integers, Tags, Simple types, Floating point
126             \li Value is pre-parsed by QCborStreamReader, so accessor functions
127                 are \c const. Must call next() to advance.
128      \row   \li Strings     \li Byte arrays, Text strings
129             \li Length (if known) is pre-parsed, but the string itself is not.
130                 The accessor functions are not const and may allocate memory.
131                 Once called, the accessor functions automatically advance to
132                 the next element.
133      \row   \li Containers  \li Arrays, Maps
134             \li Length (if known) is pre-parsed. To access the elements, you
135                 must call enterContainer(), read all elements, then call
136                 leaveContainer(). That function advances to the next element.
137    \endtable
138 
139    So a processor function typically looks like this:
140 
141    \snippet code/src_corelib_serialization_qcborstream.cpp 24
142 
143    \section1 CBOR support
144 
145    The following table lists the CBOR features that QCborStreamReader supports.
146 
147    \table
148      \header \li Feature                        \li Support
149      \row   \li Unsigned numbers                \li Yes (full range)
150      \row   \li Negative numbers                \li Yes (full range)
151      \row   \li Byte strings                    \li Yes
152      \row   \li Text strings                    \li Yes
153      \row   \li Chunked strings                 \li Yes
154      \row   \li Tags                            \li Yes (arbitrary)
155      \row   \li Booleans                        \li Yes
156      \row   \li Null                            \li Yes
157      \row   \li Undefined                       \li Yes
158      \row   \li Arbitrary simple values         \li Yes
159      \row   \li Half-precision float (16-bit)   \li Yes
160      \row   \li Single-precision float (32-bit) \li Yes
161      \row   \li Double-precision float (64-bit) \li Yes
162      \row   \li Infinities and NaN floating point \li Yes
163      \row   \li Determinate-length arrays and maps \li Yes
164      \row   \li Indeterminate-length arrays and maps \li Yes
165      \row   \li Map key types other than strings and integers \li Yes (arbitrary)
166    \endtable
167 
168    \section1 Dealing with invalid or incomplete CBOR streams
169 
170    QCborStreamReader is capable of detecting corrupt input on its own. The
171    library it uses has been extensively tested against invalid input of any
172    kind and is quite able to report errors. If any is detected,
173    QCborStreamReader will set lastError() to a value besides
174    QCborError::NoError, indicating which situation was detected.
175 
176    Most errors detected by QCborStreamReader during normal item parsing are not
177    recoverable. The code using QCborStreamReader may opt to handle the data
178    that was properly decoded or it can opt to discard the entire data.
179 
180    The only recoverable error is QCborError::EndOfFile, which indicates that
181    more data is required in order to complete the parsing. This situation is
182    useful when data is being read from an asynchronous source, such as a pipe
183    (QProcess) or a socket (QTcpSocket, QUdpSocket, QNetworkReply, etc.). When
184    more data arrives, the surrounding code needs to call either addData(), if
185    parsing from a QByteArray, or reparse(), if it is instead reading directly
186    a the QIDOevice that now has more data available (see setDevice()).
187 
188    \sa QCborStreamWriter, QCborValue, QXmlStreamReader
189  */
190 
191 /*!
192    \enum QCborStreamReader::Type
193 
194    This enumeration contains all possible CBOR types as decoded by
195    QCborStreamReader. CBOR has 7 major types, plus a number of simple types
196    carrying no value, and floating point values.
197 
198    \value UnsignedInteger       (Major type 0) Ranges from 0 to 2\sup{64} - 1
199                                 (18,446,744,073,709,551,616)
200    \value NegativeInteger       (Major type 1) Ranges from -1 to -2\sup{64}
201                                 (-18,446,744,073,709,551,616)
202    \value ByteArray             (Major type 2) Arbitrary binary data.
203    \value ByteString            An alias to ByteArray.
204    \value String                (Major type 3) Unicode text, possibly containing NULs.
205    \value TextString            An alias to String
206    \value Array                 (Major type 4) Array of heterogeneous items.
207    \value Map                   (Major type 5) Map/dictionary of heterogeneous items.
208    \value Tag                   (Major type 6) Numbers giving further semantic value
209                                 to generic CBOR items. See \l QCborTag for more information.
210    \value SimpleType            (Major type 7) Types carrying no further value. Includes
211                                 booleans (true and false), null, undefined.
212    \value Float16               IEEE 754 half-precision floating point (\c qfloat16).
213    \value HalfFloat             An alias to Float16.
214    \value Float                 IEEE 754 single-precision floating point (\tt float).
215    \value Double                IEEE 754 double-precision floating point (\tt double).
216    \value Invalid               Not a valid type, either due to parsing error or due to
217                                 reaching the end of an array or map.
218  */
219 
220 /*!
221    \enum QCborStreamReader::StringResultCode
222 
223    This enum is returned by readString() and readByteArray() and is used to
224    indicate what the status of the parsing is.
225 
226    \value EndOfString           The parsing for the string is complete, with no error.
227    \value Ok                    The function returned data; there was no error.
228    \value Error                 Parsing failed with an error.
229  */
230 
231 /*!
232    \class QCborStreamReader::StringResult
233    \inmodule QtCore
234 
235    This class is returned by readString() and readByteArray(), with either the
236    contents of the string that was read or an indication that the parsing is
237    done or found an error.
238 
239    The contents of \l data are valid only if \l status is
240    \l{StringResultCode}{Ok}. Otherwise, it should be null.
241  */
242 
243 /*!
244    \variable QCborStreamReader::StringResult::data
245 
246    Contains the actual data from the string if \l status is \c Ok.
247  */
248 
249 /*!
250    \variable QCborStreamReader::StringResult::status
251 
252    Contains the status of the attempt of reading the string from the stream.
253  */
254 
255 /*!
256    \fn QCborStreamReader::Type QCborStreamReader::type() const
257 
258    Returns the type of the current element. It is one of the valid types or
259    Invalid.
260 
261    \sa isValid(), isUnsignedInteger(), isNegativeInteger(), isInteger(),
262        isByteArray(), isString(), isArray(), isMap(), isTag(), isSimpleType(),
263        isBool(), isFalse(), isTrue(), isNull(), isUndefined(), isFloat16(),
264        isFloat(), isDouble()
265  */
266 
267 /*!
268    \fn bool QCborStreamReader::isValid() const
269 
270    Returns true if the current element is valid, false otherwise. The current
271    element may be invalid if there was a decoding error or we've just parsed
272    the last element in an array or map.
273 
274    \note This function is not the opposite of isNull(). Null is a normal CBOR
275    type that must be handled by the application.
276 
277    \sa type(), isInvalid()
278  */
279 
280 /*!
281     \fn bool QCborStreamReader::isInvalid() const
282 
283     Returns true if the current element is invalid, false otherwise. The current
284    element may be invalid if there was a decoding error or we've just parsed
285    the last element in an array or map.
286 
287    \note This function is not to be confused with isNull(). Null is a normal
288    CBOR type that must be handled by the application.
289 
290    \sa type(), isValid()
291  */
292 
293 /*!
294    \fn bool QCborStreamReader::isUnsignedInteger() const
295 
296    Returns true if the type of the current element is an unsigned integer (that
297    is if type() returns QCborStreamReader::UnsignedInteger). If this function
298    returns true, you may call toUnsignedInteger() or toInteger() to read that value.
299 
300    \sa type(), toUnsignedInteger(), toInteger(), isInteger(), isNegativeInteger()
301  */
302 
303 /*!
304    \fn bool QCborStreamReader::isNegativeInteger() const
305 
306    Returns true if the type of the current element is a negative integer (that
307    is if type() returns QCborStreamReader::NegativeInteger). If this function
308    returns true, you may call toNegativeInteger() or toInteger() to read that value.
309 
310    \sa type(), toNegativeInteger(), toInteger(), isInteger(), isUnsignedInteger()
311  */
312 
313 /*!
314    \fn bool QCborStreamReader::isInteger() const
315 
316    Returns true if the type of the current element is either an unsigned
317    integer or a negative one (that is, if type() returns
318    QCborStreamReader::UnsignedInteger or QCborStreamReader::NegativeInteger).
319    If this function returns true, you may call toInteger() to read that
320    value.
321 
322    \sa type(), toInteger(), toUnsignedInteger(), toNegativeInteger(),
323    isUnsignedInteger(), isNegativeInteger()
324  */
325 
326 /*!
327    \fn bool QCborStreamReader::isByteArray() const
328 
329    Returns true if the type of the current element is a byte array (that is,
330    if type() returns QCborStreamReader::ByteArray). If this function returns
331    true, you may call readByteArray() to read that data.
332 
333    \sa type(), readByteArray(), isString()
334  */
335 
336 /*!
337    \fn bool QCborStreamReader::isString() const
338 
339    Returns true if the type of the current element is a text string (that is,
340    if type() returns QCborStreamReader::String). If this function returns
341    true, you may call readString() to read that data.
342 
343    \sa type(), readString(), isByteArray()
344  */
345 
346 /*!
347    \fn bool QCborStreamReader::isArray() const
348 
349    Returns true if the type of the current element is an array (that is,
350    if type() returns QCborStreamReader::Array). If this function returns
351    true, you may call enterContainer() to begin parsing that container.
352 
353    When the current element is an array, you may also call isLengthKnown() to
354    find out if the array's size is explicit in the CBOR stream. If it is, that
355    size can be obtained by calling length().
356 
357    The following example pre-allocates a QVariantList given the array's size
358    for more efficient decoding:
359 
360    \snippet code/src_corelib_serialization_qcborstream.cpp 25
361 
362    \note The code above does not validate that the length is a sensible value.
363    If the input stream reports that the length is 1 billion elements, the above
364    function will try to allocate some 16 GB or more of RAM, which can lead to a
365    crash.
366 
367    \sa type(), isMap(), isLengthKnown(), length(), enterContainer(), leaveContainer()
368  */
369 
370 /*!
371    \fn bool QCborStreamReader::isMap() const
372 
373    Returns true if the type of the current element is a map (that is, if type()
374    returns QCborStreamReader::Map). If this function returns true, you may call
375    enterContainer() to begin parsing that container.
376 
377    When the current element is a map, you may also call isLengthKnown() to
378    find out if the map's size is explicit in the CBOR stream. If it is, that
379    size can be obtained by calling length().
380 
381    The following example pre-allocates a QVariantMap given the map's size
382    for more efficient decoding:
383 
384    \snippet code/src_corelib_serialization_qcborstream.cpp 26
385 
386    The example above uses a function called \c readElementAsString to read the
387    map's keys and obtain a string. That is because CBOR maps may contain any
388    type as keys, not just strings. User code needs to either perform this
389    conversion, reject non-string keys, or instead use a different container
390    besides \l QVariantMap and \l QVariantHash. For example, if the map is
391    expected to contain integer keys, which is recommended as it reduces stream
392    size and parsing, the correct container would be \c{\l{QMap}<int, QVariant>}
393    or \c{\l{QHash}<int, QVariant>}.
394 
395    \note The code above does not validate that the length is a sensible value.
396    If the input stream reports that the length is 1 billion elements, the above
397    function will try to allocate some 24 GB or more of RAM, which can lead to a
398    crash.
399 
400    \sa type(), isArray(), isLengthKnown(), length(), enterContainer(), leaveContainer()
401  */
402 
403 /*!
404    \fn bool QCborStreamReader::isTag() const
405 
406    Returns true if the type of the current element is a CBOR tag (that is,
407    if type() returns QCborStreamReader::Tag). If this function returns
408    true, you may call toTag() to read that data.
409 
410    \sa type(), toTag()
411  */
412 
413 /*!
414    \fn bool QCborStreamReader::isFloat16() const
415 
416    Returns true if the type of the current element is an IEEE 754
417    half-precision floating point (that is, if type() returns
418    QCborStreamReader::Float16). If this function returns true, you may call
419    toFloat16() to read that data.
420 
421    \sa type(), toFloat16(), isFloat(), isDouble()
422  */
423 
424 /*!
425    \fn bool QCborStreamReader::isFloat() const
426 
427    Returns true if the type of the current element is an IEEE 754
428    single-precision floating point (that is, if type() returns
429    QCborStreamReader::Float). If this function returns true, you may call
430    toFloat() to read that data.
431 
432    \sa type(), toFloat(), isFloat16(), isDouble()
433  */
434 
435 /*!
436    \fn bool QCborStreamReader::isDouble() const
437 
438    Returns true if the type of the current element is an IEEE 754
439    double-precision floating point (that is, if type() returns
440    QCborStreamReader::Double). If this function returns true, you may call
441    toDouble() to read that data.
442 
443    \sa type(), toDouble(), isFloat16(), isFloat()
444  */
445 
446 /*!
447    \fn bool QCborStreamReader::isSimpleType() const
448 
449    Returns true if the type of the current element is any CBOR simple type,
450    including a boolean value (true and false) as well as null and undefined. To
451    find out which simple type this is, call toSimpleType(). Alternatively, to
452    test for one specific simple type, call the overload that takes a
453    QCborSimpleType parameter.
454 
455    CBOR simple types are types that do not carry extra value. There are 255
456    possibilities, but there are currently only four values that have defined
457    meaning. Code is not expected to cope with unknown simple types and may
458    simply discard the stream as invalid if it finds an unknown one.
459 
460    \sa QCborSimpleType, type(), isSimpleType(QCborSimpleType), toSimpleType()
461  */
462 
463 /*!
464    \fn bool QCborStreamReader::isSimpleType(QCborSimpleType st) const
465 
466    Returns true if the type of the current element is the simple type \a st,
467    false otherwise. If this function returns true, then toSimpleType() will
468    return \a st.
469 
470    CBOR simple types are types that do not carry extra value. There are 255
471    possibilities, but there are currently only four values that have defined
472    meaning. Code is not expected to cope with unknown simple types and may
473    simply discard the stream as invalid if it finds an unknown one.
474 
475    \sa QCborSimpleType, type(), isSimpleType(), toSimpleType()
476  */
477 
478 /*!
479    \fn bool QCborStreamReader::isFalse() const
480 
481    Returns true if the current element is the \c false value, false if it is
482    anything else.
483 
484    \sa type(), isTrue(), isBool(), toBool(), isSimpleType(), toSimpleType()
485  */
486 
487 /*!
488    \fn bool QCborStreamReader::isTrue() const
489 
490    Returns true if the current element is the \c true value, false if it is
491    anything else.
492 
493    \sa type(), isFalse(), isBool(), toBool(), isSimpleType(), toSimpleType()
494  */
495 
496 /*!
497    \fn bool QCborStreamReader::isBool() const
498 
499    Returns true if the current element is a boolean value (\c true or \c
500    false), false if it is anything else. If this function returns true, you may
501    call toBool() to retrieve the value of the boolean. You may also call
502    toSimpleType() and compare to either QCborSimpleValue::True or
503    QCborSimpleValue::False.
504 
505    \sa type(), isFalse(), isTrue(), toBool(), isSimpleType(), toSimpleType()
506  */
507 
508 /*!
509    \fn bool QCborStreamReader::isNull() const
510 
511    Returns true if the current element is the \c null value, false if it is
512    anything else. Null values may be used to indicate the absence of some
513    optional data.
514 
515    \note This function is not the opposite of isValid(). A Null value is a
516    valid CBOR value.
517 
518    \sa type(), isSimpleType(), toSimpleType()
519  */
520 
521 /*!
522    \fn bool QCborStreamReader::isUndefined() const
523 
524    Returns true if the current element is the \c undefined value, false if it
525    is anything else. Undefined values may be encoded to indicate that some
526    conversion failed or was not possible when creating the stream.
527    QCborStreamReader never performs any replacement and this function will only
528    return true if the stream contains an explicit undefined value.
529 
530    \sa type(), isSimpleType(), toSimpleType()
531  */
532 
533 /*!
534    \fn bool QCborStreamReader::isContainer() const
535 
536    Returns true if the current element is a container (that is, an array or a
537    map), false if it is anything else. If the current element is a container,
538    the isLengthKnown() function may be used to find out if the container's size
539    is explicit in the stream and, if so, length() can be used to get that size.
540 
541    More importantly, for a container, the enterContainer() function is
542    available to begin iterating through the elements contained therein.
543 
544    \sa type(), isArray(), isMap(), isLengthKnown(), length(), enterContainer(),
545        leaveContainer(), containerDepth()
546  */
547 
548 class QCborStreamReaderPrivate
549 {
550 public:
551     enum {
552         // 9 bytes is the maximum size for any integer, floating point or
553         // length in CBOR.
554         MaxCborIndividualSize = 9,
555         IdealIoBufferSize = 256
556     };
557 
558     QIODevice *device;
559     QByteArray buffer;
560     QStack<CborValue> containerStack;
561 
562     CborParser parser;
563     CborValue currentElement;
564     QCborError lastError = {};
565 
566     QByteArray::size_type bufferStart;
567     bool corrupt = false;
568 
QCborStreamReaderPrivate(const QByteArray & data)569     QCborStreamReaderPrivate(const QByteArray &data)
570         : device(nullptr), buffer(data)
571     {
572         initDecoder();
573     }
574 
QCborStreamReaderPrivate(QIODevice * device)575     QCborStreamReaderPrivate(QIODevice *device)
576     {
577         setDevice(device);
578     }
579 
~QCborStreamReaderPrivate()580     ~QCborStreamReaderPrivate()
581     {
582     }
583 
setDevice(QIODevice * dev)584     void setDevice(QIODevice *dev)
585     {
586         buffer.clear();
587         device = dev;
588         initDecoder();
589     }
590 
initDecoder()591     void initDecoder()
592     {
593         containerStack.clear();
594         bufferStart = 0;
595         if (device) {
596             buffer.clear();
597             buffer.reserve(IdealIoBufferSize);      // sets the CapacityReserved flag
598         }
599 
600         preread();
601         if (CborError err = cbor_parser_init_reader(nullptr, &parser, &currentElement, this))
602             handleError(err);
603         else
604             lastError = { QCborError::NoError };
605     }
606 
bufferPtr()607     char *bufferPtr()
608     {
609         Q_ASSERT(buffer.isDetached());
610         return const_cast<char *>(buffer.constData()) + bufferStart;
611     }
612 
preread()613     void preread()
614     {
615         if (device && buffer.size() - bufferStart < MaxCborIndividualSize) {
616             // load more, but only if there's more to be read
617             qint64 avail = device->bytesAvailable();
618             Q_ASSERT(avail >= buffer.size());
619             if (avail == buffer.size())
620                 return;
621 
622             if (bufferStart)
623                 device->skip(bufferStart);  // skip what we've already parsed
624 
625             if (buffer.size() != IdealIoBufferSize)
626                 buffer.resize(IdealIoBufferSize);
627 
628             bufferStart = 0;
629             qint64 read = device->peek(bufferPtr(), IdealIoBufferSize);
630             if (read < 0)
631                 buffer.clear();
632             else if (read != IdealIoBufferSize)
633                 buffer.truncate(read);
634         }
635     }
636 
handleError(CborError err)637     void handleError(CborError err) noexcept
638     {
639         Q_ASSERT(err);
640 
641         // is the error fatal?
642         if (err != CborErrorUnexpectedEOF)
643             corrupt = true;
644 
645         lastError = QCborError { QCborError::Code(int(err)) };
646     }
647 
updateBufferAfterString(qsizetype offset,qsizetype size)648     void updateBufferAfterString(qsizetype offset, qsizetype size)
649     {
650         Q_ASSERT(device);
651 
652         bufferStart += offset;
653         qsizetype newStart = bufferStart + size;
654         qsizetype remainingInBuffer = buffer.size() - newStart;
655 
656         if (remainingInBuffer <= 0) {
657             // We've read from the QIODevice more than what was in the buffer.
658             buffer.truncate(0);
659         } else {
660             // There's still data buffered, but we need to move it around.
661             char *ptr = buffer.data();
662             memmove(ptr, ptr + newStart, remainingInBuffer);
663             buffer.truncate(remainingInBuffer);
664         }
665 
666         bufferStart = 0;
667     }
668 
669     bool ensureStringIteration();
670     QCborStreamReader::StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
671 };
672 
qt_cbor_stream_set_error(QCborStreamReaderPrivate * d,QCborError error)673 void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error)
674 {
675     d->handleError(CborError(error.c));
676 }
677 
qt_cbor_decoder_can_read(void * token,size_t len)678 static inline bool qt_cbor_decoder_can_read(void *token, size_t len)
679 {
680     Q_ASSERT(len <= QCborStreamReaderPrivate::MaxCborIndividualSize);
681     auto self = static_cast<QCborStreamReaderPrivate *>(token);
682 
683     qint64 avail = self->buffer.size() - self->bufferStart;
684     return len <= quint64(avail);
685 }
686 
qt_cbor_decoder_advance(void * token,size_t len)687 static void qt_cbor_decoder_advance(void *token, size_t len)
688 {
689     Q_ASSERT(len <= QCborStreamReaderPrivate::MaxCborIndividualSize);
690     auto self = static_cast<QCborStreamReaderPrivate *>(token);
691     Q_ASSERT(len <= size_t(self->buffer.size() - self->bufferStart));
692 
693     self->bufferStart += int(len);
694     self->preread();
695 }
696 
qt_cbor_decoder_read(void * token,void * userptr,size_t offset,size_t len)697 static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len)
698 {
699     Q_ASSERT(len == 1 || len == 2 || len == 4 || len == 8);
700     Q_ASSERT(offset == 0 || offset == 1);
701     auto self = static_cast<const QCborStreamReaderPrivate *>(token);
702 
703     // we must have pre-read the data
704     Q_ASSERT(len + offset <= size_t(self->buffer.size() - self->bufferStart));
705     return memcpy(userptr, self->buffer.constData() + self->bufferStart + offset, len);
706 }
707 
qt_cbor_decoder_transfer_string(void * token,const void ** userptr,size_t offset,size_t len)708 static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len)
709 {
710     auto self = static_cast<QCborStreamReaderPrivate *>(token);
711     Q_ASSERT(offset <= size_t(self->buffer.size()));
712     Q_STATIC_ASSERT(sizeof(size_t) >= sizeof(QByteArray::size_type));
713     Q_STATIC_ASSERT(sizeof(size_t) == sizeof(qsizetype));
714 
715     // check that we will have enough data from the QIODevice before we advance
716     // (otherwise, we'd lose the length information)
717     qsizetype total;
718     if (len > size_t(std::numeric_limits<QByteArray::size_type>::max())
719             || add_overflow<qsizetype>(offset, len, &total))
720         return CborErrorDataTooLarge;
721 
722     // our string transfer is just saving the offset to the userptr
723     *userptr = reinterpret_cast<void *>(offset);
724 
725     qint64 avail = (self->device ? self->device->bytesAvailable() : self->buffer.size()) -
726             self->bufferStart;
727     return total > avail ? CborErrorUnexpectedEOF : CborNoError;
728 }
729 
ensureStringIteration()730 bool QCborStreamReaderPrivate::ensureStringIteration()
731 {
732     if (currentElement.flags & CborIteratorFlag_IteratingStringChunks)
733         return true;
734 
735     CborError err = cbor_value_begin_string_iteration(&currentElement);
736     if (!err)
737         return true;
738     handleError(err);
739     return false;
740 }
741 
742 /*!
743    \internal
744  */
preparse()745 inline void QCborStreamReader::preparse()
746 {
747     if (lastError() == QCborError::NoError) {
748         type_ = cbor_value_get_type(&d->currentElement);
749 
750         if (type_ == CborInvalidType) {
751             // We may have reached the end.
752             if (d->device && d->containerStack.isEmpty()) {
753                 d->buffer.clear();
754                 if (d->bufferStart)
755                     d->device->skip(d->bufferStart);
756                 d->bufferStart = 0;
757             }
758         } else {
759             d->lastError = {};
760             // Undo the type mapping that TinyCBOR does (we have an explicit type
761             // for negative integer and we don't have separate types for Boolean,
762             // Null and Undefined).
763             if (type_ == CborBooleanType || type_ == CborNullType || type_ == CborUndefinedType) {
764                 type_ = CborSimpleType;
765                 value64 = quint8(d->buffer.at(d->bufferStart)) - CborSimpleType;
766             } else {
767                 // Using internal TinyCBOR API!
768                 value64 = _cbor_value_extract_int64_helper(&d->currentElement);
769 
770                 if (cbor_value_is_negative_integer(&d->currentElement))
771                     type_ = quint8(QCborStreamReader::NegativeInteger);
772             }
773         }
774     } else {
775         type_ = Invalid;
776     }
777 }
778 
779 /*!
780    Creates a QCborStreamReader object with no source data. After construction,
781    QCborStreamReader will report an error parsing.
782 
783    You can add more data by calling addData() or by setting a different source
784    device using setDevice().
785 
786    \sa addData(), isValid()
787  */
QCborStreamReader()788 QCborStreamReader::QCborStreamReader()
789     : QCborStreamReader(QByteArray())
790 {
791 }
792 
793 /*!
794    \overload
795 
796    Creates a QCborStreamReader object with \a len bytes of data starting at \a
797    data. The pointer must remain valid until QCborStreamReader is destroyed.
798  */
QCborStreamReader(const char * data,qsizetype len)799 QCborStreamReader::QCborStreamReader(const char *data, qsizetype len)
800     : QCborStreamReader(QByteArray::fromRawData(data, len))
801 {
802 }
803 
804 /*!
805    \overload
806 
807    Creates a QCborStreamReader object with \a len bytes of data starting at \a
808    data. The pointer must remain valid until QCborStreamReader is destroyed.
809  */
QCborStreamReader(const quint8 * data,qsizetype len)810 QCborStreamReader::QCborStreamReader(const quint8 *data, qsizetype len)
811     : QCborStreamReader(QByteArray::fromRawData(reinterpret_cast<const char *>(data), len))
812 {
813 }
814 
815 /*!
816    \overload
817 
818    Creates a QCborStreamReader object that will parse the CBOR stream found in
819    \a data.
820  */
QCborStreamReader(const QByteArray & data)821 QCborStreamReader::QCborStreamReader(const QByteArray &data)
822     : d(new QCborStreamReaderPrivate(data))
823 {
824     preparse();
825 }
826 
827 /*!
828    \overload
829 
830    Creates a QCborStreamReader object that will parse the CBOR stream found by
831    reading from \a device. QCborStreamReader does not take ownership of \a
832    device, so it must remain valid until this oject is destroyed.
833  */
QCborStreamReader(QIODevice * device)834 QCborStreamReader::QCborStreamReader(QIODevice *device)
835     : d(new QCborStreamReaderPrivate(device))
836 {
837     preparse();
838 }
839 
840 /*!
841    Destroys this QCborStreamReader object and frees any associated resources.
842  */
~QCborStreamReader()843 QCborStreamReader::~QCborStreamReader()
844 {
845 }
846 
847 /*!
848    Sets the source of data to \a device, resetting the decoder to its initial
849    state.
850  */
setDevice(QIODevice * device)851 void QCborStreamReader::setDevice(QIODevice *device)
852 {
853     d->setDevice(device);
854     preparse();
855 }
856 
857 /*!
858    Returns the QIODevice that was set with either setDevice() or the
859    QCborStreamReader constructor. If this object was reading from a QByteArray,
860    this function returns nullptr instead.
861  */
device() const862 QIODevice *QCborStreamReader::device() const
863 {
864     return d->device;
865 }
866 
867 /*!
868    Adds \a data to the CBOR stream and reparses the current element. This
869    function is useful if the end of the data was previously reached while
870    processing the stream, but now more data is available.
871  */
addData(const QByteArray & data)872 void QCborStreamReader::addData(const QByteArray &data)
873 {
874     addData(data.constData(), data.size());
875 }
876 
877 /*!
878    \fn void QCborStreamReader::addData(const quint8 *data, qsizetype len)
879    \overload
880 
881    Adds \a len bytes of data starting at \a data to the CBOR stream and
882    reparses the current element. This function is useful if the end of the data
883    was previously reached while processing the stream, but now more data is
884    available.
885  */
886 
887 /*!
888    \overload
889 
890    Adds \a len bytes of data starting at \a data to the CBOR stream and
891    reparses the current element. This function is useful if the end of the data
892    was previously reached while processing the stream, but now more data is
893    available.
894  */
addData(const char * data,qsizetype len)895 void QCborStreamReader::addData(const char *data, qsizetype len)
896 {
897     if (!d->device) {
898         if (len > 0)
899             d->buffer.append(data, len);
900         reparse();
901     } else {
902         qWarning("QCborStreamReader: addData() with device()");
903     }
904 }
905 
906 /*!
907    Reparses the current element. This function must be called when more data
908    becomes available in the source QIODevice after parsing failed due to
909    reaching the end of the input data before the end of the CBOR stream.
910 
911    When reading from QByteArray(), the addData() function automatically calls
912    this function. Calling it when the reading had not failed is a no-op.
913  */
reparse()914 void QCborStreamReader::reparse()
915 {
916     d->lastError = {};
917     d->preread();
918     if (CborError err = cbor_value_reparse(&d->currentElement))
919         d->handleError(err);
920     else
921         preparse();
922 }
923 
924 /*!
925    Clears the decoder state and resets the input source data to an empty byte
926    array. After this function is called, QCborStreamReader will be indicating
927    an error parsing.
928 
929    Call addData() to add more data to be parsed.
930 
931    \sa reset(), setDevice()
932  */
clear()933 void QCborStreamReader::clear()
934 {
935     setDevice(nullptr);
936 }
937 
938 /*!
939    Resets the source back to the beginning and clears the decoder state. If the
940    source data was a QByteArray, QCborStreamReader will restart from the
941    beginning of the array.
942 
943    If the source data is a QIODevice, this function will call
944    QIODevice::reset(), which will seek to byte position 0. If the CBOR stream
945    is not found at the beginning of the device (e.g., beginning of a file),
946    then this function will likely do the wrong thing. Instead, position the
947    QIODevice to the right offset and call setDevice().
948 
949    \sa clear(), setDevice()
950  */
reset()951 void QCborStreamReader::reset()
952 {
953     if (d->device)
954         d->device->reset();
955     d->lastError = {};
956     d->initDecoder();
957     preparse();
958 }
959 
960 /*!
961    Returns the last error in decoding the stream, if any. If no error
962    was encountered, this returns an QCborError::NoError.
963 
964    \sa isValid()
965  */
lastError()966 QCborError QCborStreamReader::lastError()
967 {
968     return d->lastError;
969 }
970 
971 /*!
972    Returns the offset in the input stream of the item currently being decoded.
973    The current offset is the number of decoded bytes so far only if the source
974    data is a QByteArray or it is a QIODevice that was positioned at its
975    beginning when decoding started.
976 
977    \sa reset(), clear(), device()
978  */
currentOffset() const979 qint64 QCborStreamReader::currentOffset() const
980 {
981     return (d->device ? d->device->pos() : 0) + d->bufferStart;
982 }
983 
984 /*!
985    Returns the number of containers that this stream has entered with
986    enterContainer() but not yet left.
987 
988    \sa enterContainer(), leaveContainer()
989  */
containerDepth() const990 int QCborStreamReader::containerDepth() const
991 {
992     return d->containerStack.size();
993 }
994 
995 /*!
996    Returns either QCborStreamReader::Array or QCborStreamReader::Map,
997    indicating whether the container that contains the current item was an array
998    or map, respectively. If we're currently parsing the root element, this
999    function returns QCborStreamReader::Invalid.
1000 
1001    \sa containerDepth(), enterContainer()
1002  */
parentContainerType() const1003 QCborStreamReader::Type QCborStreamReader::parentContainerType() const
1004 {
1005     if (d->containerStack.isEmpty())
1006         return Invalid;
1007     return Type(cbor_value_get_type(&qAsConst(d->containerStack).top()));
1008 }
1009 
1010 /*!
1011    Returns true if there are more items to be decoded in the current container
1012    or false of we've reached its end. If we're parsing the root element,
1013    hasNext() returning false indicates the parsing is complete; otherwise, if
1014    the container depth is non-zero, then the outer code needs to call
1015    leaveContainer().
1016 
1017    \sa parentContainerType(), containerDepth(), leaveContainer()
1018  */
hasNext() const1019 bool QCborStreamReader::hasNext() const noexcept
1020 {
1021     return cbor_value_is_valid(&d->currentElement) &&
1022             !cbor_value_at_end(&d->currentElement);
1023 }
1024 
1025 /*!
1026    Advance the CBOR stream decoding one element. You should usually call this
1027    function when parsing fixed-width basic elements (that is, integers, simple
1028    values, tags and floating point values). But this function can be called
1029    when the current item is a string, array or map too and it will skip over
1030    that entire element, including all contained elements.
1031 
1032    This function returns true if advancing was successful, false otherwise. It
1033    may fail if the stream is corrupt, incomplete or if the nesting level of
1034    arrays and maps exceeds \a maxRecursion. Calling this function when
1035    hasNext() has returned false is also an error. If this function returns
1036    false, lastError() will return the error code detailing what the failure
1037    was.
1038 
1039    \sa lastError(), isValid(), hasNext()
1040  */
next(int maxRecursion)1041 bool QCborStreamReader::next(int maxRecursion)
1042 {
1043     if (lastError() != QCborError::NoError)
1044         return false;
1045 
1046     if (!hasNext()) {
1047         d->handleError(CborErrorAdvancePastEOF);
1048     } else if (maxRecursion < 0) {
1049         d->handleError(CborErrorNestingTooDeep);
1050     } else if (isContainer()) {
1051         // iterate over each element
1052         enterContainer();
1053         while (lastError() == QCborError::NoError && hasNext())
1054             next(maxRecursion - 1);
1055         if (lastError() == QCborError::NoError)
1056             leaveContainer();
1057     } else if (isString() || isByteArray()) {
1058         auto r = _readByteArray_helper();
1059         while (r.status == Ok) {
1060             if (isString() && r.data.size() > MaxStringSize) {
1061                 d->handleError(CborErrorDataTooLarge);
1062                 break;
1063             }
1064             if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) {
1065                 d->handleError(CborErrorInvalidUtf8TextString);
1066                 break;
1067             }
1068             r = _readByteArray_helper();
1069         }
1070     } else {
1071         // fixed types
1072         CborError err = cbor_value_advance_fixed(&d->currentElement);
1073         if (err)
1074             d->handleError(err);
1075     }
1076 
1077     preparse();
1078     return d->lastError == QCborError::NoError;
1079 }
1080 
1081 /*!
1082    Returns true if the length of the current array, map, byte array or string
1083    is known (explicit in the CBOR stream), false otherwise. This function
1084    should only be called if the element is one of those.
1085 
1086    If the length is known, it may be obtained by calling length().
1087 
1088    If the length of a map or an array is not known, it is implied by the number
1089    of elements present in the stream. QCborStreamReader has no API to calculate
1090    the length in that condition.
1091 
1092    Strings and byte arrays may also have indeterminate length (that is, they
1093    may be transmitted in multiple chunks). Those cannot currently be created
1094    with QCborStreamWriter, but they could be with other encoders, so
1095    QCborStreamReader supports them.
1096 
1097    \sa length(), QCborStreamWriter::startArray(), QCborStreamWriter::startMap()
1098  */
isLengthKnown() const1099 bool QCborStreamReader::isLengthKnown() const noexcept
1100 {
1101     return cbor_value_is_length_known(&d->currentElement);
1102 }
1103 
1104 /*!
1105    Returns the length of the string or byte array, or the number of items in an
1106    array or the number, of item pairs in a map, if known. This function must
1107    not be called if the length is unknown (that is, if isLengthKnown() returned
1108    false). It is an error to do that and it will cause QCborStreamReader to
1109    stop parsing the input stream.
1110 
1111    \sa isLengthKnown(), QCborStreamWriter::startArray(), QCborStreamWriter::startMap()
1112  */
length() const1113 quint64 QCborStreamReader::length() const
1114 {
1115     CborError err;
1116     switch (type()) {
1117     case String:
1118     case ByteArray:
1119     case Map:
1120     case Array:
1121         if (isLengthKnown())
1122             return value64;
1123         err = CborErrorUnknownLength;
1124         break;
1125 
1126     default:
1127         err = CborErrorIllegalType;
1128         break;
1129     }
1130 
1131     d->handleError(err);
1132     return quint64(-1);
1133 }
1134 
1135 /*!
1136    \fn bool QCborStreamReader::enterContainer()
1137 
1138    Enters the array or map that is the current item and prepares for iterating
1139    the elements contained in the container. Returns true if entering the
1140    container succeeded, false otherwise (usually, a parsing error). Each call
1141    to enterContainer() must be paired with a call to leaveContainer().
1142 
1143    This function may only be called if the current item is an array or a map
1144    (that is, if isArray(), isMap() or isContainer() is true). Calling it in any
1145    other condition is an error.
1146 
1147    \sa leaveContainer(), isContainer(), isArray(), isMap()
1148  */
_enterContainer_helper()1149 bool QCborStreamReader::_enterContainer_helper()
1150 {
1151     d->containerStack.push(d->currentElement);
1152     CborError err = cbor_value_enter_container(&d->containerStack.top(), &d->currentElement);
1153     if (!err) {
1154         preparse();
1155         return true;
1156     }
1157     d->handleError(err);
1158     return false;
1159 }
1160 
1161 /*!
1162    Leaves the array or map whose items were being processed and positions the
1163    decoder at the next item after the end of the container. Returns true if
1164    leaving the container succeeded, false otherwise (usually, a parsing error).
1165    Each call to enterContainer() must be paired with a call to
1166    leaveContainer().
1167 
1168    This function may only be called if hasNext() has returned false and
1169    containerDepth() is not zero. Calling it in any other condition is an error.
1170 
1171    \sa enterContainer(), parentContainerType(), containerDepth()
1172  */
leaveContainer()1173 bool QCborStreamReader::leaveContainer()
1174 {
1175     if (d->containerStack.isEmpty()) {
1176         qWarning("QCborStreamReader::leaveContainer: trying to leave top-level element");
1177         return false;
1178     }
1179     if (d->corrupt)
1180         return false;
1181 
1182     CborValue container = d->containerStack.pop();
1183     CborError err = cbor_value_leave_container(&container, &d->currentElement);
1184     d->currentElement = container;
1185     if (err) {
1186         d->handleError(err);
1187         return false;
1188     }
1189 
1190     preparse();
1191     return true;
1192 }
1193 
1194 /*!
1195    \fn bool QCborStreamReader::toBool() const
1196 
1197    Returns the boolean value of the current element.
1198 
1199    This function does not perform any type conversions, including from integer.
1200    Therefore, it may only be called if isTrue(), isFalse() or isBool() returned
1201    true; calling it in any other condition is an error.
1202 
1203    \sa isBool(), isTrue(), isFalse(), toInteger()
1204  */
1205 
1206 /*!
1207    \fn QCborTag QCborStreamReader::toTag() const
1208 
1209    Returns the tag value of the current element.
1210 
1211    This function does not perform any type conversions, including from integer.
1212    Therefore, it may only be called if isTag() is true; calling it in any other
1213    condition is an error.
1214 
1215    Tags are 64-bit numbers attached to generic CBOR types that give them
1216    further meaning. For a list of known tags, see the \l QCborKnownTags
1217    enumeration.
1218 
1219    \sa isTag(), toInteger(), QCborKnownTags
1220  */
1221 
1222 /*!
1223    \fn quint64 QCborStreamReader::toUnsignedInteger() const
1224 
1225    Returns the unsigned integer value of the current element.
1226 
1227    This function does not perform any type conversions, including from boolean
1228    or CBOR tag. Therefore, it may only be called if isUnsignedInteger() is
1229    true; calling it in any other condition is an error.
1230 
1231    This function may be used to obtain numbers beyond the range of the return
1232    type of toInteger().
1233 
1234    \sa type(), toInteger(), isUnsignedInteger(), isNegativeInteger()
1235  */
1236 
1237 /*!
1238    \fn QCborNegativeValue QCborStreamReader::toNegativeInteger() const
1239 
1240    Returns the negative integer value of the current element.
1241    QCborNegativeValue is a 64-bit unsigned integer containing the absolute
1242    value of the negative number that was stored in the CBOR stream.
1243    Additionally, QCborNegativeValue(0) represents the number -2\sup{64}.
1244 
1245    This function does not perform any type conversions, including from boolean
1246    or CBOR tag. Therefore, it may only be called if isNegativeInteger() is
1247    true; calling it in any other condition is an error.
1248 
1249    This function may be used to obtain numbers beyond the range of the return
1250    type of toInteger(). However, use of negative numbers smaller than -2\sup{63}
1251    is extremely discouraged.
1252 
1253    \sa type(), toInteger(), isNegativeInteger(), isUnsignedInteger()
1254  */
1255 
1256 /*!
1257    \fn qint64 QCborStreamReader::toInteger() const
1258 
1259    Returns the integer value of the current element, be it negative, positive
1260    or zero. If the value is larger than 2\sup{63} - 1 or smaller than
1261    -2\sup{63}, the returned value will overflow and will have an incorrect
1262    sign. If handling those values is required, use toUnsignedInteger() or
1263    toNegativeInteger() instead.
1264 
1265    This function does not perform any type conversions, including from boolean
1266    or CBOR tag. Therefore, it may only be called if isInteger() is true;
1267    calling it in any other condition is an error.
1268 
1269    \sa isInteger(), toUnsignedInteger(), toNegativeInteger()
1270  */
1271 
1272 /*!
1273    \fn QCborSimpleType QCborStreamReader::toSimpleType() const
1274 
1275    Returns value of the current simple type.
1276 
1277    This function does not perform any type conversions, including from integer.
1278    Therefore, it may only be called if isSimpleType() is true; calling it in
1279    any other condition is an error.
1280 
1281    \sa isSimpleType(), isTrue(), isFalse(), isBool(), isNull(), isUndefined()
1282  */
1283 
1284 /*!
1285    \fn qfloat16 QCborStreamReader::toFloat16() const
1286 
1287    Returns the 16-bit half-precision floating point value of the current element.
1288 
1289    This function does not perform any type conversions, including from other
1290    floating point types or from integer values. Therefore, it may only be
1291    called if isFloat16() is true; calling it in any other condition is an
1292    error.
1293 
1294    \sa isFloat16(), toFloat(), toDouble()
1295  */
1296 
1297 /*!
1298    \fn float QCborStreamReader::toFloat() const
1299 
1300    Returns the 32-bit single-precision floating point value of the current
1301    element.
1302 
1303    This function does not perform any type conversions, including from other
1304    floating point types or from integer values. Therefore, it may only be
1305    called if isFloat() is true; calling it in any other condition is an error.
1306 
1307    \sa isFloat(), toFloat16(), toDouble()
1308  */
1309 
1310 /*!
1311    \fn double QCborStreamReader::toDouble() const
1312 
1313    Returns the 64-bit double-precision floating point value of the current
1314    element.
1315 
1316    This function does not perform any type conversions, including from other
1317    floating point types or from integer values. Therefore, it may only be
1318    called if isDouble() is true; calling it in any other condition is an error.
1319 
1320    \sa isDouble(), toFloat16(), toFloat()
1321  */
1322 
1323 /*!
1324    \fn QCborStreamReader::StringResult<QString> QCborStreamReader::readString()
1325 
1326    Decodes one string chunk from the CBOR string and returns it. This function
1327    is used for both regular and chunked string contents, so the caller must
1328    always loop around calling this function, even if isLengthKnown() has
1329    is true. The typical use of this function is as follows:
1330 
1331    \snippet code/src_corelib_serialization_qcborstream.cpp 27
1332 
1333    This function does not perform any type conversions, including from integers
1334    or from byte arrays. Therefore, it may only be called if isString() returned
1335    true; calling it in any other condition is an error.
1336 
1337    \sa readByteArray(), isString(), readStringChunk()
1338  */
_readString_helper()1339 QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
1340 {
1341     auto r = _readByteArray_helper();
1342     QCborStreamReader::StringResult<QString> result;
1343     result.status = r.status;
1344 
1345     if (r.status == Ok) {
1346         // See QUtf8::convertToUnicode() a detailed explanation of why this
1347         // conversion uses the same number of words or less.
1348         CborError err = CborNoError;
1349         if (r.data.size() > MaxStringSize) {
1350             err = CborErrorDataTooLarge;
1351         } else {
1352             QTextCodec::ConverterState cs;
1353             result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
1354             if (cs.invalidChars != 0 || cs.remainingChars != 0)
1355                 err = CborErrorInvalidUtf8TextString;
1356         }
1357 
1358         if (err) {
1359             d->handleError(err);
1360             result.data.clear();
1361             result.status = Error;
1362         }
1363     }
1364     return result;
1365 }
1366 
1367 /*!
1368    \fn QCborStreamReader::StringResult<QString> QCborStreamReader::readByteArray()
1369 
1370    Decodes one byte array chunk from the CBOR string and returns it. This
1371    function is used for both regular and chunked contents, so the caller must
1372    always loop around calling this function, even if isLengthKnown() has
1373    is true. The typical use of this function is as follows:
1374 
1375    \snippet code/src_corelib_serialization_qcborstream.cpp 28
1376 
1377    This function does not perform any type conversions, including from integers
1378    or from strings. Therefore, it may only be called if isByteArray() is true;
1379    calling it in any other condition is an error.
1380 
1381    \sa readString(), isByteArray(), readStringChunk()
1382  */
_readByteArray_helper()1383 QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_helper()
1384 {
1385     QCborStreamReader::StringResult<QByteArray> result;
1386     result.status = Error;
1387     qsizetype len = _currentStringChunkSize();
1388     if (len < 0)
1389         return result;
1390     if (len > MaxByteArraySize) {
1391         d->handleError(CborErrorDataTooLarge);
1392         return result;
1393     }
1394 
1395     result.data.resize(len);
1396     auto r = readStringChunk(result.data.data(), len);
1397     Q_ASSERT(r.status != Ok || r.data == len);
1398     result.status = r.status;
1399     return result;
1400 }
1401 
1402 /*!
1403     \fn qsizetype QCborStreamReader::currentStringChunkSize() const
1404 
1405     Returns the size of the current text or byte string chunk. If the CBOR
1406     stream contains a non-chunked string (that is, if isLengthKnown() returns
1407     \c true), this function returns the size of the entire string, the same as
1408     length().
1409 
1410     This function is useful to pre-allocate the buffer whose pointer can be passed
1411     to readStringChunk() later.
1412 
1413     \sa readString(), readByteArray(), readStringChunk()
1414  */
_currentStringChunkSize() const1415 qsizetype QCborStreamReader::_currentStringChunkSize() const
1416 {
1417     if (!d->ensureStringIteration())
1418         return -1;
1419 
1420     size_t len;
1421     CborError err = cbor_value_get_string_chunk_size(&d->currentElement, &len);
1422     if (err == CborErrorNoMoreStringChunks)
1423         return 0;           // not a real error
1424     else if (err)
1425         d->handleError(err);
1426     else if (qsizetype(len) < 0)
1427         d->handleError(CborErrorDataTooLarge);
1428     else
1429         return qsizetype(len);
1430     return -1;
1431 }
1432 
1433 /*!
1434     Reads the current string chunk into the buffer pointed to by \a ptr, whose
1435     size is \a maxlen. This function returns a \l StringResult object, with the
1436     number of bytes copied into \a ptr saved in the \c \l StringResult::data
1437     member. The \c \l StringResult::status member indicates whether there was
1438     an error reading the string, whether data was copied or whether this was
1439     the last chunk.
1440 
1441     This function can be called for both \l String and \l ByteArray types.
1442     For the latter, this function will read the same data that readByteArray()
1443     would have returned. For strings, it returns the UTF-8 equivalent of the \l
1444     QString that would have been returned.
1445 
1446     This function is usually used alongside currentStringChunkSize() in a loop.
1447     For example:
1448 
1449    \snippet code/src_corelib_serialization_qcborstream.cpp 29
1450 
1451     Unlike readByteArray() and readString(), this function is not limited by
1452     implementation limits of QByteArray and QString.
1453 
1454     \note This function does not perform verification that the UTF-8 contents
1455     are properly formatted. That means this function does not produce the
1456     QCborError::InvalidUtf8String error, even when readString() does.
1457 
1458     \sa currentStringChunkSize(), readString(), readByteArray(),
1459         isString(), isByteArray()
1460  */
1461 QCborStreamReader::StringResult<qsizetype>
readStringChunk(char * ptr,qsizetype maxlen)1462 QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
1463 {
1464     auto r = d->readStringChunk(ptr, maxlen);
1465     if (r.status == EndOfString && lastError() == QCborError::NoError)
1466         preparse();
1467     return r;
1468 }
1469 
1470 QCborStreamReader::StringResult<qsizetype>
readStringChunk(char * ptr,qsizetype maxlen)1471 QCborStreamReaderPrivate::readStringChunk(char *ptr, qsizetype maxlen)
1472 {
1473     CborError err;
1474     size_t len;
1475     const void *content = nullptr;
1476     QCborStreamReader::StringResult<qsizetype> result;
1477     result.data = 0;
1478     result.status = QCborStreamReader::Error;
1479 
1480     lastError = {};
1481     if (!ensureStringIteration())
1482         return result;
1483 
1484 #if 1
1485     // Using internal TinyCBOR API!
1486     err = _cbor_value_get_string_chunk(&currentElement, &content, &len, &currentElement);
1487 #else
1488     // the above is effectively the same as:
1489     if (cbor_value_is_byte_string(&currentElement))
1490         err = cbor_value_get_byte_string_chunk(&currentElement, reinterpret_cast<const uint8_t **>(&content),
1491                                                &len, &currentElement);
1492     else
1493         err = cbor_value_get_text_string_chunk(&currentElement, reinterpret_cast<const char **>(&content),
1494                                                &len, &currentElement);
1495 #endif
1496 
1497     // Range check: using implementation-defined behavior in converting an
1498     // unsigned value out of range of the destination signed type (same as
1499     // "len > size_t(std::numeric_limits<qsizetype>::max())", but generates
1500     // better code with ICC and MSVC).
1501     if (!err && qsizetype(len) < 0)
1502         err = CborErrorDataTooLarge;
1503 
1504     if (err) {
1505         if (err == CborErrorNoMoreStringChunks) {
1506             preread();
1507             err = cbor_value_finish_string_iteration(&currentElement);
1508             result.status = QCborStreamReader::EndOfString;
1509         }
1510         if (err)
1511             handleError(err);
1512         // caller musts call preparse()
1513         return result;
1514     }
1515 
1516     // Read the chunk into the user's buffer.
1517     qint64 actuallyRead;
1518     qptrdiff offset = qptrdiff(content);
1519     qsizetype toRead = qsizetype(len);
1520     qsizetype left = toRead - maxlen;
1521     if (left < 0)
1522         left = 0;               // buffer bigger than string
1523     else
1524         toRead = maxlen;        // buffer smaller than string
1525 
1526     if (device) {
1527         // This first skip can't fail because we've already read this many bytes.
1528         device->skip(bufferStart + qptrdiff(content));
1529         actuallyRead = device->read(ptr, toRead);
1530 
1531         if (actuallyRead != toRead)  {
1532             actuallyRead = -1;
1533         } else if (left) {
1534             qint64 skipped = device->skip(left);
1535             if (skipped != left)
1536                 actuallyRead = -1;
1537         }
1538 
1539         if (actuallyRead < 0) {
1540             handleError(CborErrorIO);
1541             return result;
1542         }
1543 
1544         updateBufferAfterString(offset, len);
1545     } else {
1546         actuallyRead = toRead;
1547         memcpy(ptr, buffer.constData() + bufferStart + offset, toRead);
1548         bufferStart += QByteArray::size_type(offset + len);
1549     }
1550 
1551     preread();
1552     result.data = actuallyRead;
1553     result.status = QCborStreamReader::Ok;
1554     return result;
1555 }
1556 
1557 QT_END_NAMESPACE
1558 
1559 #include "moc_qcborstreamreader.cpp"
1560