1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 Intel Corporation
4 **
5 ** Permission is hereby granted, free of charge, to any person obtaining a copy
6 ** of this software and associated documentation files (the "Software"), to deal
7 ** in the Software without restriction, including without limitation the rights
8 ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 ** copies of the Software, and to permit persons to whom the Software is
10 ** furnished to do so, subject to the following conditions:
11 **
12 ** The above copyright notice and this permission notice shall be included in
13 ** all copies or substantial portions of the Software.
14 **
15 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ** THE SOFTWARE.
22 **
23 ****************************************************************************/
24 
25 #define _XOPEN_SOURCE 700
26 #define  _DARWIN_C_SOURCE 1         /* need MAP_ANON */
27 #include <QtTest>
28 #include "cbor.h"
29 #include <stdio.h>
30 #include <stdarg.h>
31 
32 #if defined(Q_OS_UNIX)
33 #  include <sys/mman.h>
34 #  include <unistd.h>
35 #elif defined(Q_OS_WIN)
36 #  define WIN32_LEAN_AND_MEAN 1
37 #  define NOMINMAX 1
38 #  include <windows.h>
39 #endif
40 
41 Q_DECLARE_METATYPE(CborError)
42 
43 namespace QTest {
toString(const CborError & err)44 template<> char *toString<CborError>(const CborError &err)
45 {
46     return qstrdup(cbor_error_string(err));
47 }
48 }
49 
50 class tst_Parser : public QObject
51 {
52     Q_OBJECT
53 private slots:
54     void initParserEmpty();
55 
56     // parsing API
57     void integers_data();
58     void integers();
59     void fixed_data();
60     void fixed();
61     void strings_data();
strings()62     void strings() { fixed(); }
63     void tags_data();
tags()64     void tags() { fixed(); }
tagTags_data()65     void tagTags_data() { tags_data(); }
66     void tagTags();
67     void emptyContainers_data();
68     void emptyContainers();
69     void arrays_data();
70     void arrays();
undefLengthArrays_data()71     void undefLengthArrays_data() { arrays_data(); }
72     void undefLengthArrays();
nestedArrays_data()73     void nestedArrays_data() { arrays_data(); }
74     void nestedArrays();
75     void maps_data();
76     void maps();
undefLengthMaps_data()77     void undefLengthMaps_data() { maps_data(); }
78     void undefLengthMaps();
nestedMaps_data()79     void nestedMaps_data() { maps_data(); }
80     void nestedMaps();
81     void mapMixed_data();
mapMixed()82     void mapMixed() { arrays(); }
mapsAndArrays_data()83     void mapsAndArrays_data() { arrays_data(); }
84     void mapsAndArrays();
85 
86     // chunked string API
87     void chunkedString_data();
88     void chunkedString();
chunkedStringInUndefArray_data()89     void chunkedStringInUndefArray_data() { chunkedString_data(); }
90     void chunkedStringInUndefArray();
91 
92     // convenience API
93     void stringLength_data();
94     void stringLength();
95     void stringCompare_data();
96     void stringCompare();
97     void mapFind_data();
98     void mapFind();
99 
100     // validation & errors
101     void checkedIntegers_data();
102     void checkedIntegers();
103     void validation_data();
104     void validation();
105     void strictValidation_data();
106     void strictValidation();
107     void resumeParsing_data();
108     void resumeParsing();
109     void endPointer_data();
110     void endPointer();
111     void recursionLimit_data();
112     void recursionLimit();
113 };
114 
115 struct ParserWrapper
116 {
117     void *realdata = nullptr;
118     uint8_t *data;
119     size_t len;
120     CborParser parser;
121     CborValue first;
122 
~ParserWrapperParserWrapper123     ~ParserWrapper() { freeMemory(); }
124 
initParserWrapper125     CborError init(const QByteArray &ba, uint32_t flags = 0)
126     {
127         return init(ba.constData(), ba.size(), flags);
128     }
initParserWrapper129     CborError init(const char *ptr, int n, uint32_t flags = 0)
130     {
131         freeMemory();
132         data = allocateMemory(n);
133         memcpy(data, ptr, len);
134         return cbor_parser_init(data, len, flags, &parser, &first);
135     }
beginParserWrapper136     uint8_t *begin() { return data; }
endParserWrapper137     uint8_t *end()   { return data + len; }
138 
139     uint8_t *allocateMemory(size_t);
140     void freeMemory();
141 
142     static const size_t PageSize = 4096;
mmapAllocationParserWrapper143     static inline size_t mmapAllocation(size_t n)
144     {
145         // round up and add one page
146         return (n + 2*PageSize) & ~(PageSize - 1);
147     }
148     static bool shouldUseMmap();
149 };
150 
shouldUseMmap()151 bool ParserWrapper::shouldUseMmap()
152 {
153     static int v = qEnvironmentVariableIntValue("PARSER_NO_MMAP");
154     return !v;
155 }
156 
allocateMemory(size_t n)157 uint8_t *ParserWrapper::allocateMemory(size_t n)
158 {
159     len = n;
160     if (shouldUseMmap()) {
161         size_t alloc = mmapAllocation(n);
162 #if defined(Q_OS_UNIX)
163         realdata = mmap(nullptr, alloc, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
164         Q_ASSERT_X(realdata != MAP_FAILED, "allocateMemory", "mmap failed!");
165 
166         // mark last page inaccessible
167         uint8_t *ptr = static_cast<uint8_t *>(realdata);
168         ptr += alloc - PageSize;
169         mprotect(ptr, PageSize, PROT_NONE);
170 
171         ptr -= n;
172         return ptr;
173 #elif defined(Q_OS_WIN)
174         DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE;
175         DWORD flProtect = PAGE_READWRITE;
176         realdata = VirtualAlloc(nullptr, alloc, flAllocationType, flProtect);
177         Q_ASSERT_X(realdata, "allocateMemory", "VirtualAlloc failed!");
178 
179         // mark last page inaccessible
180         uint8_t *ptr = static_cast<uint8_t *>(realdata);
181         ptr += alloc - PageSize;
182         VirtualProtect(ptr, PageSize, PAGE_NOACCESS, nullptr);
183 
184         ptr -= n;
185         return ptr;
186 #endif
187     }
188     realdata = malloc(n);
189     return static_cast<uint8_t *>(realdata);
190 }
191 
freeMemory()192 void ParserWrapper::freeMemory()
193 {
194     if (shouldUseMmap()) {
195         if (realdata) {
196 #if defined(Q_OS_UNIX)
197             size_t alloc = mmapAllocation(len);
198             munmap(realdata, alloc);
199 #elif defined(Q_OS_WIN)
200             VirtualFree(realdata, 0, MEM_RELEASE);
201 #endif
202         }
203         return;
204     }
205 
206     free(realdata);
207 }
208 
qstring_printf(void * out,const char * fmt,...)209 static CborError qstring_printf(void *out, const char *fmt, ...)
210 {
211     auto str = static_cast<QString *>(out);
212     va_list va;
213     va_start(va, fmt);
214     *str += QString::vasprintf(fmt, va);
215     va_end(va);
216     return CborNoError;
217 };
218 
parseOne(CborValue * it,QString * parsed)219 CborError parseOne(CborValue *it, QString *parsed)
220 {
221     int flags = CborPrettyShowStringFragments | CborPrettyIndicateIndeterminateLength |
222                 CborPrettyIndicateOverlongNumbers;
223 
224     parsed->clear();
225     return cbor_value_to_pretty_stream(qstring_printf, parsed, it, flags);
226 }
227 
raw(const char (& data)[N])228 template <size_t N> QByteArray raw(const char (&data)[N])
229 {
230     return QByteArray::fromRawData(data, N - 1);
231 }
232 
initParserEmpty()233 void tst_Parser::initParserEmpty()
234 {
235     CborParser parser;
236     CborValue first;
237     CborError err = cbor_parser_init((const quint8 *)"", 0, 0, &parser, &first);
238     QCOMPARE(err, CborErrorUnexpectedEOF);
239 }
240 
addColumns()241 void addColumns()
242 {
243     QTest::addColumn<QByteArray>("data");
244     QTest::addColumn<QString>("expected");
245     QTest::addColumn<int>("n");         // some aux integer, not added in all columns
246 }
247 
248 bool compareFailed = true;
compareOne_real(const QByteArray & data,const QString & expected,int line,int n=-1)249 void compareOne_real(const QByteArray &data, const QString &expected, int line, int n = -1)
250 {
251     compareFailed = true;
252     ParserWrapper w;
253     CborError err = w.init(data);
254     QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
255 
256     if (cbor_value_get_type(&w.first) == CborArrayType) {
257         size_t len;
258         if (n >= 0) {
259             QVERIFY(cbor_value_is_length_known(&w.first));
260             QCOMPARE(cbor_value_get_array_length(&w.first, &len), CborNoError);
261             QCOMPARE(len, size_t(len));
262         } else {
263             QVERIFY(!cbor_value_is_length_known(&w.first));
264             QCOMPARE(cbor_value_get_array_length(&w.first, &len), CborErrorUnknownLength);
265         }
266     } else if (cbor_value_get_type(&w.first) == CborMapType) {
267         size_t len;
268         if (n >= 0) {
269             QVERIFY(cbor_value_is_length_known(&w.first));
270             QCOMPARE(cbor_value_get_map_length(&w.first, &len), CborNoError);
271             QCOMPARE(len, size_t(len));
272         } else {
273             QVERIFY(!cbor_value_is_length_known(&w.first));
274             QCOMPARE(cbor_value_get_map_length(&w.first, &len), CborErrorUnknownLength);
275         }
276     } else if (cbor_value_is_text_string(&w.first) || cbor_value_is_byte_string(&w.first)) {
277         size_t len;
278         QCOMPARE(cbor_value_calculate_string_length(&w.first, &len), CborNoError);
279         if (cbor_value_is_length_known(&w.first)) {
280             size_t len2;
281             QCOMPARE(cbor_value_get_string_length(&w.first, &len2), CborNoError);
282             QCOMPARE(len2, len);
283         } else {
284             QCOMPARE(cbor_value_get_string_length(&w.first, &len), CborErrorUnknownLength);
285         }
286     }
287 
288     CborError err2 = cbor_value_validate_basic(&w.first);
289 
290     QString decoded;
291     err = parseOne(&w.first, &decoded);
292     QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) +
293                    "\"; decoded stream:\n" + decoded.toLatin1());
294     QCOMPARE(decoded, expected);
295 
296     // check that the errors are the same
297     QCOMPARE(err2, err);
298 
299     // check that we consumed everything
300     QCOMPARE((void*)cbor_value_get_next_byte(&w.first), (void*)w.end());
301 
302     compareFailed = false;
303 }
304 #define compareOne(data, expected) compareOne_real(data, expected, __LINE__)
305 #define compareOneSize(n, data, expected) compareOne_real(data, expected, __LINE__, n)
306 
addFixedData()307 void addFixedData()
308 {
309     // unsigned integers
310     QTest::newRow("0") << raw("\x00") << "0";
311     QTest::newRow("1") << raw("\x01") << "1";
312     QTest::newRow("10") << raw("\x0a") << "10";
313     QTest::newRow("23") << raw("\x17") << "23";
314     QTest::newRow("24") << raw("\x18\x18") << "24";
315     QTest::newRow("UINT8_MAX") << raw("\x18\xff") << "255";
316     QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << "256";
317     QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << "65535";
318     QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << "65536";
319     QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << "4294967295";
320     QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << "4294967296";
321     QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
322                                 << QString::number(std::numeric_limits<uint64_t>::max());
323 
324     // negative integers
325     QTest::newRow("-1") << raw("\x20") << "-1";
326     QTest::newRow("-2") << raw("\x21") << "-2";
327     QTest::newRow("-24") << raw("\x37") << "-24";
328     QTest::newRow("-25") << raw("\x38\x18") << "-25";
329     QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << "-256";
330     QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << "-257";
331     QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << "-65536";
332     QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << "-65537";
333     QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << "-4294967296";
334     QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << "-4294967297";
335     QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
336                                << QString::number(std::numeric_limits<int64_t>::min() + 1);
337     QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
338                                << QString::number(std::numeric_limits<int64_t>::min());
339     QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809";
340     QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
341                                    << '-' + QString::number(std::numeric_limits<uint64_t>::max());
342     QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
343                                    << "-18446744073709551616";
344 
345     // overlongs
346     QTest::newRow("0*1") << raw("\x18\x00") << "0_0";
347     QTest::newRow("0*2") << raw("\x19\x00\x00") << "0_1";
348     QTest::newRow("0*4") << raw("\x1a\0\0\0\0") << "0_2";
349     QTest::newRow("0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << "0_3";
350     QTest::newRow("-1*1") << raw("\x38\x00") << "-1_0";
351     QTest::newRow("-1*2") << raw("\x39\x00\x00") << "-1_1";
352     QTest::newRow("-1*4") << raw("\x3a\0\0\0\0") << "-1_2";
353     QTest::newRow("-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << "-1_3";
354 
355     QTest::newRow("simple0") << raw("\xe0") << "simple(0)";
356     QTest::newRow("simple19") << raw("\xf3") << "simple(19)";
357     QTest::newRow("false") << raw("\xf4") << "false";
358     QTest::newRow("true") << raw("\xf5") << "true";
359     QTest::newRow("null") << raw("\xf6") << "null";
360     QTest::newRow("undefined") << raw("\xf7") << "undefined";
361     QTest::newRow("simple32") << raw("\xf8\x20") << "simple(32)";
362     QTest::newRow("simple255") << raw("\xf8\xff") << "simple(255)";
363 
364     // floating point
365 
366     QTest::newRow("0.f16") << raw("\xf9\0\0") << "0.f16";
367     QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "0.f";
368     QTest::newRow("0.")  << raw("\xfb\0\0\0\0\0\0\0\0") << "0.";
369     QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "-1.f16";
370     QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "-1.f";
371     QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "-1.";
372     QTest::newRow("65504.f16") << raw("\xf9\x7b\xff") << "65504.f16";
373     QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f";
374     QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "16777215.";
375     QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "-16777215.f";
376     QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "-16777215.";
377 
378     QTest::newRow("0.5f16") << raw("\xf9\x38\0") << "0.5f16";
379     QTest::newRow("0.5f") << raw("\xfa\x3f\0\0\0") << "0.5f";
380     QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << "0.5";
381     QTest::newRow("2.f16^11-1") << raw("\xf9\x67\xff") << "2047.f16";
382     QTest::newRow("2.f^24-1") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f";
383     QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "9007199254740991.";
384     QTest::newRow("2.f^64-epsilon") << raw("\xfa\x5f\x7f\xff\xff") << "18446742974197923840.f";
385     QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "18446744073709549568.";
386     QTest::newRow("2.f^64") << raw("\xfa\x5f\x80\0\0") << "1.8446744073709552e+19f";
387     QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << "1.8446744073709552e+19";
388 
389     QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "nan";
390     QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "nan";
391     QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "nan";
392     QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "-inf";
393     QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "-inf";
394     QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "-inf";
395     QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "inf";
396     QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "inf";
397     QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "inf";
398 
399 }
400 
addIntegers()401 static void addIntegers()
402 {
403     QTest::addColumn<QByteArray>("data");
404     QTest::addColumn<quint64>("expectedRaw");
405     QTest::addColumn<qint64>("expectedValue");
406     QTest::addColumn<bool>("isNegative");
407     QTest::addColumn<bool>("inInt64Range");
408 
409     // unsigned integers
410     QTest::newRow("0") << raw("\x00") << Q_UINT64_C(0) << Q_INT64_C(0) << false << true;
411     QTest::newRow("1") << raw("\x01") << Q_UINT64_C(1) << Q_INT64_C(1) << false << true;
412     QTest::newRow("10") << raw("\x0a") << Q_UINT64_C(10) << Q_INT64_C(10) << false << true;
413     QTest::newRow("23") << raw("\x17") << Q_UINT64_C(23) << Q_INT64_C(23) << false << true;
414     QTest::newRow("24") << raw("\x18\x18") << Q_UINT64_C(24) << Q_INT64_C(24) << false << true;
415     QTest::newRow("UINT8_MAX") << raw("\x18\xff") << Q_UINT64_C(255) << Q_INT64_C(255) << false << true;
416     QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(256) << false << true;
417     QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(65535) << false << true;
418     QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(65536) << false << true;
419     QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(4294967295) << false << true;
420     QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(4294967296) << false << true;
421     QTest::newRow("INT64_MAX") << raw("\x1b" "\x7f\xff\xff\xff" "\xff\xff\xff\xff")
422                                 << quint64(std::numeric_limits<qint64>::max())
423                                 << std::numeric_limits<qint64>::max() << false << true;
424     QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
425                                 << std::numeric_limits<quint64>::max() << qint64(-123456) << false << false;
426 
427     // negative integers
428     QTest::newRow("-1") << raw("\x20") << Q_UINT64_C(0) << Q_INT64_C(-1) << true << true;
429     QTest::newRow("-2") << raw("\x21") << Q_UINT64_C(1) << Q_INT64_C(-2) << true << true;
430     QTest::newRow("-24") << raw("\x37") << Q_UINT64_C(23) << Q_INT64_C(-24) << true << true;
431     QTest::newRow("-25") << raw("\x38\x18") << Q_UINT64_C(24) << Q_INT64_C(-25) << true << true;
432     QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << Q_UINT64_C(255) << Q_INT64_C(-256) << true << true;
433     QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(-257) << true << true;
434     QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(-65536) << true << true;
435     QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(-65537) << true << true;
436     QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(-4294967296) << true << true;
437     QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(-4294967297) << true << true;
438     QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
439                                << quint64(std::numeric_limits<qint64>::max() - 1)
440                                << (std::numeric_limits<qint64>::min() + 1)
441                                << true << true;
442     QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
443                                << quint64(std::numeric_limits<qint64>::max())
444                                << std::numeric_limits<qint64>::min()
445                                << true << true;
446     QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << Q_UINT64_C(9223372036854775808) << qint64(-123456) << true << false;
447     QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
448                                  << (std::numeric_limits<quint64>::max() - 1) << qint64(-123456) << true << false;
449     QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
450                                    << std::numeric_limits<quint64>::max() << qint64(-123456) << true << false;
451 }
452 
integers_data()453 void tst_Parser::integers_data()
454 {
455     addIntegers();
456 }
457 
integers()458 void tst_Parser::integers()
459 {
460     QFETCH(QByteArray, data);
461     QFETCH(bool, isNegative);
462     QFETCH(quint64, expectedRaw);
463     QFETCH(qint64, expectedValue);
464     QFETCH(bool, inInt64Range);
465 
466     ParserWrapper w;
467     CborError err = w.init(data);
468     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
469     QVERIFY(cbor_value_is_integer(&w.first));
470 
471     uint64_t raw;
472     cbor_value_get_raw_integer(&w.first, &raw);
473     QCOMPARE(quint64(raw), expectedRaw);
474 
475     if (isNegative) {
476         QVERIFY(cbor_value_is_negative_integer(&w.first));
477         QVERIFY(!cbor_value_is_unsigned_integer(&w.first));
478     } else {
479         QVERIFY(!cbor_value_is_negative_integer(&w.first));
480         QVERIFY(cbor_value_is_unsigned_integer(&w.first));
481     }
482 
483     int64_t value;
484     if (inInt64Range) {
485         cbor_value_get_int64(&w.first, &value);
486         QCOMPARE(qint64(value), expectedValue);
487     }
488 
489     err = cbor_value_get_int64_checked(&w.first, &value);
490     QCOMPARE(err, inInt64Range ? CborNoError : CborErrorDataTooLarge);
491 
492     int ivalue;
493     bool inIntRange = inInt64Range && (expectedValue == int(expectedValue));
494     err = cbor_value_get_int_checked(&w.first, &ivalue);
495     QCOMPARE(err, inIntRange ? CborNoError : CborErrorDataTooLarge);
496 }
497 
fixed_data()498 void tst_Parser::fixed_data()
499 {
500     addColumns();
501     addFixedData();
502 }
503 
fixed()504 void tst_Parser::fixed()
505 {
506     QFETCH(QByteArray, data);
507     QFETCH(QString, expected);
508 
509     compareOne(data, expected);
510 }
511 
addStringsData()512 void addStringsData()
513 {
514     // byte strings
515     QTest::newRow("emptybytestring") << raw("\x40") << "h''";
516     QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'";
517     QTest::newRow("bytestring1-nul") << raw("\x41\0") << "h'00'";
518     QTest::newRow("bytestring5") << raw("\x45Hello") << "h'48656c6c6f'";
519     QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234")
520                                   << "h'313233343536373839303132333435363738393031323334'";
521     QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3')
522                                    << "h'" + QString(256 * 2, '3') + '\'';
523 
524     // text strings
525     QTest::newRow("emptytextstring") << raw("\x60") << "\"\"";
526     QTest::newRow("textstring1") << raw("\x61 ") << "\" \"";
527     QTest::newRow("textstring1-nul") << raw("\x61\0") << "\"\\u0000\"";
528     QTest::newRow("textstring5") << raw("\x65Hello") << "\"Hello\"";
529     QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234")
530                                   << "\"123456789012345678901234\"";
531     QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3')
532                                    << '"' + QString(256, '3') + '"';
533 
534     // some strings with UTF-8 content
535     // we had a bug in the pretty dumper - see issue #54
536     QTest::newRow("textstringutf8-2char") << raw("\x62\xc2\xa0") << "\"\\u00A0\"";
537     QTest::newRow("textstringutf8-2char2") << raw("\x64\xc2\xa0\xc2\xa9") << "\"\\u00A0\\u00A9\"";
538     QTest::newRow("textstringutf8-3char") << raw("\x63\xe2\x88\x80") << "\"\\u2200\"";
539     QTest::newRow("textstringutf8-4char") << raw("\x64\xf0\x90\x88\x83") << "\"\\uD800\\uDE03\"";
540 
541     // strings with overlong length
542     QTest::newRow("emptybytestring*1") << raw("\x58\x00") << "h''_0";
543     QTest::newRow("emptytextstring*1") << raw("\x78\x00") << "\"\"_0";
544     QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << "h''_1";
545     QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << "\"\"_1";
546     QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << "h''_2";
547     QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << "\"\"_2";
548     QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << "h''_3";
549     QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << "\"\"_3";
550     QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << "h'48656c6c6f'_0";
551     QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << "\"Hello\"_0";
552     QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << "h'48656c6c6f'_1";
553     QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << "\"Hello\"_1";
554     QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << "h'48656c6c6f'_2";
555     QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << "\"Hello\"_2";
556     QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << "h'48656c6c6f'_3";
557     QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << "\"Hello\"_3";
558 
559     // strings with undefined length
560     QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "(_ )";
561     QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "(_ )";
562     QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "(_ h'')";
563     QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "(_ \"\")";
564     QTest::newRow("_emptybytestring2*1") << raw("\x5f\x58\x00\xff") << "(_ h''_0)";
565     QTest::newRow("_emptytextstring2*1") << raw("\x7f\x78\x00\xff") << "(_ \"\"_0)";
566     QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "(_ h'', h'')";
567     QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "(_ \"\", \"\")";
568     QTest::newRow("_emptybytestring3*2") << raw("\x5f\x59\x00\x00\x40\xff") << "(_ h''_1, h'')";
569     QTest::newRow("_emptytextstring3*2") << raw("\x7f\x79\x00\x00\x60\xff") << "(_ \"\"_1, \"\")";
570     QTest::newRow("_bytestring5x2") << raw("\x5f\x43Hel\x42lo\xff") << "(_ h'48656c', h'6c6f')";
571     QTest::newRow("_textstring5x2") << raw("\x7f\x63Hel\x62lo\xff") << "(_ \"Hel\", \"lo\")";
572     QTest::newRow("_bytestring5x2*8*4") << raw("\x5f\x5b\0\0\0\0\0\0\0\3Hel\x5a\0\0\0\2lo\xff") << "(_ h'48656c'_3, h'6c6f'_2)";
573     QTest::newRow("_textstring5x2*8*4") << raw("\x7f\x7b\0\0\0\0\0\0\0\3Hel\x7a\0\0\0\2lo\xff") << "(_ \"Hel\"_3, \"lo\"_2)";
574     QTest::newRow("_bytestring5x5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'6c', h'6c', h'6f')";
575     QTest::newRow("_textstring5x5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"l\", \"o\")";
576     QTest::newRow("_bytestring5x6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'', h'6c', h'6c', h'6f')";
577     QTest::newRow("_textstring5x6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"\", \"l\", \"o\")";
578 }
579 
strings_data()580 void tst_Parser::strings_data()
581 {
582     addColumns();
583     addStringsData();
584 }
585 
addTagsData()586 void addTagsData()
587 {
588     // since parseOne() works recursively for tags, we can't test lone tags
589     QTest::newRow("tag0") << raw("\xc0\x00") << "0(0)";
590     QTest::newRow("tag1") << raw("\xc1\x00") << "1(0)";
591     QTest::newRow("tag24") << raw("\xd8\x18\x00") << "24(0)";
592     QTest::newRow("tag255") << raw("\xd8\xff\x00") << "255(0)";
593     QTest::newRow("tag256") << raw("\xd9\1\0\x00") << "256(0)";
594     QTest::newRow("tag65535") << raw("\xd9\xff\xff\x00") << "65535(0)";
595     QTest::newRow("tag65536") << raw("\xda\0\1\0\0\x00") << "65536(0)";
596     QTest::newRow("tagUINT32_MAX-1") << raw("\xda\xff\xff\xff\xff\x00") << "4294967295(0)";
597     QTest::newRow("tagUINT32_MAX") << raw("\xdb\0\0\0\1\0\0\0\0\x00") << "4294967296(0)";
598     QTest::newRow("tagUINT64_MAX") << raw("\xdb" "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00")
599                                 << QString::number(std::numeric_limits<uint64_t>::max()) + "(0)";
600 
601     // overlong tags
602     QTest::newRow("tag0*1") << raw("\xd8\0\x00") << "0_0(0)";
603     QTest::newRow("tag0*2") << raw("\xd9\0\0\x00") << "0_1(0)";
604     QTest::newRow("tag0*4") << raw("\xda\0\0\0\0\x00") << "0_2(0)";
605     QTest::newRow("tag0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x00") << "0_3(0)";
606 
607     // tag other things
608     QTest::newRow("unixtime") << raw("\xc1\x1a\x55\x4b\xbf\xd3") << "1(1431027667)";
609     QTest::newRow("rfc3339date") << raw("\xc0\x78\x19" "2015-05-07 12:41:07-07:00")
610                                  << "0(\"2015-05-07 12:41:07-07:00\")";
611     QTest::newRow("tag6+false") << raw("\xc6\xf4") << "6(false)";
612     QTest::newRow("tag25+true") << raw("\xd8\x19\xf5") << "25(true)";
613     QTest::newRow("tag256+null") << raw("\xd9\1\0\xf6") << "256(null)";
614     QTest::newRow("tag65536+simple32") << raw("\xda\0\1\0\0\xf8\x20") << "65536(simple(32))";
615     QTest::newRow("float+unixtime") << raw("\xc1\xfa\x4e\xaa\x97\x80") << "1(1431027712.f)";
616     QTest::newRow("double+unixtime") << raw("\xc1\xfb" "\x41\xd5\x52\xef" "\xf4\xc7\xce\xfe")
617                                      << "1(1431027667.1220088)";
618 }
619 
tags_data()620 void tst_Parser::tags_data()
621 {
622     addColumns();
623     addTagsData();
624 }
625 
tagTags()626 void tst_Parser::tagTags()
627 {
628     QFETCH(QByteArray, data);
629     QFETCH(QString, expected);
630 
631     compareOne("\xd9\xd9\xf7" + data, "55799(" + expected + ')');
632     if (!compareFailed)
633         compareOne("\xd9\xd9\xf7" "\xd9\xd9\xf7" + data, "55799(55799(" + expected + "))");
634 }
635 
addEmptyContainersData()636 void addEmptyContainersData()
637 {
638     QTest::newRow("emptyarray") << raw("\x80") << "[]" << 0;
639     QTest::newRow("emptymap") << raw("\xa0") << "{}" << 0;
640     QTest::newRow("_emptyarray") << raw("\x9f\xff") << "[_ ]" << -1;
641     QTest::newRow("_emptymap") << raw("\xbf\xff") << "{_ }" << -1;
642 }
643 
emptyContainers_data()644 void tst_Parser::emptyContainers_data()
645 {
646     addColumns();
647     addEmptyContainersData();
648 }
649 
emptyContainers()650 void tst_Parser::emptyContainers()
651 {
652     QFETCH(QByteArray, data);
653     QFETCH(QString, expected);
654     QFETCH(int, n);
655 
656     compareOneSize(n, data, expected);
657 }
658 
arrays_data()659 void tst_Parser::arrays_data()
660 {
661     addColumns();
662     addFixedData();
663     addStringsData();
664     addTagsData();
665 }
666 
arrays()667 void tst_Parser::arrays()
668 {
669     QFETCH(QByteArray, data);
670     QFETCH(QString, expected);
671 
672     compareOneSize(1, "\x81" + data, '[' + expected + ']');
673     if (compareFailed) return;
674 
675     compareOneSize(2, "\x82" + data + data, '[' + expected + ", " + expected + ']');
676     if (compareFailed) return;
677 
678     // overlong length
679     compareOneSize(1, "\x98\1" + data, "[_0 " + expected + ']');
680     if (compareFailed) return;
681     compareOneSize(1, raw("\x99\0\1") + data, "[_1 " + expected + ']');
682     if (compareFailed) return;
683     compareOneSize(1, raw("\x9a\0\0\0\1") + data, "[_2 " + expected + ']');
684     if (compareFailed) return;
685     compareOneSize(1, raw("\x9b\0\0\0\0\0\0\0\1") + data, "[_3 " + expected + ']');
686     if (compareFailed) return;
687 
688     // medium-sized array: 32 elements (1 << 5)
689     expected += ", ";
690     for (int i = 0; i < 5; ++i) {
691         data += data;
692         expected += expected;
693     }
694     expected.chop(2);   // remove the last ", "
695     compareOneSize(32, "\x98\x20" + data, '[' + expected + ']');
696     if (compareFailed) return;
697 
698     // large array: 256 elements (32 << 3)
699     expected += ", ";
700     for (int i = 0; i < 3; ++i) {
701         data += data;
702         expected += expected;
703     }
704     expected.chop(2);   // remove the last ", "
705     compareOneSize(256, raw("\x99\1\0") + data, '[' + expected + ']');
706     if (compareFailed) return;
707 }
708 
undefLengthArrays()709 void tst_Parser::undefLengthArrays()
710 {
711     QFETCH(QByteArray, data);
712     QFETCH(QString, expected);
713 
714     compareOne("\x9f" + data + "\xff", "[_ " + expected + ']');
715     if (compareFailed) return;
716 
717     compareOne("\x9f" + data + data + "\xff", "[_ " + expected + ", " + expected + ']');
718 }
719 
nestedArrays()720 void tst_Parser::nestedArrays()
721 {
722     QFETCH(QByteArray, data);
723     QFETCH(QString, expected);
724 
725     compareOneSize(1, "\x81\x81" + data, "[[" + expected + "]]");
726     if (compareFailed) return;
727 
728     compareOneSize(1, "\x81\x81\x81" + data, "[[[" + expected + "]]]");
729     if (compareFailed) return;
730 
731     compareOneSize(1, "\x81\x82" + data + data, "[[" + expected + ", " + expected + "]]");
732     if (compareFailed) return;
733 
734     compareOneSize(2, "\x82\x81" + data + data, "[[" + expected + "], " + expected + "]");
735     if (compareFailed) return;
736 
737     compareOneSize(2, "\x82\x81" + data + '\x81' + data, "[[" + expected + "], [" + expected + "]]");
738     if (compareFailed) return;
739 
740     // undefined length
741     compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\xff", "[_ [_ " + expected + ", " + expected + "]]");
742     if (compareFailed) return;
743 
744     compareOneSize(-1, "\x9f\x9f" + data + "\xff\x9f" + data + "\xff\xff", "[_ [_ " + expected + "], [_ " + expected + "]]");
745     if (compareFailed) return;
746 
747     compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\x9f" + data + "\xff\xff",
748                "[_ [_ " + expected + ", " + expected + "], [_ " + expected + "]]");
749     if (compareFailed) return;
750 
751     // mix them
752     compareOneSize(1, "\x81\x9f" + data + "\xff", "[[_ " + expected + "]]");
753     if (compareFailed) return;
754 
755     compareOneSize(-1, "\x9f\x81" + data + "\xff", "[_ [" + expected + "]]");
756 }
757 
maps_data()758 void tst_Parser::maps_data()
759 {
760     arrays_data();
761 }
762 
maps()763 void tst_Parser::maps()
764 {
765     QFETCH(QByteArray, data);
766     QFETCH(QString, expected);
767 
768     // integer key
769     compareOneSize(1, "\xa1\1" + data, "{1: " + expected + '}');
770     if (compareFailed) return;
771 
772     // string key
773     compareOneSize(1, "\xa1\x65" "Hello" + data, "{\"Hello\": " + expected + '}');
774     if (compareFailed) return;
775 
776     // map to self
777     compareOneSize(1, "\xa1" + data + data, '{' + expected + ": " + expected + '}');
778     if (compareFailed) return;
779 
780     // two integer keys
781     compareOneSize(2, "\xa2\1" + data + "\2" + data, "{1: " + expected + ", 2: " + expected + '}');
782     if (compareFailed) return;
783 
784     // OneSize integer and OneSize string key
785     compareOneSize(2, "\xa2\1" + data + "\x65" "Hello" + data, "{1: " + expected + ", \"Hello\": " + expected + '}');
786     if (compareFailed) return;
787 }
788 
undefLengthMaps()789 void tst_Parser::undefLengthMaps()
790 {
791     QFETCH(QByteArray, data);
792     QFETCH(QString, expected);
793 
794     // integer key
795     compareOne("\xbf\1" + data + '\xff', "{_ 1: " + expected + '}');
796     if (compareFailed) return;
797 
798     compareOne("\xbf\1" + data + '\2' + data + '\xff', "{_ 1: " + expected + ", 2: " + expected + '}');
799     if (compareFailed) return;
800 
801     compareOne("\xbf\1" + data + "\x65Hello" + data + '\xff', "{_ 1: " + expected + ", \"Hello\": " + expected + '}');
802     if (compareFailed) return;
803 
804     compareOne("\xbf\x65Hello" + data + '\1' + data + '\xff', "{_ \"Hello\": " + expected + ", 1: " + expected + '}');
805 }
806 
nestedMaps()807 void tst_Parser::nestedMaps()
808 {
809     QFETCH(QByteArray, data);
810     QFETCH(QString, expected);
811 
812     // nested maps as values
813     compareOneSize(1, "\xa1\1\xa1\2" + data, "{1: {2: " + expected + "}}");
814     if (compareFailed) return;
815 
816     compareOneSize(1, "\xa1\x65Hello\xa1\2" + data, "{\"Hello\": {2: " + expected + "}}");
817     if (compareFailed) return;
818 
819     compareOneSize(1, "\xa1\1\xa2\2" + data + '\x20' + data, "{1: {2: " + expected + ", -1: " + expected + "}}");
820     if (compareFailed) return;
821 
822     compareOneSize(2, "\xa2\1\xa1\2" + data + "\2\xa1\x20" + data, "{1: {2: " + expected + "}, 2: {-1: " + expected + "}}");
823     if (compareFailed) return;
824 
825     // nested maps as keys
826     compareOneSize(1, "\xa1\xa1\xf4" + data + "\xf5", "{{false: " + expected + "}: true}");
827     if (compareFailed) return;
828 
829     compareOneSize(1, "\xa1\xa1" + data + data + "\xa1" + data + data,
830                "{{" + expected + ": " + expected + "}: {" + expected + ": " + expected + "}}");
831     if (compareFailed) return;
832 
833     // undefined length
834     compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\xff", "{_ 1: {_ 2: " + expected + "}}");
835     if (compareFailed) return;
836 
837     compareOneSize(-1, "\xbf\1\xbf\2" + data + '\x20' + data + "\xff\xff", "{_ 1: {_ 2: " + expected + ", -1: " + expected + "}}");
838     if (compareFailed) return;
839 
840     compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\2\xbf\x20" + data + "\xff\xff",
841                "{_ 1: {_ 2: " + expected + "}, 2: {_ -1: " + expected + "}}");
842     if (compareFailed) return;
843 
844     compareOneSize(-1, "\xbf\xbf" + data + data + "\xff\xbf" + data + data + "\xff\xff",
845                "{_ {_ " + expected + ": " + expected + "}: {_ " + expected + ": " + expected + "}}");
846     if (compareFailed) return;
847 
848     // mix them
849     compareOneSize(1, "\xa1\1\xbf\2" + data + "\xff", "{1: {_ 2: " + expected + "}}");
850     if (compareFailed) return;
851 
852     compareOneSize(-1, "\xbf\1\xa1\2" + data + "\xff", "{_ 1: {2: " + expected + "}}");
853     if (compareFailed) return;
854 }
855 
addMapMixedData()856 void addMapMixedData()
857 {
858     QTest::newRow("map-0-24") << raw("\xa1\0\x18\x18") << "{0: 24}" << 1;
859     QTest::newRow("map-0*1-24") << raw("\xa1\x18\0\x18\x18") << "{0_0: 24}" << 1;
860     QTest::newRow("map-0*1-24*2") << raw("\xa1\x18\0\x19\0\x18") << "{0_0: 24_1}" << 1;
861     QTest::newRow("map-0*4-24*2") << raw("\xa1\x1a\0\0\0\0\x19\0\x18") << "{0_2: 24_1}" << 1;
862     QTest::newRow("map-24-0") << raw("\xa1\x18\x18\0") << "{24: 0}" << 1;
863     QTest::newRow("map-24-0*1") << raw("\xa1\x18\x18\x18\0") << "{24: 0_0}" << 1;
864     QTest::newRow("map-255-65535") << raw("\xa1\x18\xff\x19\xff\xff") << "{255: 65535}" << 1;
865 
866     QTest::newRow("_map-0-24") << raw("\xbf\0\x18\x18\xff") << "{_ 0: 24}" << 1;
867     QTest::newRow("_map-0*1-24") << raw("\xbf\x18\0\x18\x18\xff") << "{_ 0_0: 24}" << 1;
868     QTest::newRow("_map-0*1-24*2") << raw("\xbf\x18\0\x19\0\x18\xff") << "{_ 0_0: 24_1}" << 1;
869     QTest::newRow("_map-0*4-24*2") << raw("\xbf\x1a\0\0\0\0\x19\0\x18\xff") << "{_ 0_2: 24_1}" << 1;
870     QTest::newRow("_map-24-0") << raw("\xbf\x18\x18\0\xff") << "{_ 24: 0}" << 1;
871     QTest::newRow("_map-24-0*1") << raw("\xbf\x18\x18\x18\0\xff") << "{_ 24: 0_0}" << 1;
872     QTest::newRow("_map-255-65535") << raw("\xbf\x18\xff\x19\xff\xff\xff") << "{_ 255: 65535}" << 1;
873 }
874 
mapMixed_data()875 void tst_Parser::mapMixed_data()
876 {
877     addColumns();
878     addMapMixedData();
879 }
880 
mapsAndArrays()881 void tst_Parser::mapsAndArrays()
882 {
883     QFETCH(QByteArray, data);
884     QFETCH(QString, expected);
885 
886     // arrays of maps
887     compareOneSize(1, "\x81\xa1\1" + data, "[{1: " + expected + "}]");
888     if (compareFailed) return;
889 
890     compareOneSize(2, "\x82\xa1\1" + data + "\xa1\2" + data, "[{1: " + expected + "}, {2: " + expected + "}]");
891     if (compareFailed) return;
892 
893     compareOneSize(1, "\x81\xa2\1" + data + "\2" + data, "[{1: " + expected + ", 2: " + expected + "}]");
894     if (compareFailed) return;
895 
896     compareOneSize(-1, "\x9f\xa1\1" + data + "\xff", "[_ {1: " + expected + "}]");
897     if (compareFailed) return;
898 
899     compareOneSize(1, "\x81\xbf\1" + data + "\xff", "[{_ 1: " + expected + "}]");
900     if (compareFailed) return;
901 
902     compareOneSize(-1, "\x9f\xbf\1" + data + "\xff\xff", "[_ {_ 1: " + expected + "}]");
903     if (compareFailed) return;
904 
905     // maps of arrays
906     compareOneSize(1, "\xa1\1\x81" + data, "{1: [" + expected + "]}");
907     if (compareFailed) return;
908 
909     compareOneSize(1, "\xa1\1\x82" + data + data, "{1: [" + expected + ", " + expected + "]}");
910     if (compareFailed) return;
911 
912     compareOneSize(2, "\xa2\1\x81" + data + "\x65Hello\x81" + data, "{1: [" + expected + "], \"Hello\": [" + expected + "]}");
913     if (compareFailed) return;
914 
915     compareOneSize(1, "\xa1\1\x9f" + data + "\xff", "{1: [_ " + expected + "]}");
916     if (compareFailed) return;
917 
918     compareOneSize(1, "\xa1\1\x9f" + data + data + "\xff", "{1: [_ " + expected + ", " + expected + "]}");
919     if (compareFailed) return;
920 
921     compareOneSize(-1, "\xbf\1\x81" + data + "\xff", "{_ 1: [" + expected + "]}");
922     if (compareFailed) return;
923 
924     compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\xff", "{_ 1: [_ " + expected + "]}");
925     if (compareFailed) return;
926 
927     compareOneSize(-1, "\xbf\1\x9f" + data + data + "\xff\xff", "{_ 1: [_ " + expected + ", " + expected + "]}");
928     if (compareFailed) return;
929 
930     // mixed with indeterminate length strings
931     compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\x65Hello\xbf" + data + "\x7f\xff\xff\xff",
932                    "{_ 1: [_ " + expected + "], \"Hello\": {_ " + expected + ": (_ )}}");
933 }
934 
chunkedString_data()935 void tst_Parser::chunkedString_data()
936 {
937     QTest::addColumn<QByteArray>("data");
938     QTest::addColumn<QString>("concatenated");
939     QTest::addColumn<QStringList>("chunks");
940 
941     // non-chunked:
942     QTest::newRow("emptybytestring") << raw("\x40") << "h''" << QStringList{"h''"};
943     QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'" << QStringList{"h'20'"};
944     QTest::newRow("emptytextstring") << raw("\x60") << "\"\"" << QStringList{"\"\""};
945     QTest::newRow("textstring1") << raw("\x61 ") << "\" \"" << QStringList{"\" \""};
946 
947     // empty chunked:
948     QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "h''" << QStringList{};
949     QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "\"\"" << QStringList{};
950     QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "h''" << QStringList{"h''"};
951     QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "\"\"" << QStringList{"\"\""};
952     QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "h''" << QStringList{"h''", "h''"};
953     QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "\"\"" << QStringList{"\"\"", "\"\""};
954 
955     // regular chunks
956     QTest::newRow("_bytestring1") << raw("\x5f\x41 \xff") << "h'20'" << QStringList{"h'20'"};
957     QTest::newRow("_bytestring2") << raw("\x5f\x41 \x41z\xff") << "h'207a'" << QStringList{"h'20'", "h'7a'"};
958     QTest::newRow("_bytestring3") << raw("\x5f\x41 \x58\x18""123456789012345678901234\x41z\xff")
959                                   << "h'203132333435363738393031323334353637383930313233347a'"
960                                   << QStringList{"h'20'", "h'313233343536373839303132333435363738393031323334'", "h'7a'"};
961 
962     QTest::newRow("_textstring1") << raw("\x7f\x61 \xff") << "\" \"" << QStringList{"\" \""};
963     QTest::newRow("_textstring2") << raw("\x7f\x61 \x61z\xff") << "\" z\"" << QStringList{"\" \"", "\"z\""};
964     QTest::newRow("_textstring3") << raw("\x7f\x61 \x78\x18""123456789012345678901234\x61z\xff")
965                                   << "\" 123456789012345678901234z\""
966                                   << QStringList{"\" \"", "\"123456789012345678901234\"", "\"z\""};
967 }
968 
chunkedStringTest(const QByteArray & data,const QString & concatenated,QStringList & chunks,CborType ourType)969 static void chunkedStringTest(const QByteArray &data, const QString &concatenated,
970                               QStringList &chunks, CborType ourType)
971 {
972     ParserWrapper w;
973     CborError err = w.init(data);
974     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
975 
976     CborValue value;
977     QVERIFY(cbor_value_is_array(&w.first));
978     err = cbor_value_enter_container(&w.first, &value);
979     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
980     QVERIFY(cbor_value_is_byte_string(&value) || cbor_value_is_text_string(&value));
981 
982     CborValue copy = value;
983 
984     Q_UNUSED(chunks);   // for future API
985     QCOMPARE(cbor_value_advance(&value), CborNoError);
986 
987     // compare to the concatenated data
988     {
989         size_t n;
990         err = cbor_value_calculate_string_length(&copy, &n);
991         QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
992 
993         QByteArray buffer(n, Qt::Uninitialized);
994         QString formatted;
995         if (cbor_value_is_byte_string(&copy)) {
996             err = cbor_value_copy_byte_string(&copy, (uint8_t *)buffer.data(), &n, nullptr);
997             QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
998             QCOMPARE(int(n), buffer.size());
999 
1000             formatted = QString::fromLatin1("h'" + buffer.toHex() + '\'');
1001         } else {
1002             err = cbor_value_copy_text_string(&copy, buffer.data(), &n, nullptr);
1003             QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1004             QCOMPARE(int(n), buffer.size());
1005 
1006             formatted = '"' + QString::fromUtf8(buffer.data(), n) + '"';
1007         }
1008         QCOMPARE(formatted, concatenated);
1009     }
1010 
1011     // confirm that the extra string we appended is still here
1012     QVERIFY(!cbor_value_at_end(&value));
1013     QCOMPARE(cbor_value_get_type(&value), ourType);
1014     size_t len;
1015     err = cbor_value_get_string_length(&value, &len);
1016     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1017     QCOMPARE(len, size_t(0));
1018 
1019     err = cbor_value_advance(&value);
1020     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1021 
1022     // confirm EOF
1023     QVERIFY(cbor_value_at_end(&value));
1024 
1025     err = cbor_value_leave_container(&w.first, &value);
1026     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1027     QCOMPARE((void*)cbor_value_get_next_byte(&w.first), (void*)w.end());
1028 }
1029 
chunkedString()1030 void tst_Parser::chunkedString()
1031 {
1032     QFETCH(QByteArray, data);
1033     QFETCH(QString, concatenated);
1034     QFETCH(QStringList, chunks);
1035 
1036     // Make this an array of two entries, with the second an empty byte or text string
1037     CborType ourType = CborType(data.at(0) & 0xe0);
1038     data.prepend(char(0x82));
1039     data.append(ourType);
1040 
1041     chunkedStringTest(data, concatenated, chunks, ourType);
1042 }
1043 
chunkedStringInUndefArray()1044 void tst_Parser::chunkedStringInUndefArray()
1045 {
1046     QFETCH(QByteArray, data);
1047     QFETCH(QString, concatenated);
1048     QFETCH(QStringList, chunks);
1049 
1050     // Make this an array of undefined length entries, with the second entry an empty byte or text string
1051     CborType ourType = CborType(data.at(0) & 0xe0);
1052     data.prepend(char(0x9f));
1053     data.append(ourType);
1054     data.append(char(0xff));
1055 
1056     chunkedStringTest(data, concatenated, chunks, ourType);
1057 }
1058 
stringLength_data()1059 void tst_Parser::stringLength_data()
1060 {
1061     QTest::addColumn<QByteArray>("data");
1062     QTest::addColumn<int>("expected");
1063 
1064     QTest::newRow("emptybytestring") << raw("\x40") << 0;
1065     QTest::newRow("bytestring1") << raw("\x41 ") << 1;
1066     QTest::newRow("bytestring1-nul") << raw("\x41\0") << 1;
1067     QTest::newRow("bytestring5") << raw("\x45Hello") << 5;
1068     QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") << 24;
1069     QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3') << 256;
1070 
1071     // text strings
1072     QTest::newRow("emptytextstring") << raw("\x60") << 0;
1073     QTest::newRow("textstring1") << raw("\x61 ") << 1;
1074     QTest::newRow("textstring1-nul") << raw("\x61\0") << 1;
1075     QTest::newRow("textstring5") << raw("\x65Hello") << 5;
1076     QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") << 24;
1077     QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') << 256;
1078 
1079     // strings with overlong length
1080     QTest::newRow("emptybytestring*1") << raw("\x58\x00") << 0;
1081     QTest::newRow("emptytextstring*1") << raw("\x78\x00") << 0;
1082     QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << 0;
1083     QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << 0;
1084     QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << 0;
1085     QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << 0;
1086     QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << 0;
1087     QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << 0;
1088     QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << 5;
1089     QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << 5;
1090     QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << 5;
1091     QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << 5;
1092     QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << 5;
1093     QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << 5;
1094     QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << 5;
1095     QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << 5;
1096 
1097     // strings with undefined length
1098     QTest::newRow("_emptybytestring") << raw("\x5f\xff") << 0;
1099     QTest::newRow("_emptytextstring") << raw("\x7f\xff") << 0;
1100     QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << 0;
1101     QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << 0;
1102     QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << 0;
1103     QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << 0;
1104     QTest::newRow("_bytestring5*2") << raw("\x5f\x43Hel\x42lo\xff") << 5;
1105     QTest::newRow("_textstring5*2") << raw("\x7f\x63Hel\x62lo\xff") << 5;
1106     QTest::newRow("_bytestring5*5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << 5;
1107     QTest::newRow("_textstring5*5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << 5;
1108     QTest::newRow("_bytestring5*6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << 5;
1109     QTest::newRow("_textstring5*6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << 5;
1110 }
1111 
stringLength()1112 void tst_Parser::stringLength()
1113 {
1114     QFETCH(QByteArray, data);
1115     QFETCH(int, expected);
1116 
1117     ParserWrapper w;
1118     CborError err = w.init(data);
1119     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1120 
1121     size_t result;
1122     err = cbor_value_calculate_string_length(&w.first, &result);
1123     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1124     QCOMPARE(result, size_t(expected));
1125 
1126     if (cbor_value_is_length_known(&w.first)) {
1127         QCOMPARE(cbor_value_get_string_length(&w.first, &result), CborNoError);
1128         QCOMPARE(result, size_t(expected));
1129     }
1130 
1131 }
1132 
stringCompare_data()1133 void tst_Parser::stringCompare_data()
1134 {
1135     QTest::addColumn<QByteArray>("data");
1136     QTest::addColumn<QString>("string");
1137     QTest::addColumn<bool>("expected");
1138 
1139     // compare empty to empty
1140     QTest::newRow("empty-empty") << raw("\x60") << QString() << true;
1141     QTest::newRow("_empty-empty") << raw("\x7f\xff") << QString() << true;
1142     QTest::newRow("_empty*1-empty") << raw("\x7f\x60\xff") << QString() << true;
1143     QTest::newRow("_empty*2-empty") << raw("\x7f\x60\x60\xff") << QString() << true;
1144 
1145     // compare empty to non-empty
1146     QTest::newRow("empty-nonempty") << raw("\x60") << "Hello" << false;
1147     QTest::newRow("_empty-nonempty") << raw("\x7f\xff") << "Hello" << false;
1148     QTest::newRow("_empty*1-nonempty") << raw("\x7f\x60\xff") << "Hello" << false;
1149     QTest::newRow("_empty*2-nonempty") << raw("\x7f\x60\x60\xff") << "Hello" << false;
1150 
1151     // compare same strings
1152     QTest::newRow("same-short-short") << raw("\x65Hello") << "Hello" << true;
1153     QTest::newRow("same-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello" << true;
1154     QTest::newRow("same-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello" << true;
1155     QTest::newRow("same-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello" << true;
1156     QTest::newRow("same-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello" << true;
1157     QTest::newRow("same-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
1158                                     << "Good morning, good afternoon and goodnight" << true;
1159     QTest::newRow("same-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
1160                                        << "Good morning, good afternoon and goodnight" << true;
1161     QTest::newRow("same-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
1162                                        << "Good morning, good afternoon and goodnight" << true;
1163 
1164     // compare different strings (same length)
1165     QTest::newRow("diff-same-length-short-short") << raw("\x65Hello") << "World" << false;
1166     QTest::newRow("diff-same-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "World" << false;
1167     QTest::newRow("diff-same-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "World" << false;
1168     QTest::newRow("diff-same-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "World" << false;
1169     QTest::newRow("diff-same-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "World" << false;
1170     QTest::newRow("diff-same-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
1171                                                 << "Good morning, good afternoon and goodnight, world" << false;
1172     QTest::newRow("diff-same-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
1173                                                    << "Good morning, good afternoon and goodnight, world" << false;
1174     QTest::newRow("diff-same-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
1175                                                    << "Good morning, good afternoon and goodnight, world" << false;
1176 
1177     // compare different strings (different length)
1178     QTest::newRow("diff-diff-length-short-short") << raw("\x65Hello") << "Hello World" << false;
1179     QTest::newRow("diff-diff-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello World" << false;
1180     QTest::newRow("diff-diff-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello World" << false;
1181     QTest::newRow("diff-diff-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello World" << false;
1182     QTest::newRow("diff-diff-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello World" << false;
1183     QTest::newRow("diff-diff-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
1184                                                 << "Good morning, good afternoon and goodnight World" << false;
1185     QTest::newRow("diff-diff-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
1186                                                    << "Good morning, good afternoon and goodnight World" << false;
1187     QTest::newRow("diff-diff-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
1188                                                    << "Good morning, good afternoon and goodnight World" << false;
1189 
1190     // compare against non-strings
1191     QTest::newRow("unsigned") << raw("\0") << "0" << false;
1192     QTest::newRow("negative") << raw("\x20") << "-1" << false;
1193     QTest::newRow("emptybytestring") << raw("\x40") << "" << false;
1194     QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "" << false;
1195     QTest::newRow("shortbytestring") << raw("\x45Hello") << "Hello" << false;
1196     QTest::newRow("longbytestring") << raw("\x58\x2aGood morning, good afternoon and goodnight")
1197                                     << "Good morning, good afternoon and goodnight" << false;
1198     QTest::newRow("emptyarray") << raw("\x80") << "" << false;
1199     QTest::newRow("emptymap") << raw("\xa0") << "" << false;
1200     QTest::newRow("array") << raw("\x81\x65Hello") << "Hello" << false;
1201     QTest::newRow("map") << raw("\xa1\x65Hello\x65World") << "Hello World" << false;
1202     QTest::newRow("false") << raw("\xf4") << "false" << false;
1203     QTest::newRow("true") << raw("\xf5") << "true" << false;
1204     QTest::newRow("null") << raw("\xf6") << "null" << false;
1205 }
1206 
compareOneString(const QByteArray & data,const QString & string,bool expected,int line)1207 void compareOneString(const QByteArray &data, const QString &string, bool expected, int line)
1208 {
1209     compareFailed = true;
1210 
1211     ParserWrapper w;
1212     CborError err = w.init(data);
1213     QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
1214 
1215     bool result;
1216     QByteArray bastring = string.toUtf8();
1217     err = cbor_value_text_string_equals(&w.first, bastring.constData(), &result);
1218     QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
1219     QCOMPARE(result, expected);
1220 
1221     if (expected) {
1222         size_t len;
1223         cbor_value_skip_tag(&w.first);
1224         if (cbor_value_is_length_known(&w.first)) {
1225             QCOMPARE(cbor_value_get_string_length(&w.first, &len), CborNoError);
1226             QCOMPARE(int(len), bastring.size());
1227         }
1228         QCOMPARE(cbor_value_calculate_string_length(&w.first, &len), CborNoError);
1229         QCOMPARE(int(len), bastring.size());
1230     }
1231 
1232     compareFailed = false;
1233 }
1234 #define compareOneString(data, string, expected) compareOneString(data, string, expected, __LINE__)
1235 
stringCompare()1236 void tst_Parser::stringCompare()
1237 {
1238     QFETCH(QByteArray, data);
1239     QFETCH(QString, string);
1240     QFETCH(bool, expected);
1241 
1242     compareOneString(data, string, expected);
1243     if (compareFailed) return;
1244 
1245     // tag it
1246     compareOneString("\xc1" + data, string, expected);
1247     if (compareFailed) return;
1248 
1249     compareOneString("\xc1\xc2" + data, string, expected);
1250 }
1251 
mapFind_data()1252 void tst_Parser::mapFind_data()
1253 {
1254     // Rules:
1255     //  we are searching for string "needle"
1256     //  if present, the value should be the string "haystack" (with tag 42)
1257 
1258     QTest::addColumn<QByteArray>("data");
1259     QTest::addColumn<bool>("expected");
1260 
1261     QTest::newRow("emptymap") << raw("\xa0") << false;
1262     QTest::newRow("_emptymap") << raw("\xbf\xff") << false;
1263 
1264     // maps not containing our items
1265     QTest::newRow("absent-unsigned-unsigned") << raw("\xa1\0\0") << false;
1266     QTest::newRow("absent-taggedunsigned-unsigned") << raw("\xa1\xc0\0\0") << false;
1267     QTest::newRow("absent-unsigned-taggedunsigned") << raw("\xa1\0\xc0\0") << false;
1268     QTest::newRow("absent-taggedunsigned-taggedunsigned") << raw("\xa1\xc0\0\xc0\0") << false;
1269     QTest::newRow("absent-string-unsigned") << raw("\xa1\x68haystack\0") << false;
1270     QTest::newRow("absent-taggedstring-unsigned") << raw("\xa1\xc0\x68haystack\0") << false;
1271     QTest::newRow("absent-string-taggedunsigned") << raw("\xa1\x68haystack\xc0\0") << false;
1272     QTest::newRow("absent-taggedstring-taggedunsigned") << raw("\xa1\xc0\x68haystack\xc0\0") << false;
1273     QTest::newRow("absent-string-string") << raw("\xa1\x68haystack\x66needle") << false;
1274     QTest::newRow("absent-string-taggedstring") << raw("\xa1\x68haystack\xc0\x66needle") << false;
1275     QTest::newRow("absent-taggedstring-string") << raw("\xa1\xc0\x68haystack\x66needle") << false;
1276     QTest::newRow("absent-string-taggedstring") << raw("\xa1\xc0\x68haystack\xc0\x66needle") << false;
1277 
1278     QTest::newRow("absent-string-emptyarray") << raw("\xa1\x68haystack\x80") << false;
1279     QTest::newRow("absent-string-_emptyarray") << raw("\xa1\x68haystack\x9f\xff") << false;
1280     QTest::newRow("absent-string-array1") << raw("\xa1\x68haystack\x81\0") << false;
1281     QTest::newRow("absent-string-array2") << raw("\xa1\x68haystack\x85\0\1\2\3\4") << false;
1282     QTest::newRow("absent-string-array3") << raw("\xa1\x68haystack\x85\x63one\x63two\x65three\x64""four\x64""five") << false;
1283 
1284     QTest::newRow("absent-string-emptymap") << raw("\xa1\x68haystack\xa0") << false;
1285     QTest::newRow("absent-string-_emptymap") << raw("\xa1\x68haystack\xbf\xff") << false;
1286     QTest::newRow("absent-string-map") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle") << false;
1287     QTest::newRow("absent-string-map2") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle\61z\62yx") << false;
1288 
1289     // maps containing our items
1290     QTest::newRow("alone") << raw("\xa1\x66needle\xd8\x2a\x68haystack") << true;
1291     QTest::newRow("tagged") << raw("\xa1\xc1\x66needle\xd8\x2a\x68haystack") << true;
1292     QTest::newRow("doubletagged") << raw("\xa1\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true;
1293     QTest::newRow("chunked") << raw("\xa1\x7f\x66needle\xff\xd8\x2a\x68haystack") << true;
1294     QTest::newRow("chunked*2") << raw("\xa1\x7f\x60\x66needle\xff\xd8\x2a\x68haystack") << true;
1295     QTest::newRow("chunked*2bis") << raw("\xa1\x7f\x66needle\x60\xff\xd8\x2a\x68haystack") << true;
1296     QTest::newRow("chunked*3") << raw("\xa1\x7f\x62ne\x62""ed\x62le\xff\xd8\x2a\x68haystack") << true;
1297     QTest::newRow("chunked*8") << raw("\xa1\x7f\x61n\x61""e\x60\x61""e\x61""d\x60\x62le\x60\xff\xd8\x2a\x68haystack") << true;
1298 
1299     QTest::newRow("1before") << raw("\xa2\x68haystack\x66needle\x66needle\xd8\x2a\x68haystack") << true;
1300     QTest::newRow("tagged-1before") << raw("\xa2\xc1\x68haystack\x66needle\xc1\x66needle\xd8\x2a\x68haystack") << true;
1301     QTest::newRow("doubletagged-1before2") << raw("\xa2\xc1\xc2\x68haystack\x66needle\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true;
1302 
1303     QTest::newRow("arraybefore") << raw("\xa2\x61z\x80\x66needle\xd8\x2a\x68haystack") << true;
1304     QTest::newRow("nestedarraybefore") << raw("\xa2\x61z\x81\x81\0\x66needle\xd8\x2a\x68haystack") << true;
1305     QTest::newRow("arrayarraybefore") << raw("\xa2\x82\1\2\x80\x66needle\xd8\x2a\x68haystack") << true;
1306 
1307     QTest::newRow("mapbefore") << raw("\xa2\x61z\xa0\x66needle\xd8\x2a\x68haystack") << true;
1308     QTest::newRow("nestedmapbefore") << raw("\xa2\x61z\xa1\0\x81\0\x66needle\xd8\x2a\x68haystack") << true;
1309     QTest::newRow("mapmapbefore") << raw("\xa2\xa1\1\2\xa0\x66needle\xd8\x2a\x68haystack") << true;
1310 }
1311 
mapFind()1312 void tst_Parser::mapFind()
1313 {
1314     QFETCH(QByteArray, data);
1315     QFETCH(bool, expected);
1316 
1317     ParserWrapper w;
1318     CborError err = w.init(data);
1319     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1320 
1321     CborValue element;
1322     err = cbor_value_map_find_value(&w.first, "needle", &element);
1323     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1324 
1325     if (expected) {
1326         QCOMPARE(int(element.type), int(CborTagType));
1327 
1328         CborTag tag;
1329         err = cbor_value_get_tag(&element, &tag);
1330         QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1331         QCOMPARE(int(tag), 42);
1332 
1333         bool equals;
1334         err = cbor_value_text_string_equals(&element, "haystack", &equals);
1335         QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1336         QVERIFY(equals);
1337     } else {
1338         QCOMPARE(int(element.type), int(CborInvalidType));
1339     }
1340 }
1341 
checkedIntegers_data()1342 void tst_Parser::checkedIntegers_data()
1343 {
1344     QTest::addColumn<QByteArray>("data");
1345     QTest::addColumn<QVariant>("result");       // QVariant so we can note numbers out of int64_t range
1346 
1347     QTest::newRow("0") << raw("\x00") << QVariant(Q_INT64_C(0));
1348     QTest::newRow("1") << raw("\x01") << QVariant(Q_INT64_C(1));
1349     QTest::newRow("10") << raw("\x0a") << QVariant(Q_INT64_C(10));
1350     QTest::newRow("23") << raw("\x17") << QVariant(Q_INT64_C(23));
1351     QTest::newRow("24") << raw("\x18\x18") << QVariant(Q_INT64_C(24));
1352     QTest::newRow("UINT8_MAX") << raw("\x18\xff") << QVariant(Q_INT64_C(255));
1353     QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << QVariant(Q_INT64_C(256));
1354     QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << QVariant(Q_INT64_C(65535));
1355     QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << QVariant(Q_INT64_C(65536));
1356     QTest::newRow("INT32_MAX") << raw("\x1a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(2147483647));
1357     QTest::newRow("INT32_MAX+1") << raw("\x1a\x80\x00\x00\x00") << QVariant(Q_INT64_C(2147483648));
1358     QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295));
1359     QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296));
1360     QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
1361                                 << QVariant();  // out of range
1362 
1363     // negative integers
1364     QTest::newRow("-1") << raw("\x20") << QVariant(Q_INT64_C(-1));
1365     QTest::newRow("-2") << raw("\x21") << QVariant(Q_INT64_C(-2));
1366     QTest::newRow("-24") << raw("\x37") << QVariant(Q_INT64_C(-24));
1367     QTest::newRow("-25") << raw("\x38\x18") << QVariant(Q_INT64_C(-25));
1368     QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(Q_INT64_C(-256));
1369     QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(Q_INT64_C(-257));
1370     QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(Q_INT64_C(-65536));
1371     QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(Q_INT64_C(-65537));
1372     QTest::newRow("INT32_MIN") << raw("\x3a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(-2147483648));
1373     QTest::newRow("INT32_MIN-1") << raw("\x3a\x80\x00\x00\x00") << QVariant(Q_INT64_C(-2147483649));
1374     QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296));
1375     QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297));
1376     QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
1377                                << QVariant(std::numeric_limits<qint64>::min() + 1);
1378     QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
1379                                << QVariant(std::numeric_limits<qint64>::min());
1380     QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << QVariant();  // out of range
1381     QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
1382                                    << QVariant();   // out of range
1383     QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
1384                                    << QVariant();   // out of range
1385 }
1386 
checkedIntegers()1387 void tst_Parser::checkedIntegers()
1388 {
1389     QFETCH(QByteArray, data);
1390     QFETCH(QVariant, result);
1391     int64_t expected = result.toLongLong();
1392 
1393     ParserWrapper w;
1394     CborError err = w.init(data);
1395     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1396 
1397     int64_t v;
1398     err = cbor_value_get_int64_checked(&w.first, &v);
1399     if (result.isNull()) {
1400         QCOMPARE(err, CborErrorDataTooLarge);
1401     } else {
1402         QCOMPARE(v, expected);
1403     }
1404 
1405     int v2;
1406     err = cbor_value_get_int_checked(&w.first, &v2);
1407     if (result.isNull() || expected < std::numeric_limits<int>::min() || expected > std::numeric_limits<int>::max()) {
1408         QCOMPARE(err, CborErrorDataTooLarge);
1409     } else {
1410         QCOMPARE(int64_t(v2), expected);
1411     }
1412 }
1413 
addValidationColumns()1414 static void addValidationColumns()
1415 {
1416     QTest::addColumn<QByteArray>("data");
1417     QTest::addColumn<int>("flags");     // future
1418     QTest::addColumn<CborError>("expectedError");
1419 }
1420 
addValidationData()1421 static void addValidationData()
1422 {
1423     // illegal numbers are future extension points
1424     QTest::newRow("illegal-number-in-unsigned-1") << raw("\x81\x1c") << 0 << CborErrorIllegalNumber;
1425     QTest::newRow("illegal-number-in-unsigned-2") << raw("\x81\x1d") << 0 << CborErrorIllegalNumber;
1426     QTest::newRow("illegal-number-in-unsigned-3") << raw("\x81\x1e") << 0 << CborErrorIllegalNumber;
1427     QTest::newRow("illegal-number-in-unsigned-4") << raw("\x81\x1f") << 0 << CborErrorIllegalNumber;
1428     QTest::newRow("illegal-number-in-negative-1") << raw("\x81\x3c") << 0 << CborErrorIllegalNumber;
1429     QTest::newRow("illegal-number-in-negative-2") << raw("\x81\x3d") << 0 << CborErrorIllegalNumber;
1430     QTest::newRow("illegal-number-in-negative-3") << raw("\x81\x3e") << 0 << CborErrorIllegalNumber;
1431     QTest::newRow("illegal-number-in-negative-4") << raw("\x81\x3f") << 0 << CborErrorIllegalNumber;
1432     QTest::newRow("illegal-number-in-bytearray-length-1") << raw("\x81\x5c") << 0 << CborErrorIllegalNumber;
1433     QTest::newRow("illegal-number-in-bytearray-length-2") << raw("\x81\x5d") << 0 << CborErrorIllegalNumber;
1434     QTest::newRow("illegal-number-in-bytearray-length-3") << raw("\x81\x5e") << 0 << CborErrorIllegalNumber;
1435     QTest::newRow("illegal-number-in-string-length-1") << raw("\x81\x7c") << 0 << CborErrorIllegalNumber;
1436     QTest::newRow("illegal-number-in-string-length-2") << raw("\x81\x7d") << 0 << CborErrorIllegalNumber;
1437     QTest::newRow("illegal-number-in-string-length-3") << raw("\x81\x7e") << 0 << CborErrorIllegalNumber;
1438     QTest::newRow("illegal-number-in-array-length-1") << raw("\x81\x9c") << 0 << CborErrorIllegalNumber;
1439     QTest::newRow("illegal-number-in-array-length-2") << raw("\x81\x9d") << 0 << CborErrorIllegalNumber;
1440     QTest::newRow("illegal-number-in-array-length-3") << raw("\x81\x9e") << 0 << CborErrorIllegalNumber;
1441     QTest::newRow("illegal-number-in-map-length-1") << raw("\x81\xbc") << 0 << CborErrorIllegalNumber;
1442     QTest::newRow("illegal-number-in-map-length-2") << raw("\x81\xbd") << 0 << CborErrorIllegalNumber;
1443     QTest::newRow("illegal-number-in-map-length-3") << raw("\x81\xbe") << 0 << CborErrorIllegalNumber;
1444     QTest::newRow("illegal-number-in-tag-1") << raw("\x81\xdc") << 0 << CborErrorIllegalNumber;
1445     QTest::newRow("illegal-number-in-tag-2") << raw("\x81\xdd") << 0 << CborErrorIllegalNumber;
1446     QTest::newRow("illegal-number-in-tag-3") << raw("\x81\xde") << 0 << CborErrorIllegalNumber;
1447     QTest::newRow("illegal-number-in-tag-4") << raw("\x81\xdf") << 0 << CborErrorIllegalNumber;
1448 
1449     QTest::newRow("unsigned-too-short-1-0") << raw("\x81\x18") << 0 << CborErrorUnexpectedEOF;   // requires 1 byte, 0 given
1450     QTest::newRow("unsigned-too-short-2-0") << raw("\x81\x19") << 0 << CborErrorUnexpectedEOF;   // requires 2 bytes, 0 given
1451     QTest::newRow("unsigned-too-short-2-1") << raw("\x81\x19\x01") << 0 << CborErrorUnexpectedEOF; // etc
1452     QTest::newRow("unsigned-too-short-4-0") << raw("\x81\x1a") << 0 << CborErrorUnexpectedEOF;
1453     QTest::newRow("unsigned-too-short-4-3") << raw("\x81\x1a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1454     QTest::newRow("unsigned-too-short-8-0") << raw("\x81\x1b") << 0 << CborErrorUnexpectedEOF;
1455     QTest::newRow("unsigned-too-short-8-7") << raw("\x81\x1b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1456     QTest::newRow("negative-length-too-short-1-0") << raw("\x81\x38") << 0 << CborErrorUnexpectedEOF;
1457     QTest::newRow("negative-length-too-short-2-0") << raw("\x81\x39") << 0 << CborErrorUnexpectedEOF;
1458     QTest::newRow("negative-length-too-short-2-1") << raw("\x81\x39\x01") << 0 << CborErrorUnexpectedEOF;
1459     QTest::newRow("negative-length-too-short-4-0") << raw("\x81\x3a") << 0 << CborErrorUnexpectedEOF;
1460     QTest::newRow("negative-length-too-short-4-3") << raw("\x81\x3a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1461     QTest::newRow("negative-length-too-short-8-0") << raw("\x81\x3b") << 0 << CborErrorUnexpectedEOF;
1462     QTest::newRow("negative-length-too-short-8-7") << raw("\x81\x3b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1463     QTest::newRow("bytearray-length-too-short-1-0") << raw("\x81\x58") << 0 << CborErrorUnexpectedEOF;
1464     QTest::newRow("bytearray-length-too-short-2-0") << raw("\x81\x59") << 0 << CborErrorUnexpectedEOF;
1465     QTest::newRow("bytearray-length-too-short-2-1") << raw("\x81\x59\x01") << 0 << CborErrorUnexpectedEOF;
1466     QTest::newRow("bytearray-length-too-short-4-0") << raw("\x81\x5a") << 0 << CborErrorUnexpectedEOF;
1467     QTest::newRow("bytearray-length-too-short-4-3") << raw("\x81\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1468     QTest::newRow("bytearray-length-too-short-8-0") << raw("\x81\x5b") << 0 << CborErrorUnexpectedEOF;
1469     QTest::newRow("bytearray-length-too-short-8-7") << raw("\x81\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1470     QTest::newRow("string-length-too-short-1-0") << raw("\x81\x78") << 0 << CborErrorUnexpectedEOF;
1471     QTest::newRow("string-length-too-short-2-0") << raw("\x81\x79") << 0 << CborErrorUnexpectedEOF;
1472     QTest::newRow("string-length-too-short-2-1") << raw("\x81\x79\x01") << 0 << CborErrorUnexpectedEOF;
1473     QTest::newRow("string-length-too-short-4-0") << raw("\x81\x7a") << 0 << CborErrorUnexpectedEOF;
1474     QTest::newRow("string-length-too-short-4-3") << raw("\x81\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1475     QTest::newRow("string-length-too-short-8-0") << raw("\x81\x7b") << 0 << CborErrorUnexpectedEOF;
1476     QTest::newRow("string-length-too-short-8-7") << raw("\x81\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1477     QTest::newRow("bytearray-chunked-length-too-short-1-0") << raw("\x81\x5f\x58") << 0 << CborErrorUnexpectedEOF;
1478     QTest::newRow("bytearray-chunked-length-too-short-2-0") << raw("\x81\x5f\x59") << 0 << CborErrorUnexpectedEOF;
1479     QTest::newRow("bytearray-chunked-length-too-short-2-1") << raw("\x81\x5f\x59\x01") << 0 << CborErrorUnexpectedEOF;
1480     QTest::newRow("bytearray-chunked-length-too-short-4-0") << raw("\x81\x5f\x5a") << 0 << CborErrorUnexpectedEOF;
1481     QTest::newRow("bytearray-chunked-length-too-short-4-3") << raw("\x81\x5f\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1482     QTest::newRow("bytearray-chunked-length-too-short-8-0") << raw("\x81\x5f\x5b") << 0 << CborErrorUnexpectedEOF;
1483     QTest::newRow("bytearray-chunked-length-too-short-8-7") << raw("\x81\x5f\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1484     QTest::newRow("string-chunked-length-too-short-1-0") << raw("\x81\x7f\x78") << 0 << CborErrorUnexpectedEOF;
1485     QTest::newRow("string-chunked-length-too-short-2-0") << raw("\x81\x7f\x79") << 0 << CborErrorUnexpectedEOF;
1486     QTest::newRow("string-chunked-length-too-short-2-1") << raw("\x81\x7f\x79\x01") << 0 << CborErrorUnexpectedEOF;
1487     QTest::newRow("string-chunked-length-too-short-4-0") << raw("\x81\x7f\x7a") << 0 << CborErrorUnexpectedEOF;
1488     QTest::newRow("string-chunked-length-too-short-4-3") << raw("\x81\x7f\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1489     QTest::newRow("string-chunked-length-too-short-8-0") << raw("\x81\x7f\x7b") << 0 << CborErrorUnexpectedEOF;
1490     QTest::newRow("string-chunked-length-too-short-8-7") << raw("\x81\x7f\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1491     QTest::newRow("bytearray-chunked-2-length-too-short-1-0") << raw("\x81\x5f\x40\x58") << 0 << CborErrorUnexpectedEOF;
1492     QTest::newRow("bytearray-chunked-2-length-too-short-2-0") << raw("\x81\x5f\x40\x59") << 0 << CborErrorUnexpectedEOF;
1493     QTest::newRow("bytearray-chunked-2-length-too-short-2-1") << raw("\x81\x5f\x40\x59\x01") << 0 << CborErrorUnexpectedEOF;
1494     QTest::newRow("bytearray-chunked-2-length-too-short-4-0") << raw("\x81\x5f\x40\x5a") << 0 << CborErrorUnexpectedEOF;
1495     QTest::newRow("bytearray-chunked-2-length-too-short-4-3") << raw("\x81\x5f\x40\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1496     QTest::newRow("bytearray-chunked-2-length-too-short-8-0") << raw("\x81\x5f\x40\x5b") << 0 << CborErrorUnexpectedEOF;
1497     QTest::newRow("bytearray-chunked-2-length-too-short-8-7") << raw("\x81\x5f\x40\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1498     QTest::newRow("string-chunked-2-length-too-short-1-0") << raw("\x81\x7f\x60\x78") << 0 << CborErrorUnexpectedEOF;
1499     QTest::newRow("string-chunked-2-length-too-short-2-0") << raw("\x81\x7f\x60\x79") << 0 << CborErrorUnexpectedEOF;
1500     QTest::newRow("string-chunked-2-length-too-short-2-1") << raw("\x81\x7f\x60\x79\x01") << 0 << CborErrorUnexpectedEOF;
1501     QTest::newRow("string-chunked-2-length-too-short-4-0") << raw("\x81\x7f\x60\x7a") << 0 << CborErrorUnexpectedEOF;
1502     QTest::newRow("string-chunked-2-length-too-short-4-3") << raw("\x81\x7f\x60\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1503     QTest::newRow("string-chunked-2-length-too-short-8-0") << raw("\x81\x7f\x60\x7b") << 0 << CborErrorUnexpectedEOF;
1504     QTest::newRow("string-chunked-2-length-too-short-8-7") << raw("\x81\x7f\x60\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1505     QTest::newRow("array-length-too-short-1-0") << raw("\x81\x98") << 0 << CborErrorUnexpectedEOF;
1506     QTest::newRow("array-length-too-short-2-0") << raw("\x81\x99") << 0 << CborErrorUnexpectedEOF;
1507     QTest::newRow("array-length-too-short-2-1") << raw("\x81\x99\x01") << 0 << CborErrorUnexpectedEOF;
1508     QTest::newRow("array-length-too-short-4-0") << raw("\x81\x9a") << 0 << CborErrorUnexpectedEOF;
1509     QTest::newRow("array-length-too-short-4-3") << raw("\x81\x9a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1510     QTest::newRow("array-length-too-short-8-0") << raw("\x81\x9b") << 0 << CborErrorUnexpectedEOF;
1511     QTest::newRow("array-length-too-short-8-7") << raw("\x81\x9b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1512     QTest::newRow("map-length-too-short-1-0") << raw("\x81\xb8") << 0 << CborErrorUnexpectedEOF;
1513     QTest::newRow("map-length-too-short-2-0") << raw("\x81\xb9") << 0 << CborErrorUnexpectedEOF;
1514     QTest::newRow("map-length-too-short-2-1") << raw("\x81\xb9\x01") << 0 << CborErrorUnexpectedEOF;
1515     QTest::newRow("map-length-too-short-4-0") << raw("\x81\xba") << 0 << CborErrorUnexpectedEOF;
1516     QTest::newRow("map-length-too-short-4-3") << raw("\x81\xba\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1517     QTest::newRow("map-length-too-short-8-0") << raw("\x81\xbb") << 0 << CborErrorUnexpectedEOF;
1518     QTest::newRow("map-length-too-short-8-7") << raw("\x81\xbb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1519     QTest::newRow("tag-too-short-1-0") << raw("\x81\xd8") << 0 << CborErrorUnexpectedEOF;
1520     QTest::newRow("tag-too-short-2-0") << raw("\x81\xd9") << 0 << CborErrorUnexpectedEOF;
1521     QTest::newRow("tag-too-short-2-1") << raw("\x81\xd9\x01") << 0 << CborErrorUnexpectedEOF;
1522     QTest::newRow("tag-too-short-4-0") << raw("\x81\xda") << 0 << CborErrorUnexpectedEOF;
1523     QTest::newRow("tag-too-short-4-3") << raw("\x81\xda\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
1524     QTest::newRow("tag-too-short-8-0") << raw("\x81\xdb") << 0 << CborErrorUnexpectedEOF;
1525     QTest::newRow("tag-too-short-8-7") << raw("\x81\xdb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
1526     QTest::newRow("fp16-too-short1") << raw("\x81\xf9") << 0 << CborErrorUnexpectedEOF;
1527     QTest::newRow("fp16-too-short2") << raw("\x81\xf9\x00") << 0 << CborErrorUnexpectedEOF;
1528     QTest::newRow("float-too-short1") << raw("\x81\xfa") << 0 << CborErrorUnexpectedEOF;
1529     QTest::newRow("float-too-short2") << raw("\x81\xfa\0\0\0") << 0 << CborErrorUnexpectedEOF;
1530     QTest::newRow("double-too-short1") << raw("\x81\xfb") << 0 << CborErrorUnexpectedEOF;
1531     QTest::newRow("double-too-short2") << raw("\x81\xfb\0\0\0\0\0\0\0") << 0 << CborErrorUnexpectedEOF;
1532 
1533     QTest::newRow("bytearray-too-short1") << raw("\x81\x42z") << 0 << CborErrorUnexpectedEOF;
1534     QTest::newRow("bytearray-too-short2") << raw("\x81\x58\x02z") << 0 << CborErrorUnexpectedEOF;
1535     QTest::newRow("bytearray-too-short3") << raw("\x81\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1536     QTest::newRow("bytearray-too-short4") << raw("\x81\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1537     QTest::newRow("string-too-short1") << raw("\x81\x62z") << 0 << CborErrorUnexpectedEOF;
1538     QTest::newRow("string-too-short2") << raw("\x81\x78\x02z") << 0 << CborErrorUnexpectedEOF;
1539     QTest::newRow("string-too-short3") << raw("\x81\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1540     QTest::newRow("string-too-short4") << raw("\x81\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1541     QTest::newRow("bytearray-chunked-too-short1") << raw("\x81\x5f\x42z") << 0 << CborErrorUnexpectedEOF;
1542     QTest::newRow("bytearray-chunked-too-short2") << raw("\x81\x5f\x58\x02z") << 0 << CborErrorUnexpectedEOF;
1543     QTest::newRow("bytearray-chunked-too-short3") << raw("\x81\x5f\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1544     QTest::newRow("bytearray-chunked-too-short4") << raw("\x81\x5f\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1545     QTest::newRow("string-chunked-too-short1") << raw("\x81\x7f\x62z") << 0 << CborErrorUnexpectedEOF;
1546     QTest::newRow("string-chunked-too-short2") << raw("\x81\x7f\x78\x02z") << 0 << CborErrorUnexpectedEOF;
1547     QTest::newRow("string-chunked-too-short3") << raw("\x81\x7f\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1548     QTest::newRow("string-chunked-too-short4") << raw("\x81\x7f\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1549     QTest::newRow("bytearray-chunked-too-short1x2") << raw("\x81\x5f\x40\x42z") << 0 << CborErrorUnexpectedEOF;
1550     QTest::newRow("bytearray-chunked-too-short2x2") << raw("\x81\x5f\x40\x58\x02z") << 0 << CborErrorUnexpectedEOF;
1551     QTest::newRow("bytearray-chunked-too-short3x2") << raw("\x81\x5f\x40\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1552     QTest::newRow("bytearray-chunked-too-short4x2") << raw("\x81\x5f\x40\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1553     QTest::newRow("string-chunked-too-short1x2") << raw("\x81\x7f\x60\x62z") << 0 << CborErrorUnexpectedEOF;
1554     QTest::newRow("string-chunked-too-short2x2") << raw("\x81\x7f\x60\x78\x02z") << 0 << CborErrorUnexpectedEOF;
1555     QTest::newRow("string-chunked-too-short3x2") << raw("\x81\x7f\x60\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1556     QTest::newRow("string-chunked-too-short4x2") << raw("\x81\x7f\x60\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
1557 
1558     QTest::newRow("bytearray-no-break1") << raw("\x81\x5f") << 0 << CborErrorUnexpectedEOF;
1559     QTest::newRow("bytearray-no-break2") << raw("\x81\x5f\x40") << 0 << CborErrorUnexpectedEOF;
1560     QTest::newRow("string-no-break1") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF;
1561     QTest::newRow("string-no-break2") << raw("\x81\x7f\x60") << 0 << CborErrorUnexpectedEOF;
1562     QTest::newRow("array-no-break1") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF;
1563     QTest::newRow("array-no-break2") << raw("\x81\x9f\0") << 0 << CborErrorUnexpectedEOF;
1564     QTest::newRow("map-no-break1") << raw("\x81\xbf") << 0 << CborErrorUnexpectedEOF;
1565     QTest::newRow("map-no-break2") << raw("\x81\xbf\0\0") << 0 << CborErrorUnexpectedEOF;
1566     QTest::newRow("map-break-after-key") << raw("\x81\xbf\0\xff") << 0 << CborErrorUnexpectedBreak;
1567     QTest::newRow("map-break-after-second-key") << raw("\x81\xbf\x64xyzw\x04\x00\xff") << 0 << CborErrorUnexpectedBreak;
1568     QTest::newRow("map-break-after-value-tag") << raw("\x81\xbf\0\xc0\xff") << 0 << CborErrorUnexpectedBreak;
1569     QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak;
1570 
1571     // check for pointer additions wrapping over the limit of the address space
1572     CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF;
1573     // on 32-bit systems, this is a -1
1574     QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
1575     QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
1576     // on 32-bit systems, a 4GB addition could be dropped
1577     QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
1578     QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
1579     // on 64-bit systems, this could be a -1
1580     QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
1581     QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
1582 
1583     // ditto on chunks
1584     QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
1585     QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
1586     // on 32-bit systems, a 4GB addition could be dropped
1587     QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
1588     QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
1589     // on 64-bit systems, this could be a -1
1590     QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
1591     QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
1592 
1593     QTest::newRow("eof-after-array") << raw("\x81") << 0 << CborErrorUnexpectedEOF;
1594     QTest::newRow("eof-after-array2") << raw("\x81\x78\x20") << 0 << CborErrorUnexpectedEOF;
1595     QTest::newRow("eof-after-array-element") << raw("\x81\x82\x01") << 0 << CborErrorUnexpectedEOF;
1596     QTest::newRow("eof-after-object") << raw("\x81\xa1") << 0 << CborErrorUnexpectedEOF;
1597     QTest::newRow("eof-after-object2") << raw("\x81\xb8\x20") << 0 << CborErrorUnexpectedEOF;
1598     QTest::newRow("eof-after-object-key") << raw("\x81\xa1\x01") << 0 << CborErrorUnexpectedEOF;
1599     QTest::newRow("eof-after-object-value") << raw("\x81\xa2\x01\x01") << 0 << CborErrorUnexpectedEOF;
1600     QTest::newRow("eof-after-tag") << raw("\x81\xc0") << 0 << CborErrorUnexpectedEOF;
1601     QTest::newRow("eof-after-tag2") << raw("\x81\xd8\x20") << 0 << CborErrorUnexpectedEOF;
1602 
1603     // major type 7 has future types
1604     QTest::newRow("future-type-28") << raw("\x81\xfc") << 0 << CborErrorUnknownType;
1605     QTest::newRow("future-type-29") << raw("\x81\xfd") << 0 << CborErrorUnknownType;
1606     QTest::newRow("future-type-30") << raw("\x81\xfe") << 0 << CborErrorUnknownType;
1607     QTest::newRow("unexpected-break") << raw("\x81\xff") << 0 << CborErrorUnexpectedBreak;
1608     QTest::newRow("illegal-simple-0") << raw("\x81\xf8\0") << 0 << CborErrorIllegalSimpleType;
1609     QTest::newRow("illegal-simple-31") << raw("\x81\xf8\x1f") << 0 << CborErrorIllegalSimpleType;
1610 
1611     // not only too big (UINT_MAX or UINT_MAX+1 in size), but also incomplete
1612     if (sizeof(size_t) < sizeof(uint64_t)) {
1613         QTest::newRow("bytearray-too-big1") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
1614         QTest::newRow("string-too-big1") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
1615     }
1616     QTest::newRow("array-too-big1") << raw("\x81\x9a\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge;
1617     QTest::newRow("array-too-big2") << raw("\x81\x9b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
1618     QTest::newRow("object-too-big1") << raw("\x81\xba\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge;
1619     QTest::newRow("object-too-big2") << raw("\x81\xbb\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
1620 
1621     QTest::newRow("no-break-for-array0") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF;
1622     QTest::newRow("no-break-for-array1") << raw("\x81\x9f\x01") << 0 << CborErrorUnexpectedEOF;
1623 
1624     QTest::newRow("no-break-string0") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF;
1625     QTest::newRow("no-break-string1") << raw("\x81\x7f\x61Z") << 0 << CborErrorUnexpectedEOF;
1626 
1627     QTest::newRow("nested-indefinite-length-bytearrays") << raw("\x81\x5f\x5f\xff\xff") << 0 << CborErrorIllegalNumber;
1628     QTest::newRow("nested-indefinite-length-strings") << raw("\x81\x7f\x7f\xff\xff") << 0 << CborErrorIllegalNumber;
1629 
1630     QTest::newRow("string-chunk-unsigned") << raw("\x81\x7f\0\xff") << 0 << CborErrorIllegalType;
1631     QTest::newRow("string-chunk-negative") << raw("\x81\x7f\x20\xff") << 0 << CborErrorIllegalType;
1632     QTest::newRow("string-chunk-bytearray") << raw("\x81\x7f\x40\xff") << 0 << CborErrorIllegalType;
1633     QTest::newRow("string-chunk-array") << raw("\x81\x7f\x80\xff") << 0 << CborErrorIllegalType;
1634     QTest::newRow("string-chunk-map") << raw("\x81\x7f\xa0\xff") << 0 << CborErrorIllegalType;
1635     QTest::newRow("string-chunk-tag") << raw("\x81\x7f\xc0\xff") << 0 << CborErrorIllegalType;
1636     QTest::newRow("string-chunk-tagged-string") << raw("\x81\x7f\xc0\x60\xff") << 0 << CborErrorIllegalType;
1637     QTest::newRow("string-chunk-simple0") << raw("\x81\x7f\xe0\xff") << 0 << CborErrorIllegalType;
1638     QTest::newRow("string-chunk-false") << raw("\x81\x7f\xf4\xff") << 0 << CborErrorIllegalType;
1639     QTest::newRow("string-chunk-true") << raw("\x81\x7f\xf5\xff") << 0 << CborErrorIllegalType;
1640     QTest::newRow("string-chunk-null") << raw("\x81\x7f\xf6\xff") << 0 << CborErrorIllegalType;
1641     QTest::newRow("string-chunk-undefined") << raw("\x81\x7f\xf7\xff") << 0 << CborErrorIllegalType;
1642 
1643     QTest::newRow("bytearray-chunk-string") << raw("\x81\x5f\x60\xff") << 0 << CborErrorIllegalType;
1644     QTest::newRow("bytearray-chunk-tagged-bytearray") << raw("\x81\x7f\xc0\x40\xff") << 0 << CborErrorIllegalType;
1645 
1646     // RFC 7049 Section 2.2.2 "Indefinite-Length Byte Strings and Text Strings" says
1647     //    Text strings with indefinite lengths act the same as byte strings
1648     //    with indefinite lengths, except that all their chunks MUST be
1649     //    definite-length text strings.  Note that this implies that the bytes
1650     //    of a single UTF-8 character cannot be spread between chunks: a new
1651     //    chunk can only be started at a character boundary.
1652     // This test technically tests the dumper, not the parser.
1653     QTest::newRow("string-utf8-chunk-split") << raw("\x81\x7f\x61\xc2\x61\xa0\xff") << 0 << CborErrorInvalidUtf8TextString;
1654 }
1655 
validation_data()1656 void tst_Parser::validation_data()
1657 {
1658     addValidationColumns();
1659     addValidationData();
1660 }
1661 
validation()1662 void tst_Parser::validation()
1663 {
1664     QFETCH(QByteArray, data);
1665     QFETCH(int, flags);
1666     QFETCH(CborError, expectedError);
1667 
1668     QString decoded;
1669     ParserWrapper w;
1670     CborError err = w.init(data, uint32_t(flags));
1671     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1672 
1673     CborError err2 = cbor_value_validate_basic(&w.first);
1674     CborError err3 = cbor_value_validate(&w.first, CborValidateBasic);
1675     err = parseOne(&w.first, &decoded);
1676     QCOMPARE(err, expectedError);
1677     if (!QByteArray(QTest::currentDataTag()).contains("utf8")) {
1678         QCOMPARE(err2, expectedError);
1679         QCOMPARE(err3, expectedError);
1680     }
1681 
1682     // see if we've got a map
1683     if (QByteArray(QTest::currentDataTag()).startsWith("map")) {
1684         w.init(data, uint32_t(flags));      // reinit
1685         QVERIFY(cbor_value_is_array(&w.first));
1686 
1687         CborValue map;
1688         CborError err = cbor_value_enter_container(&w.first, &map);
1689         if (err == CborNoError) {
1690             QVERIFY(cbor_value_is_map(&map));
1691             CborValue element;
1692             err = cbor_value_map_find_value(&map, "foobar", &element);
1693             if (err == CborNoError)
1694                 QVERIFY(!cbor_value_is_valid(&element));
1695         }
1696 
1697         QCOMPARE(err, expectedError);
1698     }
1699 }
1700 
strictValidation_data()1701 void tst_Parser::strictValidation_data()
1702 {
1703     addValidationColumns();
1704 
1705     // Canonical validation - fixed types
1706     QTest::newRow("unsigned-0") << raw("\x00") << int(CborValidateCanonicalFormat) << CborNoError;
1707     QTest::newRow("unsigned-24") << raw("\x18\x18") << int(CborValidateCanonicalFormat) << CborNoError;
1708     QTest::newRow("unsigned-256") << raw("\x19\1\0") << int(CborValidateCanonicalFormat) << CborNoError;
1709     QTest::newRow("unsigned-65536") << raw("\x1a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1710     QTest::newRow("unsigned-4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1711     QTest::newRow("overlong-unsigned-0*1") << raw("\x18\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1712     QTest::newRow("overlong-unsigned-0*2") << raw("\x19\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1713     QTest::newRow("overlong-unsigned-0*4") << raw("\x1a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1714     QTest::newRow("overlong-unsigned-0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1715     QTest::newRow("overlong-unsigned-24*2") << raw("\x19\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1716     QTest::newRow("overlong-unsigned-24*4") << raw("\x1a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1717     QTest::newRow("overlong-unsigned-24*8") << raw("\x1b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1718     QTest::newRow("overlong-unsigned-256*4") << raw("\x1a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1719     QTest::newRow("overlong-unsigned-256*8") << raw("\x1b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1720     QTest::newRow("overlong-unsigned-65536*8") << raw("\x1b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1721     QTest::newRow("negative-1") << raw("\x20") << int(CborValidateCanonicalFormat) << CborNoError;
1722     QTest::newRow("negative-25") << raw("\x38\x38") << int(CborValidateCanonicalFormat) << CborNoError;
1723     QTest::newRow("negative-257") << raw("\x39\1\0") << int(CborValidateCanonicalFormat) << CborNoError;
1724     QTest::newRow("negative-65537") << raw("\x3a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1725     QTest::newRow("negative-4294967297") << raw("\x3b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1726     QTest::newRow("overlong-negative-1*1") << raw("\x38\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1727     QTest::newRow("overlong-negative-1*2") << raw("\x39\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1728     QTest::newRow("overlong-negative-1*4") << raw("\x3a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1729     QTest::newRow("overlong-negative-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1730     QTest::newRow("overlong-negative-25*2") << raw("\x39\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1731     QTest::newRow("overlong-negative-25*4") << raw("\x3a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1732     QTest::newRow("overlong-negative-25*8") << raw("\x3b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1733     QTest::newRow("overlong-negative-257*4") << raw("\x3a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1734     QTest::newRow("overlong-negative-257*8") << raw("\x3b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1735     QTest::newRow("overlong-negative-65537*8") << raw("\x3b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1736     QTest::newRow("simple-0") << raw("\xe0") << int(CborValidateCanonicalFormat) << CborNoError;
1737     QTest::newRow("false") << raw("\xf4") << int(CborValidateCanonicalFormat) << CborNoError;
1738     QTest::newRow("true") << raw("\xf5") << int(CborValidateCanonicalFormat) << CborNoError;
1739     QTest::newRow("null") << raw("\xf6") << int(CborValidateCanonicalFormat) << CborNoError;
1740     QTest::newRow("undefined") << raw("\xf7") << int(CborValidateCanonicalFormat) << CborNoError;
1741     QTest::newRow("simple-32") << raw("\xf8\x20") << int(CborValidateCanonicalFormat) << CborNoError;
1742     QTest::newRow("fp-nan") << raw("\xf9\x7e\00") << int(CborValidateCanonicalFormat) << CborNoError;
1743     QTest::newRow("fp--inf") << raw("\xf9\xfc\00") << int(CborValidateCanonicalFormat) << CborNoError;
1744     QTest::newRow("fp-+inf") << raw("\xf9\x7c\00") << int(CborValidateCanonicalFormat) << CborNoError;
1745     QTest::newRow("overlong-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1746     QTest::newRow("overlong-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1747     QTest::newRow("overlong-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1748     QTest::newRow("overlong-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1749     QTest::newRow("overlong-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1750     QTest::newRow("overlong-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1751 
1752     // canonical - lengths
1753     QByteArray data24(24, 0x20);    // also decodes as -1
1754     QByteArray data256(256, 0x40);  // also decodes as h''
1755     QByteArray data65536(65536, 0x60);// also decodes as ""
1756     QTest::newRow("bytearray-0") << raw("\x40") << int(CborValidateCanonicalFormat) << CborNoError;
1757     QTest::newRow("bytearray-24") << (raw("\x58\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
1758     QTest::newRow("bytearray-256") << (raw("\x59\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
1759     QTest::newRow("bytearray-65536") << (raw("\x5a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
1760     QTest::newRow("_bytearray-0") << raw("\x5f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1761     QTest::newRow("overlong-bytearray-0*1") << raw("\x58\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1762     QTest::newRow("overlong-bytearray-0*2") << raw("\x59\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1763     QTest::newRow("overlong-bytearray-0*4") << raw("\x5a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1764     QTest::newRow("overlong-bytearray-0*8") << raw("\x5b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1765     QTest::newRow("overlong-bytearray-24*2") << (raw("\x59\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1766     QTest::newRow("overlong-bytearray-24*4") << (raw("\x5a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1767     QTest::newRow("overlong-bytearray-24*8") << (raw("\x5b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1768     QTest::newRow("overlong-bytearray-256*4") << (raw("\x5a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1769     QTest::newRow("overlong-bytearray-256*8") << (raw("\x5b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1770     QTest::newRow("overlong-bytearray-65536*8") << (raw("\x5b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1771     QTest::newRow("string-0") << raw("\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1772     QTest::newRow("string-24") << (raw("\x78\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
1773     QTest::newRow("string-256") << (raw("\x79\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
1774     QTest::newRow("string-65536") << (raw("\x7a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
1775     QTest::newRow("_string-0") << raw("\x7f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1776     QTest::newRow("overlong-string-0*1") << raw("\x78\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1777     QTest::newRow("overlong-string-0*2") << raw("\x79\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1778     QTest::newRow("overlong-string-0*4") << raw("\x7a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1779     QTest::newRow("overlong-string-0*8") << raw("\x7b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1780     QTest::newRow("overlong-string-24*2") << (raw("\x79\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1781     QTest::newRow("overlong-string-24*4") << (raw("\x7a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1782     QTest::newRow("overlong-string-24*8") << (raw("\x7b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1783     QTest::newRow("overlong-string-256*4") << (raw("\x7a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1784     QTest::newRow("overlong-string-256*8") << (raw("\x7b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1785     QTest::newRow("overlong-string-65536*8") << (raw("\x7b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1786     QTest::newRow("array-0") << raw("\x80") << int(CborValidateCanonicalFormat) << CborNoError;
1787     QTest::newRow("array-24") << (raw("\x98\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
1788     QTest::newRow("array-256") << (raw("\x99\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
1789     QTest::newRow("array-65536") << (raw("\x9a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
1790     QTest::newRow("_array-0") << raw("\x9f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1791     QTest::newRow("overlong-array-0*1") << raw("\x98\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1792     QTest::newRow("overlong-array-0*2") << raw("\x99\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1793     QTest::newRow("overlong-array-0*4") << raw("\x9a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1794     QTest::newRow("overlong-array-0*8") << raw("\x9b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1795     QTest::newRow("overlong-array-24*2") << (raw("\x99\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1796     QTest::newRow("overlong-array-24*4") << (raw("\x9a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1797     QTest::newRow("overlong-array-24*8") << (raw("\x9b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1798     QTest::newRow("overlong-array-256*4") << (raw("\x9a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1799     QTest::newRow("overlong-array-256*8") << (raw("\x9b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1800     QTest::newRow("overlong-array-65536*8") << (raw("\x9b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1801 
1802     // we need unique, sorted, string keys for map
1803     // we'll make all key-value pairs a total of 4 bytes
1804     char mapentry[] = { 0x62, 0, 0, 0x20 };
1805     QByteArray mapdata24(24 * sizeof(mapentry), Qt::Uninitialized);
1806     QByteArray mapdata256(256 * sizeof(mapentry), Qt::Uninitialized);
1807     char *mapdata24ptr = mapdata24.data();
1808     char *mapdata256ptr = mapdata256.data();
1809     for (int i = 0; i < 256; ++i) {
1810         mapentry[1] = 'A' + (i >> 4);
1811         mapentry[2] = 'a' + (i & 0xf);
1812         memcpy(mapdata256ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry));
1813         if (i < 24)
1814             memcpy(mapdata24ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry));
1815     }
1816     QTest::newRow("map-0") << raw("\xa0") << int(CborValidateCanonicalFormat) << CborNoError;
1817     QTest::newRow("map-24") << (raw("\xb8\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborNoError;
1818     QTest::newRow("map-256") << (raw("\xb9\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborNoError;
1819     QTest::newRow("_map-0") << raw("\xbf\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1820     QTest::newRow("overlong-map-0*1") << raw("\xb8\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1821     QTest::newRow("overlong-map-0*2") << raw("\xb9\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1822     QTest::newRow("overlong-map-0*4") << raw("\xba\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1823     QTest::newRow("overlong-map-0*8") << raw("\xbb\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1824     QTest::newRow("overlong-map-24*2") << (raw("\xb9\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1825     QTest::newRow("overlong-map-24*4") << (raw("\xba\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1826     QTest::newRow("overlong-map-24*8") << (raw("\xbb\0\0\0\0\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1827     QTest::newRow("overlong-map-256*4") << (raw("\xba\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1828     QTest::newRow("overlong-map-256*8") << (raw("\xbb\0\0\0\0\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1829     QTest::newRow("unsorted-length-map-UU") << raw("\xa2\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1830     QTest::newRow("unsorted-length-map-UUU") << raw("\xa3\1\1\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1831     QTest::newRow("unsorted-length-map-SS") << raw("\xa2\x61z\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1832     QTest::newRow("unsorted-length-map-SSS") << raw("\xa3\x61z\1\x61z\2\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1833     QTest::newRow("unsorted-length-map-SB") << raw("\xa2\x61z\1\x40\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1834     QTest::newRow("unsorted-length-map-AS") << raw("\xa2\x83\0\x20\x45Hello\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1835     QTest::newRow("unsorted-content-map-SS") << raw("\xa2\x61z\1\x61y\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1836     QTest::newRow("unsorted-content-map-AS") << raw("\xa2\x81\x21\1\x61\x21\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1837 
1838     QTest::newRow("tag-0") << raw("\xc0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1839     QTest::newRow("tag-24") << raw("\xd8\x18\x40") << int(CborValidateCanonicalFormat) << CborNoError;
1840     QTest::newRow("tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1841     QTest::newRow("tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1842     QTest::newRow("overlong-tag-0*1") << raw("\xd8\x00\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1843     QTest::newRow("overlong-tag-0*2") << raw("\xd9\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1844     QTest::newRow("overlong-tag-0*4") << raw("\xda\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1845     QTest::newRow("overlong-tag-0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1846     QTest::newRow("overlong-tag-24*2") << raw("\xd9\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1847     QTest::newRow("overlong-tag-24*4") << raw("\xda\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1848     QTest::newRow("overlong-tag-24*8") << raw("\xdb\0\0\0\0\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1849     QTest::newRow("overlong-tag-256*4") << raw("\xda\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1850     QTest::newRow("overlong-tag-256*8") << raw("\xdb\0\0\0\0\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1851     QTest::newRow("overlong-tag-65536*8") << raw("\xdb\0\0\0\0\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1852 
1853     // non-canonical: string length in chunked transfer
1854     QTest::newRow("overlong-_bytearray-0*1") << raw("\x5f\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1855     QTest::newRow("overlong-_bytearray-0*2") << raw("\x5f\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1856     QTest::newRow("overlong-_bytearray-0*4") << raw("\x5f\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1857     QTest::newRow("overlong-_bytearray-0*8") << raw("\x5f\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1858     QTest::newRow("overlong-_bytearray-24*2") << (raw("\x5f\x59\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1859     QTest::newRow("overlong-_bytearray-24*4") << (raw("\x5f\x5a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1860     QTest::newRow("overlong-_bytearray-24*8") << (raw("\x5f\x5b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1861     QTest::newRow("overlong-_bytearray-256*4") << (raw("\x5f\x5a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1862     QTest::newRow("overlong-_bytearray-256*8") << (raw("\x5f\x5b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1863     QTest::newRow("overlong-_bytearray-65536*8") << (raw("\x5f\x5b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1864     QTest::newRow("overlong-_bytearrayx2-0*1") << raw("\x5f\x40\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1865     QTest::newRow("overlong-_bytearrayx2-0*2") << raw("\x5f\x40\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1866     QTest::newRow("overlong-_bytearrayx2-0*4") << raw("\x5f\x40\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1867     QTest::newRow("overlong-_bytearrayx2-0*8") << raw("\x5f\x40\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1868     QTest::newRow("overlong-_string-0*1") << raw("\x7f\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1869     QTest::newRow("overlong-_string-0*2") << raw("\x7f\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1870     QTest::newRow("overlong-_string-0*4") << raw("\x7f\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1871     QTest::newRow("overlong-_string-0*8") << raw("\x7f\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1872     QTest::newRow("overlong-_string-24*2") << (raw("\x7f\x79\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1873     QTest::newRow("overlong-_string-24*4") << (raw("\x7f\x7a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1874     QTest::newRow("overlong-_string-24*8") << (raw("\x7f\x7b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1875     QTest::newRow("overlong-_string-256*4") << (raw("\x7f\x7a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1876     QTest::newRow("overlong-_string-256*8") << (raw("\x7f\x7b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1877     QTest::newRow("overlong-_string-65536*8") << (raw("\x7f\x7b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1878     QTest::newRow("overlong-_stringx2-0*1") << raw("\x7f\x60\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1879     QTest::newRow("overlong-_stringx2-0*2") << raw("\x7f\x60\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1880     QTest::newRow("overlong-_stringx2-0*4") << raw("\x7f\x60\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1881     QTest::newRow("overlong-_stringx2-0*8") << raw("\x7f\x60\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1882 
1883     // strict mode
1884     // UTF-8 sequences with invalid continuation bytes
1885     QTest::newRow("invalid-utf8-bad-continuation-1char") << raw("\x61\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1886     QTest::newRow("invalid-utf8-bad-continuation-2chars-1") << raw("\x62\xc2\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1887     QTest::newRow("invalid-utf8-bad-continuation-2chars-2") << raw("\x62\xc3\xdf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1888     QTest::newRow("invalid-utf8-bad-continuation-2chars-3") << raw("\x62\xc7\xf0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1889     QTest::newRow("invalid-utf8-bad-continuation-3chars-1") << raw("\x63\xe0\xa0\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1890     QTest::newRow("invalid-utf8-bad-continuation-3chars-2") << raw("\x63\xe0\xc0\xa0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1891     QTest::newRow("invalid-utf8-bad-continuation-4chars-1") << raw("\x64\xf0\x90\x80\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1892     QTest::newRow("invalid-utf8-bad-continuation-4chars-2") << raw("\x64\xf0\x90\xc0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1893     QTest::newRow("invalid-utf8-bad-continuation-4chars-3") << raw("\x64\xf0\xc0\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1894     // Too short UTF-8 sequences (in an array so there's a byte after that would make it valid UTF-8 if it were part of the string)
1895     QTest::newRow("invalid-utf8-too-short-2chars") << raw("\x82\x61\xc2\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1896     QTest::newRow("invalid-utf8-too-short-3chars-1") << raw("\x82\x61\xe0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1897     QTest::newRow("invalid-utf8-too-short-3chars-2") << raw("\x82\x62\xe0\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1898     QTest::newRow("invalid-utf8-too-short-4chars-1") << raw("\x82\x61\xf0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1899     QTest::newRow("invalid-utf8-too-short-4chars-2") << raw("\x82\x62\xf0\x90\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1900     QTest::newRow("invalid-utf8-too-short-4chars-3") << raw("\x82\x63\xf0\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1901     // UTF-16 surrogages encoded in UTF-8
1902     QTest::newRow("invalid-utf8-hi-surrogate") << raw("\x63\xed\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1903     QTest::newRow("invalid-utf8-lo-surrogate") << raw("\x63\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1904     QTest::newRow("invalid-utf8-surrogate-pair") << raw("\x66\xed\xa0\x80\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1905     // Non-Unicode UTF-8 sequences
1906     QTest::newRow("invalid-utf8-non-unicode-1") << raw("\x64\xf4\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1907     QTest::newRow("invalid-utf8-non-unicode-2") << raw("\x65\xf8\x88\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1908     QTest::newRow("invalid-utf8-non-unicode-3") << raw("\x66\xfc\x84\x80\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1909     QTest::newRow("invalid-utf8-non-unicode-4") << raw("\x66\xfd\xbf\xbf\xbf\xbf\xbf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1910     // invalid bytes in UTF-8
1911     QTest::newRow("invalid-utf8-fe") << raw("\x61\xfe") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1912     QTest::newRow("invalid-utf8-ff") << raw("\x61\xff") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1913     // Overlong sequences
1914     QTest::newRow("invalid-utf8-overlong-1-2") << raw("\x62\xc1\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1915     QTest::newRow("invalid-utf8-overlong-1-3") << raw("\x63\xe0\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1916     QTest::newRow("invalid-utf8-overlong-1-4") << raw("\x64\xf0\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1917     QTest::newRow("invalid-utf8-overlong-1-5") << raw("\x65\xf8\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1918     QTest::newRow("invalid-utf8-overlong-1-6") << raw("\x66\xfc\x80\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1919     QTest::newRow("invalid-utf8-overlong-2-3") << raw("\x63\xe0\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1920     QTest::newRow("invalid-utf8-overlong-2-4") << raw("\x64\xf0\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1921     QTest::newRow("invalid-utf8-overlong-2-5") << raw("\x65\xf8\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1922     QTest::newRow("invalid-utf8-overlong-2-6") << raw("\x66\xfc\x80\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1923     QTest::newRow("invalid-utf8-overlong-3-4") << raw("\x64\xf0\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1924     QTest::newRow("invalid-utf8-overlong-3-5") << raw("\x65\xf8\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1925     QTest::newRow("invalid-utf8-overlong-3-6") << raw("\x66\xfc\x80\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1926     QTest::newRow("invalid-utf8-overlong-4-5") << raw("\x65\xf8\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1927     QTest::newRow("invalid-utf8-overlong-4-6") << raw("\x66\xfc\x80\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1928 
1929     QTest::newRow("nonunique-content-map-UU") << raw("\xa2\0\1\0\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
1930     QTest::newRow("nonunique-content-map-SS") << raw("\xa2\x61z\1\x61z\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
1931     QTest::newRow("nonunique-content-map-AA") << raw("\xa2\x81\x65Hello\1\x81\x65Hello\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
1932 
1933     QTest::newRow("tag-0-unsigned") << raw("\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1934     QTest::newRow("tag-0-bytearray") << raw("\xc0\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1935     QTest::newRow("tag-0-string") << raw("\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
1936     QTest::newRow("tag-0-tag-0-string") << raw("\xc0\xc0\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1937     QTest::newRow("tag-1-unsigned") << raw("\xc1\x00") << int(CborValidateStrictMode) << CborNoError;
1938     QTest::newRow("tag-1-negative") << raw("\xc1\x20") << int(CborValidateStrictMode) << CborNoError;
1939     QTest::newRow("tag-1-bytearray") << raw("\xc1\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1940     QTest::newRow("tag-2-bytearray") << raw("\xc2\x40") << int(CborValidateStrictMode) << CborNoError;
1941     QTest::newRow("tag-2-string") << raw("\xc2\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1942     QTest::newRow("tag-3-bytearray") << raw("\xc3\x40") << int(CborValidateStrictMode) << CborNoError;
1943     QTest::newRow("tag-3-string") << raw("\xc3\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1944     QTest::newRow("tag-4-string") << raw("\xc4\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1945     QTest::newRow("tag-4-array") << raw("\xc4\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
1946     QTest::newRow("tag-5-string") << raw("\xc5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1947     QTest::newRow("tag-5-array") << raw("\xc5\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
1948     QTest::newRow("tag-21-bytearray") << raw("\xd5\x40") << int(CborValidateStrictMode) << CborNoError;
1949     QTest::newRow("tag-21-string") << raw("\xd5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1950     QTest::newRow("tag-21-array") << raw("\xd5\x80") << int(CborValidateStrictMode) << CborNoError;
1951     QTest::newRow("tag-21-map") << raw("\xd5\xa0") << int(CborValidateStrictMode) << CborNoError;
1952     QTest::newRow("tag-22-bytearray") << raw("\xd6\x40") << int(CborValidateStrictMode) << CborNoError;
1953     QTest::newRow("tag-22-string") << raw("\xd6\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1954     QTest::newRow("tag-22-array") << raw("\xd6\x80") << int(CborValidateStrictMode) << CborNoError;
1955     QTest::newRow("tag-22-map") << raw("\xd6\xa0") << int(CborValidateStrictMode) << CborNoError;
1956     QTest::newRow("tag-23-bytearray") << raw("\xd7\x40") << int(CborValidateStrictMode) << CborNoError;
1957     QTest::newRow("tag-23-string") << raw("\xd7\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1958     QTest::newRow("tag-23-array") << raw("\xd7\x80") << int(CborValidateStrictMode) << CborNoError;
1959     QTest::newRow("tag-23-map") << raw("\xd7\xa0") << int(CborValidateStrictMode) << CborNoError;
1960     QTest::newRow("tag-24-bytearray") << raw("\xd8\x18\x40") << int(CborValidateStrictMode) << CborNoError;
1961     QTest::newRow("tag-24-string") << raw("\xd8\x18\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1962     QTest::newRow("tag-32-bytearray") << raw("\xd8\x20\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1963     QTest::newRow("tag-32-string") << raw("\xd8\x20\x60") << int(CborValidateStrictMode) << CborNoError;
1964     QTest::newRow("tag-33-bytearray") << raw("\xd8\x21\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1965     QTest::newRow("tag-33-string") << raw("\xd8\x21\x60") << int(CborValidateStrictMode) << CborNoError;
1966     QTest::newRow("tag-34-bytearray") << raw("\xd8\x22\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1967     QTest::newRow("tag-34-string") << raw("\xd8\x22\x60") << int(CborValidateStrictMode) << CborNoError;
1968     QTest::newRow("tag-35-bytearray") << raw("\xd8\x23\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1969     QTest::newRow("tag-35-string") << raw("\xd8\x23\x60") << int(CborValidateStrictMode) << CborNoError;
1970     QTest::newRow("tag-36-bytearray") << raw("\xd8\x24\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1971     QTest::newRow("tag-36-string") << raw("\xd8\x24\x60") << int(CborValidateStrictMode) << CborNoError;
1972     QTest::newRow("tag-55799-unsigned") << raw("\xd9\xd9\xf7\x00") << int(CborValidateStrictMode) << CborNoError;
1973     QTest::newRow("tag-55799-negative") << raw("\xd9\xd9\xf7\x20") << int(CborValidateStrictMode) << CborNoError;
1974     QTest::newRow("tag-55799-bytearray") << raw("\xd9\xd9\xf7\x40") << int(CborValidateStrictMode) << CborNoError;
1975     QTest::newRow("tag-55799-string") << raw("\xd9\xd9\xf7\x60") << int(CborValidateStrictMode) << CborNoError;
1976     QTest::newRow("tag-55799-array") << raw("\xd9\xd9\xf7\x80") << int(CborValidateStrictMode) << CborNoError;
1977     QTest::newRow("tag-55799-map") << raw("\xd9\xd9\xf7\xa0") << int(CborValidateStrictMode) << CborNoError;
1978     QTest::newRow("tag-55799-tag-0-unsigned") << raw("\xd9\xd9\xf7\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1979     QTest::newRow("tag-55799-tag-0-string") << raw("\xd9\xd9\xf7\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
1980     QTest::newRow("tag-55799-simple0") << raw("\xd9\xd9\xf7\xe0") << int(CborValidateStrictMode) << CborNoError;
1981     QTest::newRow("tag-55799-false") << raw("\xd9\xd9\xf7\xf4") << int(CborValidateStrictMode) << CborNoError;
1982     QTest::newRow("tag-55799-true") << raw("\xd9\xd9\xf7\xf5") << int(CborValidateStrictMode) << CborNoError;
1983     QTest::newRow("tag-55799-null") << raw("\xd9\xd9\xf7\xf6") << int(CborValidateStrictMode) << CborNoError;
1984     QTest::newRow("tag-55799-undefined") << raw("\xd9\xd9\xf7\xf7") << int(CborValidateStrictMode) << CborNoError;
1985     QTest::newRow("tag-55799-simple32") << raw("\xd9\xd9\xf7\xf8\x20") << int(CborValidateStrictMode) << CborNoError;
1986     QTest::newRow("tag-55799-half") << raw("\xd9\xd9\xf7\xf9\0\0") << int(CborValidateStrictMode) << CborNoError;
1987     QTest::newRow("tag-55799-float") << raw("\xd9\xd9\xf7\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
1988     QTest::newRow("tag-55799-double") << raw("\xd9\xd9\xf7\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
1989 
1990     // excluded non-finite
1991     QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1992     QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1993     QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1994     QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1995     QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1996     QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1997 
1998     // excluded undefined
1999     QTest::newRow("no-undefined") << raw("\xf7") << int(CborValidateNoUndefined) << CborErrorExcludedType;
2000 
2001     // exclude non-finite
2002     QTest::newRow("excluded-fp-nan_f16") << raw("\xf9\x7e\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2003     QTest::newRow("excluded-fp--inf_f16") << raw("\xf9\xfc\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2004     QTest::newRow("excluded-fp-+inf_f16") << raw("\xf9\x7c\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2005     QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2006     QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2007     QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2008     QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2009     QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2010     QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
2011 
2012     // exclude non-string keys in maps
2013     QTest::newRow("excluded-map-unsigned") << raw("\xa1\x00\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2014     QTest::newRow("excluded-map-negative") << raw("\xa1\x20\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2015     QTest::newRow("excluded-map-bytearray") << raw("\xa1\x40\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2016     QTest::newRow("map-string") << raw("\xa1\x60\1") << int(CborValidateMapKeysAreString) << CborNoError;
2017     QTest::newRow("map-tag-0-string") << raw("\xa1\xc0\x60\1") << int(CborValidateMapKeysAreString) << CborNoError;
2018     QTest::newRow("excluded-map-array") << raw("\xa1\x80\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2019     QTest::newRow("excluded-map-map") << raw("\xa1\xa0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2020     QTest::newRow("excluded-map-simple-0") << raw("\xa1\xe0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2021     QTest::newRow("excluded-map-false") << raw("\xa1\xf4\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2022     QTest::newRow("excluded-map-true") << raw("\xa1\xf5\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2023     QTest::newRow("excluded-map-null") << raw("\xa1\xf6\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2024     QTest::newRow("excluded-map-undefined") << raw("\xa1\xf7\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2025     QTest::newRow("excluded-map-half") << raw("\xa1\xf9\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2026     QTest::newRow("excluded-map-float") << raw("\xa1\xfa\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2027     QTest::newRow("excluded-map-double") << raw("\xa1\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
2028 
2029     // unknown simple types
2030     QTest::newRow("unknown-simple-type-0") << raw("\xe0") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType;
2031     QTest::newRow("unknown-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType;
2032     QTest::newRow("allowed-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypesSA) << CborNoError;
2033 
2034     // unknown tags
2035     QTest::newRow("unknown-tag-6") << raw("\xc6\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
2036     QTest::newRow("unknown-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
2037     QTest::newRow("unknown-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
2038     QTest::newRow("unknown-tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
2039     QTest::newRow("unknown-tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
2040     QTest::newRow("allowed-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTagsSA) << CborNoError;
2041     QTest::newRow("allowed-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTagsSR) << CborNoError;
2042 
2043     // excluded tags
2044     QTest::newRow("excluded-tag-0") << raw("\xc0\x60") << int(CborValidateNoTags) << CborErrorExcludedType;
2045     QTest::newRow("excluded-tag-24") << raw("\xd8\x18\x40") << int(CborValidateNoTags) << CborErrorExcludedType;
2046     QTest::newRow("excluded-tag-55799") << raw("\xd9\xd9\xf7\x60") << int(CborValidateNoTags) << CborErrorExcludedType;
2047 
2048     // complete data
2049     QTest::newRow("garbage-data-0") << raw("\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2050     QTest::newRow("garbage-data-1") << raw("\x20\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2051     QTest::newRow("garbage-data-2") << raw("\x40\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2052     QTest::newRow("garbage-data-3") << raw("\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2053     QTest::newRow("garbage-data-4") << raw("\x80\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2054     QTest::newRow("garbage-data-5") << raw("\xa0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2055     QTest::newRow("garbage-data-6") << raw("\xc0\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2056     QTest::newRow("garbage-data-7") << raw("\xf4\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2057     QTest::newRow("garbage-data-f16") << raw("\xf9\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2058     QTest::newRow("garbage-data-f32") << raw("\xfa\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2059     QTest::newRow("garbage-data-f64") << raw("\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
2060 }
2061 
strictValidation()2062 void tst_Parser::strictValidation()
2063 {
2064     QFETCH(QByteArray, data);
2065     QFETCH(int, flags);
2066     QFETCH(CborError, expectedError);
2067 
2068     QString decoded;
2069     ParserWrapper w;
2070     CborError err = w.init(data);
2071     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
2072 
2073     err = cbor_value_validate(&w.first, flags);
2074     QCOMPARE(err, expectedError);
2075 }
2076 
resumeParsing_data()2077 void tst_Parser::resumeParsing_data()
2078 {
2079     addColumns();
2080     addFixedData();
2081     addStringsData();
2082     addTagsData();
2083     addMapMixedData();
2084 }
2085 
resumeParsing()2086 void tst_Parser::resumeParsing()
2087 {
2088     QFETCH(QByteArray, data);
2089     QFETCH(QString, expected);
2090 
2091     for (int len = 0; len < data.length() - 1; ++len) {
2092         ParserWrapper w;
2093         CborError err = w.init(data.constData(), len);
2094         if (!err) {
2095             QString decoded;
2096             err = parseOne(&w.first, &decoded);
2097         }
2098         if (err != CborErrorUnexpectedEOF)
2099             qDebug() << "Length is" << len;
2100         QCOMPARE(err, CborErrorUnexpectedEOF);
2101     }
2102 }
2103 
endPointer_data()2104 void tst_Parser::endPointer_data()
2105 {
2106     QTest::addColumn<QByteArray>("data");
2107     QTest::addColumn<int>("offset");
2108 
2109     QTest::newRow("number1") << raw("\x81\x01\x01") << 2;
2110     QTest::newRow("number24") << raw("\x81\x18\x18\x01") << 3;
2111     QTest::newRow("string") << raw("\x81\x61Z\x01") << 3;
2112     QTest::newRow("indefinite-string") << raw("\x81\x7f\x61Z\xff\x01") << 5;
2113     QTest::newRow("array") << raw("\x81\x02\x01") << 2;
2114     QTest::newRow("indefinite-array") << raw("\x81\x9f\x02\xff\x01") << 4;
2115     QTest::newRow("object") << raw("\x81\xa1\x03\x02\x01") << 4;
2116     QTest::newRow("indefinite-object") << raw("\x81\xbf\x03\x02\xff\x01") << 5;
2117 }
2118 
endPointer()2119 void tst_Parser::endPointer()
2120 {
2121     QFETCH(QByteArray, data);
2122     QFETCH(int, offset);
2123 
2124     QString decoded;
2125     ParserWrapper w;
2126     CborError err = w.init(data);
2127     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
2128 
2129     err = parseOne(&w.first, &decoded);
2130     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
2131     QCOMPARE(int(cbor_value_get_next_byte(&w.first) - w.begin()), offset);
2132 }
2133 
recursionLimit_data()2134 void tst_Parser::recursionLimit_data()
2135 {
2136     static const int recursions = CBOR_PARSER_MAX_RECURSIONS + 2;
2137     QTest::addColumn<QByteArray>("data");
2138 
2139     QTest::newRow("array") << QByteArray(recursions, '\x81') + '\x20';
2140     QTest::newRow("_array") << QByteArray(recursions, '\x9f') + '\x20' + QByteArray(recursions, '\xff');
2141 
2142     QByteArray data;
2143     for (int i = 0; i < recursions; ++i)
2144         data += "\xa1\x65Hello";
2145     data += '\2';
2146     QTest::newRow("map-recursive-values") << data;
2147 
2148     data.clear();
2149     for (int i = 0; i < recursions; ++i)
2150         data += "\xbf\x65World";
2151     data += '\2';
2152     for (int i = 0; i < recursions; ++i)
2153         data += "\xff";
2154     QTest::newRow("_map-recursive-values") << data;
2155 
2156     data = QByteArray(recursions, '\xa1');
2157     data += '\2';
2158     for (int i = 0; i < recursions; ++i)
2159         data += "\x7f\x64quux\xff";
2160     QTest::newRow("map-recursive-keys") << data;
2161 
2162     data = QByteArray(recursions, '\xbf');
2163     data += '\2';
2164     for (int i = 0; i < recursions; ++i)
2165         data += "\1\xff";
2166     QTest::newRow("_map-recursive-keys") << data;
2167 
2168     data.clear();
2169     for (int i = 0; i < recursions / 2; ++i)
2170         data += "\x81\xa1\1";
2171     data += '\2';
2172     QTest::newRow("mixed") << data;
2173 }
2174 
recursionLimit()2175 void tst_Parser::recursionLimit()
2176 {
2177     QFETCH(QByteArray, data);
2178 
2179     ParserWrapper w;
2180     CborError err = w.init(data);
2181     QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
2182 
2183     // check that it is valid:
2184     CborValue it = w.first;
2185     {
2186         QString dummy;
2187         err = parseOne(&it, &dummy);
2188         QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
2189     }
2190 
2191     it = w.first;
2192     err = cbor_value_advance(&it);
2193     QCOMPARE(err, CborErrorNestingTooDeep);
2194 
2195     it = w.first;
2196     if (cbor_value_is_map(&it)) {
2197         CborValue dummy;
2198         err = cbor_value_map_find_value(&it, "foo", &dummy);
2199         QCOMPARE(err, CborErrorNestingTooDeep);
2200     }
2201 }
2202 
2203 QTEST_MAIN(tst_Parser)
2204 #include "tst_parser.moc"
2205