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
42 namespace QTest {
toString(const CborError & err)43 template<> char *toString<CborError>(const CborError &err)
44 {
45 return qstrdup(cbor_error_string(err));
46 }
47 }
48
49 class tst_Parser : public QObject
50 {
51 Q_OBJECT
52 private slots:
53 void initParserEmpty();
54
55 // parsing API
56 void integers_data();
57 void integers();
58 void halfFloat_data();
59 void halfFloat();
60 void fixed_data();
61 void fixed();
62 void strings_data();
strings()63 void strings() { fixed(); }
64 void tags_data();
tags()65 void tags() { fixed(); }
tagTags_data()66 void tagTags_data() { tags_data(); }
67 void tagTags();
68 void emptyContainers_data();
69 void emptyContainers();
70 void arrays_data();
71 void arrays();
undefLengthArrays_data()72 void undefLengthArrays_data() { arrays_data(); }
73 void undefLengthArrays();
nestedArrays_data()74 void nestedArrays_data() { arrays_data(); }
75 void nestedArrays();
76 void maps_data();
77 void maps();
undefLengthMaps_data()78 void undefLengthMaps_data() { maps_data(); }
79 void undefLengthMaps();
nestedMaps_data()80 void nestedMaps_data() { maps_data(); }
81 void nestedMaps();
82 void mapMixed_data();
mapMixed()83 void mapMixed() { arrays(); }
mapsAndArrays_data()84 void mapsAndArrays_data() { arrays_data(); }
85 void mapsAndArrays();
86
readerApi_data()87 void readerApi_data() { arrays_data(); }
88 void readerApi();
89 void reparse_data();
90 void reparse();
91
92 // chunked string API
93 void chunkedString_data();
94 void chunkedString();
chunkedStringInUndefArray_data()95 void chunkedStringInUndefArray_data() { chunkedString_data(); }
96 void chunkedStringInUndefArray();
97
98 // convenience API
99 void stringLength_data();
100 void stringLength();
101 void stringCompare_data();
102 void stringCompare();
103 void mapFind_data();
104 void mapFind();
105
106 // validation & errors
107 void checkedIntegers_data();
108 void checkedIntegers();
109 void validation_data();
110 void validation();
111 void strictValidation_data();
112 void strictValidation();
113 void incompleteData_data();
114 void incompleteData();
115 void endPointer_data();
116 void endPointer();
117 void recursionLimit_data();
118 void recursionLimit();
119 };
120
121 struct ParserWrapper
122 {
123 void *realdata = nullptr;
124 uint8_t *data;
125 size_t len;
126 CborParser parser;
127 CborValue first;
128
~ParserWrapperParserWrapper129 ~ParserWrapper() { freeMemory(); }
130
initParserWrapper131 CborError init(const QByteArray &ba, uint32_t flags = 0)
132 {
133 return init(ba.constData(), ba.size(), flags);
134 }
initParserWrapper135 CborError init(const char *ptr, int n, uint32_t flags = 0)
136 {
137 freeMemory();
138 data = allocateMemory(n);
139 memcpy(data, ptr, len);
140 return cbor_parser_init(data, len, flags, &parser, &first);
141 }
beginParserWrapper142 uint8_t *begin() { return data; }
endParserWrapper143 uint8_t *end() { return data + len; }
144
145 uint8_t *allocateMemory(size_t);
146 void freeMemory();
147
148 static const size_t PageSize = 4096;
mmapAllocationParserWrapper149 static inline size_t mmapAllocation(size_t n)
150 {
151 // round up and add one page
152 return (n + 2*PageSize) & ~(PageSize - 1);
153 }
154 static bool shouldUseMmap();
155 };
156
shouldUseMmap()157 bool ParserWrapper::shouldUseMmap()
158 {
159 static int v = qEnvironmentVariableIntValue("PARSER_NO_MMAP");
160 return !v;
161 }
162
allocateMemory(size_t n)163 uint8_t *ParserWrapper::allocateMemory(size_t n)
164 {
165 len = n;
166 if (shouldUseMmap()) {
167 size_t alloc = mmapAllocation(n);
168 #if defined(Q_OS_UNIX)
169 realdata = mmap(nullptr, alloc, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
170 Q_ASSERT_X(realdata != MAP_FAILED, "allocateMemory", "mmap failed!");
171
172 // mark last page inaccessible
173 uint8_t *ptr = static_cast<uint8_t *>(realdata);
174 ptr += alloc - PageSize;
175 mprotect(ptr, PageSize, PROT_NONE);
176
177 ptr -= n;
178 return ptr;
179 #elif defined(Q_OS_WIN)
180 DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE;
181 DWORD flProtect = PAGE_READWRITE;
182 realdata = VirtualAlloc(nullptr, alloc, flAllocationType, flProtect);
183 Q_ASSERT_X(realdata, "allocateMemory", "VirtualAlloc failed!");
184
185 // mark last page inaccessible
186 uint8_t *ptr = static_cast<uint8_t *>(realdata);
187 ptr += alloc - PageSize;
188 VirtualProtect(ptr, PageSize, PAGE_NOACCESS, nullptr);
189
190 ptr -= n;
191 return ptr;
192 #endif
193 }
194 realdata = malloc(n);
195 return static_cast<uint8_t *>(realdata);
196 }
197
freeMemory()198 void ParserWrapper::freeMemory()
199 {
200 if (shouldUseMmap()) {
201 if (realdata) {
202 #if defined(Q_OS_UNIX)
203 size_t alloc = mmapAllocation(len);
204 munmap(realdata, alloc);
205 #elif defined(Q_OS_WIN)
206 VirtualFree(realdata, 0, MEM_RELEASE);
207 #endif
208 }
209 return;
210 }
211
212 free(realdata);
213 }
214
qstring_printf(void * out,const char * fmt,...)215 static CborError qstring_printf(void *out, const char *fmt, ...)
216 {
217 auto str = static_cast<QString *>(out);
218 va_list va;
219 va_start(va, fmt);
220 *str += QString::vasprintf(fmt, va);
221 va_end(va);
222 return CborNoError;
223 };
224
parseOne(CborValue * it,QString * parsed)225 CborError parseOne(CborValue *it, QString *parsed)
226 {
227 int flags = CborPrettyShowStringFragments | CborPrettyIndicateIndeterminateLength |
228 CborPrettyIndicateOverlongNumbers;
229
230 parsed->clear();
231 return cbor_value_to_pretty_stream(qstring_printf, parsed, it, flags);
232 }
233
parseOneChunk(CborValue * it,QString * parsed)234 CborError parseOneChunk(CborValue *it, QString *parsed)
235 {
236 CborError err;
237 CborType ourType = cbor_value_get_type(it);
238 if (ourType == CborByteStringType) {
239 const uint8_t *bytes;
240 size_t len;
241 err = cbor_value_get_byte_string_chunk(it, &bytes, &len, it);
242 if (err)
243 return err;
244
245 if (bytes)
246 *parsed = QString::fromLatin1("h'" +
247 QByteArray::fromRawData(reinterpret_cast<const char *>(bytes), len).toHex() +
248 '\'');
249 } else if (ourType == CborTextStringType) {
250 const char *text;
251 size_t len;
252 err = cbor_value_get_text_string_chunk(it, &text, &len, it);
253 if (err)
254 return err;
255
256 if (text)
257 *parsed = '"' + QString::fromUtf8(text, len) + '"';
258 } else {
259 Q_ASSERT(false);
260 }
261 return err;
262 }
263
initParserEmpty()264 void tst_Parser::initParserEmpty()
265 {
266 CborParser parser;
267 CborValue first;
268 CborError err = cbor_parser_init((const quint8 *)"", 0, 0, &parser, &first);
269 QCOMPARE(err, CborErrorUnexpectedEOF);
270 }
271
272 bool compareFailed = true;
compareOne_real(const QByteArray & data,const QString & expected,int line,int n=-1)273 void compareOne_real(const QByteArray &data, const QString &expected, int line, int n = -1)
274 {
275 compareFailed = true;
276 ParserWrapper w;
277 CborError err = w.init(data);
278 QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
279
280 if (cbor_value_get_type(&w.first) == CborArrayType) {
281 size_t len;
282 if (n >= 0) {
283 QVERIFY(cbor_value_is_length_known(&w.first));
284 QCOMPARE(cbor_value_get_array_length(&w.first, &len), CborNoError);
285 QCOMPARE(len, size_t(len));
286 } else {
287 QVERIFY(!cbor_value_is_length_known(&w.first));
288 QCOMPARE(cbor_value_get_array_length(&w.first, &len), CborErrorUnknownLength);
289 }
290 } else if (cbor_value_get_type(&w.first) == CborMapType) {
291 size_t len;
292 if (n >= 0) {
293 QVERIFY(cbor_value_is_length_known(&w.first));
294 QCOMPARE(cbor_value_get_map_length(&w.first, &len), CborNoError);
295 QCOMPARE(len, size_t(len));
296 } else {
297 QVERIFY(!cbor_value_is_length_known(&w.first));
298 QCOMPARE(cbor_value_get_map_length(&w.first, &len), CborErrorUnknownLength);
299 }
300 } else if (cbor_value_is_text_string(&w.first) || cbor_value_is_byte_string(&w.first)) {
301 size_t len;
302 QCOMPARE(cbor_value_calculate_string_length(&w.first, &len), CborNoError);
303 if (cbor_value_is_length_known(&w.first)) {
304 size_t len2;
305 QCOMPARE(cbor_value_get_string_length(&w.first, &len2), CborNoError);
306 QCOMPARE(len2, len);
307 } else {
308 QCOMPARE(cbor_value_get_string_length(&w.first, &len), CborErrorUnknownLength);
309 }
310 }
311
312 CborError err2 = cbor_value_validate_basic(&w.first);
313
314 QString decoded;
315 err = parseOne(&w.first, &decoded);
316 QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) +
317 "\"; decoded stream:\n" + decoded.toLatin1());
318 QCOMPARE(decoded, expected);
319
320 // check that the errors are the same
321 QCOMPARE(err2, err);
322
323 // check that we consumed everything
324 QCOMPARE((void*)cbor_value_get_next_byte(&w.first), (void*)w.end());
325
326 compareFailed = false;
327 }
328 #define compareOne(data, expected) compareOne_real(data, expected, __LINE__)
329 #define compareOneSize(n, data, expected) compareOne_real(data, expected, __LINE__, n)
330
331 #include "data.cpp"
332
integers_data()333 void tst_Parser::integers_data()
334 {
335 addIntegers();
336 }
337
integers()338 void tst_Parser::integers()
339 {
340 QFETCH(QByteArray, data);
341 QFETCH(bool, isNegative);
342 QFETCH(quint64, expectedRaw);
343 QFETCH(qint64, expectedValue);
344 QFETCH(bool, inInt64Range);
345
346 ParserWrapper w;
347 CborError err = w.init(data);
348 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
349 QVERIFY(cbor_value_is_integer(&w.first));
350
351 uint64_t raw;
352 cbor_value_get_raw_integer(&w.first, &raw);
353 QCOMPARE(quint64(raw), expectedRaw);
354
355 if (isNegative) {
356 QVERIFY(cbor_value_is_negative_integer(&w.first));
357 QVERIFY(!cbor_value_is_unsigned_integer(&w.first));
358 } else {
359 QVERIFY(!cbor_value_is_negative_integer(&w.first));
360 QVERIFY(cbor_value_is_unsigned_integer(&w.first));
361 }
362
363 int64_t value;
364 if (inInt64Range) {
365 cbor_value_get_int64(&w.first, &value);
366 QCOMPARE(qint64(value), expectedValue);
367 }
368
369 err = cbor_value_get_int64_checked(&w.first, &value);
370 QCOMPARE(err, inInt64Range ? CborNoError : CborErrorDataTooLarge);
371
372 int ivalue;
373 bool inIntRange = inInt64Range && (expectedValue == int(expectedValue));
374 err = cbor_value_get_int_checked(&w.first, &ivalue);
375 QCOMPARE(err, inIntRange ? CborNoError : CborErrorDataTooLarge);
376 }
377
addHalfFloat()378 static void addHalfFloat()
379 {
380 QTest::addColumn<QByteArray>("data");
381 QTest::addColumn<unsigned>("expectedRaw");
382 QTest::addColumn<double>("expectedValue");
383
384 QTest::newRow("+0") << raw("\x00\x00") << 0U << 0.0;
385 QTest::newRow("-0") << raw("\x80\x00") << 0x8000U << 0.0;
386
387 QTest::newRow("min.denorm") << raw("\x00\x01") << 1U << ldexp(1.0, -14) * ldexp(1.0, -10);
388 QTest::newRow("-min.denorm") << raw("\x80\x01") << 0x8001U << ldexp(-1.0, -14) * ldexp(1.0, -10);
389
390 QTest::newRow("max.denorm") << raw("\x03\xff") << 0x03ffU << ldexp(1.0, -14) * (1.0 - ldexp(1.0, -10));
391 QTest::newRow("-max.denorm") << raw("\x83\xff") << 0x83ffU << ldexp(-1.0, -14) * (1.0 - ldexp(1.0, -10));
392
393 QTest::newRow("min.norm") << raw("\x04\x00") << 0x0400U << ldexp(1.0, -14);
394 QTest::newRow("-min.norm") << raw("\x84\x00") << 0x8400U << ldexp(-1.0, -14);
395
396 QTest::newRow("1.0") << raw("\x3c\x00") << 0x3c00U << 1.0;
397 QTest::newRow("-1.0") << raw("\xbc\x00") << 0xbc00U << -1.0;
398
399 QTest::newRow("1.5") << raw("\x3e\x00") << 0x3e00U << 1.5;
400 QTest::newRow("-1.5") << raw("\xbe\x00") << 0xbe00U << -1.5;
401
402 QTest::newRow("max") << raw("\x7b\xff") << 0x7bffU << ldexp(1.0, 15) * (2.0 - ldexp(1.0, -10));
403 QTest::newRow("-max") << raw("\xfb\xff") << 0xfbffU << ldexp(-1.0, 15) * (2.0 - ldexp(1.0, -10));
404
405 QTest::newRow("inf") << raw("\x7c\x00") << 0x7c00U << double(INFINITY);
406 QTest::newRow("-inf") << raw("\xfc\x00") << 0xfc00U << double(-INFINITY);
407
408 QTest::newRow("nan") << raw("\x7c\x01") << 0x7c01U << double(NAN);
409 QTest::newRow("nan2") << raw("\xfc\x01") << 0xfc01U << double(NAN);
410 QTest::newRow("nan3") << raw("\x7e\x00") << 0x7e00U << double(NAN);
411 QTest::newRow("nan4") << raw("\xfe\x00") << 0xfe00U << double(NAN);
412 }
413
halfFloat_data()414 void tst_Parser::halfFloat_data()
415 {
416 addHalfFloat();
417 }
418
halfFloat()419 void tst_Parser::halfFloat()
420 {
421 QFETCH(QByteArray, data);
422 QFETCH(unsigned, expectedRaw);
423 QFETCH(double, expectedValue);
424
425 CborParser parser;
426 CborValue first;
427
428 data.prepend('\xf9');
429
430 CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
431 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
432 QVERIFY(cbor_value_is_half_float(&first));
433
434 uint16_t raw;
435 cbor_value_get_half_float(&first, &raw);
436 QCOMPARE(raw, uint16_t(expectedRaw));
437
438 float value;
439 cbor_value_get_half_float_as_float(&first, &value);
440
441 const double epsilon = ldexp(1.0, -25);
442
443 if (qIsNaN(expectedValue)) {
444 QVERIFY(qIsNaN(value));
445 } else if (qIsInf(expectedValue)) {
446 QVERIFY(value == (float)expectedValue);
447 } else {
448 QVERIFY(qAbs(value - (float)expectedValue) < epsilon);
449 }
450 }
451
fixed_data()452 void tst_Parser::fixed_data()
453 {
454 addColumns();
455 addFixedData();
456 }
457
fixed()458 void tst_Parser::fixed()
459 {
460 QFETCH(QByteArray, data);
461 QFETCH(QString, expected);
462
463 compareOne(data, expected);
464 }
465
strings_data()466 void tst_Parser::strings_data()
467 {
468 addColumns();
469 addStringsData();
470 }
471
tags_data()472 void tst_Parser::tags_data()
473 {
474 addColumns();
475 addTagsData();
476 }
477
tagTags()478 void tst_Parser::tagTags()
479 {
480 QFETCH(QByteArray, data);
481 QFETCH(QString, expected);
482
483 compareOne("\xd9\xd9\xf7" + data, "55799(" + expected + ')');
484 if (!compareFailed)
485 compareOne("\xd9\xd9\xf7" "\xd9\xd9\xf7" + data, "55799(55799(" + expected + "))");
486 }
487
emptyContainers_data()488 void tst_Parser::emptyContainers_data()
489 {
490 addColumns();
491 addEmptyContainersData();
492 }
493
emptyContainers()494 void tst_Parser::emptyContainers()
495 {
496 QFETCH(QByteArray, data);
497 QFETCH(QString, expected);
498 QFETCH(int, n);
499
500 compareOneSize(n, data, expected);
501 }
502
arrays_data()503 void tst_Parser::arrays_data()
504 {
505 addColumns();
506 addFixedData();
507 addStringsData();
508 addTagsData();
509 }
510
arrays()511 void tst_Parser::arrays()
512 {
513 QFETCH(QByteArray, data);
514 QFETCH(QString, expected);
515
516 compareOneSize(1, "\x81" + data, '[' + expected + ']');
517 if (compareFailed) return;
518
519 compareOneSize(2, "\x82" + data + data, '[' + expected + ", " + expected + ']');
520 if (compareFailed) return;
521
522 // overlong length
523 compareOneSize(1, "\x98\1" + data, "[_0 " + expected + ']');
524 if (compareFailed) return;
525 compareOneSize(1, raw("\x99\0\1") + data, "[_1 " + expected + ']');
526 if (compareFailed) return;
527 compareOneSize(1, raw("\x9a\0\0\0\1") + data, "[_2 " + expected + ']');
528 if (compareFailed) return;
529 compareOneSize(1, raw("\x9b\0\0\0\0\0\0\0\1") + data, "[_3 " + expected + ']');
530 if (compareFailed) return;
531
532 // medium-sized array: 32 elements (1 << 5)
533 expected += ", ";
534 for (int i = 0; i < 5; ++i) {
535 data += data;
536 expected += expected;
537 }
538 expected.chop(2); // remove the last ", "
539 compareOneSize(32, "\x98\x20" + data, '[' + expected + ']');
540 if (compareFailed) return;
541
542 // large array: 256 elements (32 << 3)
543 expected += ", ";
544 for (int i = 0; i < 3; ++i) {
545 data += data;
546 expected += expected;
547 }
548 expected.chop(2); // remove the last ", "
549 compareOneSize(256, raw("\x99\1\0") + data, '[' + expected + ']');
550 if (compareFailed) return;
551 }
552
undefLengthArrays()553 void tst_Parser::undefLengthArrays()
554 {
555 QFETCH(QByteArray, data);
556 QFETCH(QString, expected);
557
558 compareOne("\x9f" + data + "\xff", "[_ " + expected + ']');
559 if (compareFailed) return;
560
561 compareOne("\x9f" + data + data + "\xff", "[_ " + expected + ", " + expected + ']');
562 }
563
nestedArrays()564 void tst_Parser::nestedArrays()
565 {
566 QFETCH(QByteArray, data);
567 QFETCH(QString, expected);
568
569 compareOneSize(1, "\x81\x81" + data, "[[" + expected + "]]");
570 if (compareFailed) return;
571
572 compareOneSize(1, "\x81\x81\x81" + data, "[[[" + expected + "]]]");
573 if (compareFailed) return;
574
575 compareOneSize(1, "\x81\x82" + data + data, "[[" + expected + ", " + expected + "]]");
576 if (compareFailed) return;
577
578 compareOneSize(2, "\x82\x81" + data + data, "[[" + expected + "], " + expected + "]");
579 if (compareFailed) return;
580
581 compareOneSize(2, "\x82\x81" + data + '\x81' + data, "[[" + expected + "], [" + expected + "]]");
582 if (compareFailed) return;
583
584 // undefined length
585 compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\xff", "[_ [_ " + expected + ", " + expected + "]]");
586 if (compareFailed) return;
587
588 compareOneSize(-1, "\x9f\x9f" + data + "\xff\x9f" + data + "\xff\xff", "[_ [_ " + expected + "], [_ " + expected + "]]");
589 if (compareFailed) return;
590
591 compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\x9f" + data + "\xff\xff",
592 "[_ [_ " + expected + ", " + expected + "], [_ " + expected + "]]");
593 if (compareFailed) return;
594
595 // mix them
596 compareOneSize(1, "\x81\x9f" + data + "\xff", "[[_ " + expected + "]]");
597 if (compareFailed) return;
598
599 compareOneSize(-1, "\x9f\x81" + data + "\xff", "[_ [" + expected + "]]");
600 }
601
maps_data()602 void tst_Parser::maps_data()
603 {
604 arrays_data();
605 }
606
maps()607 void tst_Parser::maps()
608 {
609 QFETCH(QByteArray, data);
610 QFETCH(QString, expected);
611
612 // integer key
613 compareOneSize(1, "\xa1\1" + data, "{1: " + expected + '}');
614 if (compareFailed) return;
615
616 // string key
617 compareOneSize(1, "\xa1\x65" "Hello" + data, "{\"Hello\": " + expected + '}');
618 if (compareFailed) return;
619
620 // map to self
621 compareOneSize(1, "\xa1" + data + data, '{' + expected + ": " + expected + '}');
622 if (compareFailed) return;
623
624 // two integer keys
625 compareOneSize(2, "\xa2\1" + data + "\2" + data, "{1: " + expected + ", 2: " + expected + '}');
626 if (compareFailed) return;
627
628 // OneSize integer and OneSize string key
629 compareOneSize(2, "\xa2\1" + data + "\x65" "Hello" + data, "{1: " + expected + ", \"Hello\": " + expected + '}');
630 if (compareFailed) return;
631 }
632
undefLengthMaps()633 void tst_Parser::undefLengthMaps()
634 {
635 QFETCH(QByteArray, data);
636 QFETCH(QString, expected);
637
638 // integer key
639 compareOne("\xbf\1" + data + '\xff', "{_ 1: " + expected + '}');
640 if (compareFailed) return;
641
642 compareOne("\xbf\1" + data + '\2' + data + '\xff', "{_ 1: " + expected + ", 2: " + expected + '}');
643 if (compareFailed) return;
644
645 compareOne("\xbf\1" + data + "\x65Hello" + data + '\xff', "{_ 1: " + expected + ", \"Hello\": " + expected + '}');
646 if (compareFailed) return;
647
648 compareOne("\xbf\x65Hello" + data + '\1' + data + '\xff', "{_ \"Hello\": " + expected + ", 1: " + expected + '}');
649 }
650
nestedMaps()651 void tst_Parser::nestedMaps()
652 {
653 QFETCH(QByteArray, data);
654 QFETCH(QString, expected);
655
656 // nested maps as values
657 compareOneSize(1, "\xa1\1\xa1\2" + data, "{1: {2: " + expected + "}}");
658 if (compareFailed) return;
659
660 compareOneSize(1, "\xa1\x65Hello\xa1\2" + data, "{\"Hello\": {2: " + expected + "}}");
661 if (compareFailed) return;
662
663 compareOneSize(1, "\xa1\1\xa2\2" + data + '\x20' + data, "{1: {2: " + expected + ", -1: " + expected + "}}");
664 if (compareFailed) return;
665
666 compareOneSize(2, "\xa2\1\xa1\2" + data + "\2\xa1\x20" + data, "{1: {2: " + expected + "}, 2: {-1: " + expected + "}}");
667 if (compareFailed) return;
668
669 // nested maps as keys
670 compareOneSize(1, "\xa1\xa1\xf4" + data + "\xf5", "{{false: " + expected + "}: true}");
671 if (compareFailed) return;
672
673 compareOneSize(1, "\xa1\xa1" + data + data + "\xa1" + data + data,
674 "{{" + expected + ": " + expected + "}: {" + expected + ": " + expected + "}}");
675 if (compareFailed) return;
676
677 // undefined length
678 compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\xff", "{_ 1: {_ 2: " + expected + "}}");
679 if (compareFailed) return;
680
681 compareOneSize(-1, "\xbf\1\xbf\2" + data + '\x20' + data + "\xff\xff", "{_ 1: {_ 2: " + expected + ", -1: " + expected + "}}");
682 if (compareFailed) return;
683
684 compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\2\xbf\x20" + data + "\xff\xff",
685 "{_ 1: {_ 2: " + expected + "}, 2: {_ -1: " + expected + "}}");
686 if (compareFailed) return;
687
688 compareOneSize(-1, "\xbf\xbf" + data + data + "\xff\xbf" + data + data + "\xff\xff",
689 "{_ {_ " + expected + ": " + expected + "}: {_ " + expected + ": " + expected + "}}");
690 if (compareFailed) return;
691
692 // mix them
693 compareOneSize(1, "\xa1\1\xbf\2" + data + "\xff", "{1: {_ 2: " + expected + "}}");
694 if (compareFailed) return;
695
696 compareOneSize(-1, "\xbf\1\xa1\2" + data + "\xff", "{_ 1: {2: " + expected + "}}");
697 if (compareFailed) return;
698 }
699
mapMixed_data()700 void tst_Parser::mapMixed_data()
701 {
702 addColumns();
703 addMapMixedData();
704 }
705
mapsAndArrays()706 void tst_Parser::mapsAndArrays()
707 {
708 QFETCH(QByteArray, data);
709 QFETCH(QString, expected);
710
711 // arrays of maps
712 compareOneSize(1, "\x81\xa1\1" + data, "[{1: " + expected + "}]");
713 if (compareFailed) return;
714
715 compareOneSize(2, "\x82\xa1\1" + data + "\xa1\2" + data, "[{1: " + expected + "}, {2: " + expected + "}]");
716 if (compareFailed) return;
717
718 compareOneSize(1, "\x81\xa2\1" + data + "\2" + data, "[{1: " + expected + ", 2: " + expected + "}]");
719 if (compareFailed) return;
720
721 compareOneSize(-1, "\x9f\xa1\1" + data + "\xff", "[_ {1: " + expected + "}]");
722 if (compareFailed) return;
723
724 compareOneSize(1, "\x81\xbf\1" + data + "\xff", "[{_ 1: " + expected + "}]");
725 if (compareFailed) return;
726
727 compareOneSize(-1, "\x9f\xbf\1" + data + "\xff\xff", "[_ {_ 1: " + expected + "}]");
728 if (compareFailed) return;
729
730 // maps of arrays
731 compareOneSize(1, "\xa1\1\x81" + data, "{1: [" + expected + "]}");
732 if (compareFailed) return;
733
734 compareOneSize(1, "\xa1\1\x82" + data + data, "{1: [" + expected + ", " + expected + "]}");
735 if (compareFailed) return;
736
737 compareOneSize(2, "\xa2\1\x81" + data + "\x65Hello\x81" + data, "{1: [" + expected + "], \"Hello\": [" + expected + "]}");
738 if (compareFailed) return;
739
740 compareOneSize(1, "\xa1\1\x9f" + data + "\xff", "{1: [_ " + expected + "]}");
741 if (compareFailed) return;
742
743 compareOneSize(1, "\xa1\1\x9f" + data + data + "\xff", "{1: [_ " + expected + ", " + expected + "]}");
744 if (compareFailed) return;
745
746 compareOneSize(-1, "\xbf\1\x81" + data + "\xff", "{_ 1: [" + expected + "]}");
747 if (compareFailed) return;
748
749 compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\xff", "{_ 1: [_ " + expected + "]}");
750 if (compareFailed) return;
751
752 compareOneSize(-1, "\xbf\1\x9f" + data + data + "\xff\xff", "{_ 1: [_ " + expected + ", " + expected + "]}");
753 if (compareFailed) return;
754
755 // mixed with indeterminate length strings
756 compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\x65Hello\xbf" + data + "\x7f\xff\xff\xff",
757 "{_ 1: [_ " + expected + "], \"Hello\": {_ " + expected + ": (_ )}}");
758 }
759
760 struct Input {
761 QByteArray data;
762 int consumed;
763 };
764
765 static const CborParserOperations byteArrayOps = {
__anon0518a6960102() 766 /* can_read_bytes = */ [](void *token, size_t len) {
767 auto input = static_cast<Input *>(token);
768 return input->data.size() - input->consumed >= int(len);
769 },
__anon0518a6960202() 770 /* read_bytes = */ [](void *token, void *dst, size_t offset, size_t len) {
771 auto input = static_cast<Input *>(token);
772 return memcpy(dst, input->data.constData() + input->consumed + offset, len);
773 },
__anon0518a6960302() 774 /* advance_bytes = */ [](void *token, size_t len) {
775 auto input = static_cast<Input *>(token);
776 input->consumed += int(len);
777 },
__anon0518a6960402() 778 /* transfer_string = */ [](void *token, const void **userptr, size_t offset, size_t len) {
779 // ###
780 auto input = static_cast<Input *>(token);
781 if (input->data.size() - input->consumed < int(len + offset))
782 return CborErrorUnexpectedEOF;
783 input->consumed += int(offset);
784 *userptr = input->data.constData() + input->consumed;
785 input->consumed += int(len);
786 return CborNoError;
787 }
788 };
789
readerApi()790 void tst_Parser::readerApi()
791 {
792 QFETCH(QByteArray, data);
793 QFETCH(QString, expected);
794
795 Input input = { data, 0 };
796
797 CborParser parser;
798 CborValue first;
799 CborError err = cbor_parser_init_reader(&byteArrayOps, &parser, &first, &input);
800 QCOMPARE(err, CborNoError);
801
802 QString decoded;
803 err = parseOne(&first, &decoded);
804 QCOMPARE(err, CborNoError);
805 QCOMPARE(decoded, expected);
806
807 // check we consumed everything
808 QCOMPARE(input.consumed, data.size());
809 }
810
reparse_data()811 void tst_Parser::reparse_data()
812 {
813 // only one-item rows
814 addColumns();
815 addFixedData();
816 }
817
reparse()818 void tst_Parser::reparse()
819 {
820 QFETCH(QByteArray, data);
821 QFETCH(QString, expected);
822
823 Input input = { QByteArray(), 0 };
824 CborParser parser;
825 CborValue first;
826 CborError err = cbor_parser_init_reader(&byteArrayOps, &parser, &first, &input);
827 QCOMPARE(err, CborErrorUnexpectedEOF);
828
829 for (int i = 0; i < data.size(); ++i) {
830 input.data = data.left(i);
831 err = cbor_value_reparse(&first);
832 if (err != CborErrorUnexpectedEOF)
833 qDebug() << "At" << i;
834 QCOMPARE(err, CborErrorUnexpectedEOF);
835 QCOMPARE(input.consumed, 0);
836 }
837
838 // now it should work
839 input.data = data;
840 err = cbor_value_reparse(&first);
841 QCOMPARE(err, CborNoError);
842
843 QString decoded;
844 err = parseOne(&first, &decoded);
845 QCOMPARE(err, CborNoError);
846 QCOMPARE(decoded, expected);
847
848 // check we consumed everything
849 QCOMPARE(input.consumed, data.size());
850 }
851
chunkedString_data()852 void tst_Parser::chunkedString_data()
853 {
854 addChunkedStringData();
855 }
856
chunkedStringTest(const QByteArray & data,const QString & concatenated,QStringList & chunks,CborType ourType)857 static void chunkedStringTest(const QByteArray &data, const QString &concatenated,
858 QStringList &chunks, CborType ourType)
859 {
860 ParserWrapper w;
861 CborError err = w.init(data);
862 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
863
864 CborValue value;
865 QVERIFY(cbor_value_is_array(&w.first));
866 err = cbor_value_enter_container(&w.first, &value);
867 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
868 QVERIFY(cbor_value_is_byte_string(&value) || cbor_value_is_text_string(&value));
869
870 CborValue copy = value;
871
872 err = cbor_value_begin_string_iteration(&value);
873 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
874 forever {
875 QString decoded;
876 err = parseOneChunk(&value, &decoded);
877 if (err == CborErrorNoMoreStringChunks)
878 break; // last chunk
879
880 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
881
882 QVERIFY2(!chunks.isEmpty(), "Too many chunks");
883 QString expected = chunks.takeFirst();
884 QCOMPARE(decoded, expected);
885 }
886
887 err = cbor_value_finish_string_iteration(&value);
888 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
889 QVERIFY2(chunks.isEmpty(), "Too few chunks");
890
891 // compare to the concatenated data
892 {
893 size_t n;
894 err = cbor_value_calculate_string_length(©, &n);
895 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
896
897 QByteArray buffer(n, Qt::Uninitialized);
898 QString formatted;
899 if (cbor_value_is_byte_string(©)) {
900 err = cbor_value_copy_byte_string(©, (uint8_t *)buffer.data(), &n, nullptr);
901 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
902 QCOMPARE(int(n), buffer.size());
903
904 formatted = QString::fromLatin1("h'" + buffer.toHex() + '\'');
905 } else {
906 err = cbor_value_copy_text_string(©, buffer.data(), &n, nullptr);
907 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
908 QCOMPARE(int(n), buffer.size());
909
910 formatted = '"' + QString::fromUtf8(buffer.data(), n) + '"';
911 }
912 QCOMPARE(formatted, concatenated);
913 }
914
915 // confirm that the extra string we appended is still here
916 QVERIFY(!cbor_value_at_end(&value));
917 QCOMPARE(cbor_value_get_type(&value), ourType);
918 size_t len;
919 err = cbor_value_get_string_length(&value, &len);
920 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
921 QCOMPARE(len, size_t(0));
922
923 err = cbor_value_advance(&value);
924 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
925
926 // confirm EOF
927 QVERIFY(cbor_value_at_end(&value));
928
929 err = cbor_value_leave_container(&w.first, &value);
930 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
931 QCOMPARE((void*)cbor_value_get_next_byte(&w.first), (void*)w.end());
932 }
933
chunkedString()934 void tst_Parser::chunkedString()
935 {
936 QFETCH(QByteArray, data);
937 QFETCH(QString, concatenated);
938 QFETCH(QStringList, chunks);
939
940 // Make this an array of two entries, with the second an empty byte or text string
941 CborType ourType = CborType(data.at(0) & 0xe0);
942 data.prepend(char(0x82));
943 data.append(ourType);
944
945 chunkedStringTest(data, concatenated, chunks, ourType);
946 }
947
chunkedStringInUndefArray()948 void tst_Parser::chunkedStringInUndefArray()
949 {
950 QFETCH(QByteArray, data);
951 QFETCH(QString, concatenated);
952 QFETCH(QStringList, chunks);
953
954 // Make this an array of undefined length entries, with the second entry an empty byte or text string
955 CborType ourType = CborType(data.at(0) & 0xe0);
956 data.prepend(char(0x9f));
957 data.append(ourType);
958 data.append(char(0xff));
959
960 chunkedStringTest(data, concatenated, chunks, ourType);
961 }
962
stringLength_data()963 void tst_Parser::stringLength_data()
964 {
965 QTest::addColumn<QByteArray>("data");
966 QTest::addColumn<int>("expected");
967
968 QTest::newRow("emptybytestring") << raw("\x40") << 0;
969 QTest::newRow("bytestring1") << raw("\x41 ") << 1;
970 QTest::newRow("bytestring1-nul") << raw("\x41\0") << 1;
971 QTest::newRow("bytestring5") << raw("\x45Hello") << 5;
972 QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") << 24;
973 QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3') << 256;
974
975 // text strings
976 QTest::newRow("emptytextstring") << raw("\x60") << 0;
977 QTest::newRow("textstring1") << raw("\x61 ") << 1;
978 QTest::newRow("textstring1-nul") << raw("\x61\0") << 1;
979 QTest::newRow("textstring5") << raw("\x65Hello") << 5;
980 QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") << 24;
981 QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') << 256;
982
983 // strings with overlong length
984 QTest::newRow("emptybytestring*1") << raw("\x58\x00") << 0;
985 QTest::newRow("emptytextstring*1") << raw("\x78\x00") << 0;
986 QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << 0;
987 QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << 0;
988 QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << 0;
989 QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << 0;
990 QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << 0;
991 QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << 0;
992 QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << 5;
993 QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << 5;
994 QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << 5;
995 QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << 5;
996 QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << 5;
997 QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << 5;
998 QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << 5;
999 QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << 5;
1000
1001 // strings with undefined length
1002 QTest::newRow("_emptybytestring") << raw("\x5f\xff") << 0;
1003 QTest::newRow("_emptytextstring") << raw("\x7f\xff") << 0;
1004 QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << 0;
1005 QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << 0;
1006 QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << 0;
1007 QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << 0;
1008 QTest::newRow("_bytestring5*2") << raw("\x5f\x43Hel\x42lo\xff") << 5;
1009 QTest::newRow("_textstring5*2") << raw("\x7f\x63Hel\x62lo\xff") << 5;
1010 QTest::newRow("_bytestring5*5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << 5;
1011 QTest::newRow("_textstring5*5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << 5;
1012 QTest::newRow("_bytestring5*6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << 5;
1013 QTest::newRow("_textstring5*6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << 5;
1014 }
1015
stringLength()1016 void tst_Parser::stringLength()
1017 {
1018 QFETCH(QByteArray, data);
1019 QFETCH(int, expected);
1020
1021 ParserWrapper w;
1022 CborError err = w.init(data);
1023 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1024
1025 size_t result;
1026 err = cbor_value_calculate_string_length(&w.first, &result);
1027 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1028 QCOMPARE(result, size_t(expected));
1029
1030 if (cbor_value_is_length_known(&w.first)) {
1031 QCOMPARE(cbor_value_get_string_length(&w.first, &result), CborNoError);
1032 QCOMPARE(result, size_t(expected));
1033 }
1034
1035 }
1036
stringCompare_data()1037 void tst_Parser::stringCompare_data()
1038 {
1039 QTest::addColumn<QByteArray>("data");
1040 QTest::addColumn<QString>("string");
1041 QTest::addColumn<bool>("expected");
1042
1043 // compare empty to empty
1044 QTest::newRow("empty-empty") << raw("\x60") << QString() << true;
1045 QTest::newRow("_empty-empty") << raw("\x7f\xff") << QString() << true;
1046 QTest::newRow("_empty*1-empty") << raw("\x7f\x60\xff") << QString() << true;
1047 QTest::newRow("_empty*2-empty") << raw("\x7f\x60\x60\xff") << QString() << true;
1048
1049 // compare empty to non-empty
1050 QTest::newRow("empty-nonempty") << raw("\x60") << "Hello" << false;
1051 QTest::newRow("_empty-nonempty") << raw("\x7f\xff") << "Hello" << false;
1052 QTest::newRow("_empty*1-nonempty") << raw("\x7f\x60\xff") << "Hello" << false;
1053 QTest::newRow("_empty*2-nonempty") << raw("\x7f\x60\x60\xff") << "Hello" << false;
1054
1055 // compare same strings
1056 QTest::newRow("same-short-short") << raw("\x65Hello") << "Hello" << true;
1057 QTest::newRow("same-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello" << true;
1058 QTest::newRow("same-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello" << true;
1059 QTest::newRow("same-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello" << true;
1060 QTest::newRow("same-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello" << true;
1061 QTest::newRow("same-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
1062 << "Good morning, good afternoon and goodnight" << true;
1063 QTest::newRow("same-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
1064 << "Good morning, good afternoon and goodnight" << true;
1065 QTest::newRow("same-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
1066 << "Good morning, good afternoon and goodnight" << true;
1067
1068 // compare different strings (same length)
1069 QTest::newRow("diff-same-length-short-short") << raw("\x65Hello") << "World" << false;
1070 QTest::newRow("diff-same-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "World" << false;
1071 QTest::newRow("diff-same-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "World" << false;
1072 QTest::newRow("diff-same-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "World" << false;
1073 QTest::newRow("diff-same-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "World" << false;
1074 QTest::newRow("diff-same-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
1075 << "Good morning, good afternoon and goodnight, world" << false;
1076 QTest::newRow("diff-same-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
1077 << "Good morning, good afternoon and goodnight, world" << false;
1078 QTest::newRow("diff-same-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
1079 << "Good morning, good afternoon and goodnight, world" << false;
1080
1081 // compare different strings (different length)
1082 QTest::newRow("diff-diff-length-short-short") << raw("\x65Hello") << "Hello World" << false;
1083 QTest::newRow("diff-diff-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello World" << false;
1084 QTest::newRow("diff-diff-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello World" << false;
1085 QTest::newRow("diff-diff-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello World" << false;
1086 QTest::newRow("diff-diff-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello World" << false;
1087 QTest::newRow("diff-diff-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
1088 << "Good morning, good afternoon and goodnight World" << false;
1089 QTest::newRow("diff-diff-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
1090 << "Good morning, good afternoon and goodnight World" << false;
1091 QTest::newRow("diff-diff-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
1092 << "Good morning, good afternoon and goodnight World" << false;
1093
1094 // compare against non-strings
1095 QTest::newRow("unsigned") << raw("\0") << "0" << false;
1096 QTest::newRow("negative") << raw("\x20") << "-1" << false;
1097 QTest::newRow("emptybytestring") << raw("\x40") << "" << false;
1098 QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "" << false;
1099 QTest::newRow("shortbytestring") << raw("\x45Hello") << "Hello" << false;
1100 QTest::newRow("longbytestring") << raw("\x58\x2aGood morning, good afternoon and goodnight")
1101 << "Good morning, good afternoon and goodnight" << false;
1102 QTest::newRow("emptyarray") << raw("\x80") << "" << false;
1103 QTest::newRow("emptymap") << raw("\xa0") << "" << false;
1104 QTest::newRow("array") << raw("\x81\x65Hello") << "Hello" << false;
1105 QTest::newRow("map") << raw("\xa1\x65Hello\x65World") << "Hello World" << false;
1106 QTest::newRow("false") << raw("\xf4") << "false" << false;
1107 QTest::newRow("true") << raw("\xf5") << "true" << false;
1108 QTest::newRow("null") << raw("\xf6") << "null" << false;
1109 }
1110
compareOneString(const QByteArray & data,const QString & string,bool expected,int line)1111 void compareOneString(const QByteArray &data, const QString &string, bool expected, int line)
1112 {
1113 compareFailed = true;
1114
1115 ParserWrapper w;
1116 CborError err = w.init(data);
1117 QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
1118
1119 bool result;
1120 QByteArray bastring = string.toUtf8();
1121 err = cbor_value_text_string_equals(&w.first, bastring.constData(), &result);
1122 QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
1123 QCOMPARE(result, expected);
1124
1125 if (expected) {
1126 size_t len;
1127 cbor_value_skip_tag(&w.first);
1128 if (cbor_value_is_length_known(&w.first)) {
1129 QCOMPARE(cbor_value_get_string_length(&w.first, &len), CborNoError);
1130 QCOMPARE(int(len), bastring.size());
1131 }
1132 QCOMPARE(cbor_value_calculate_string_length(&w.first, &len), CborNoError);
1133 QCOMPARE(int(len), bastring.size());
1134 }
1135
1136 compareFailed = false;
1137 }
1138 #define compareOneString(data, string, expected) compareOneString(data, string, expected, __LINE__)
1139
stringCompare()1140 void tst_Parser::stringCompare()
1141 {
1142 QFETCH(QByteArray, data);
1143 QFETCH(QString, string);
1144 QFETCH(bool, expected);
1145
1146 compareOneString(data, string, expected);
1147 if (compareFailed) return;
1148
1149 // tag it
1150 compareOneString("\xc1" + data, string, expected);
1151 if (compareFailed) return;
1152
1153 compareOneString("\xc1\xc2" + data, string, expected);
1154 }
1155
mapFind_data()1156 void tst_Parser::mapFind_data()
1157 {
1158 // Rules:
1159 // we are searching for string "needle"
1160 // if present, the value should be the string "haystack" (with tag 42)
1161
1162 QTest::addColumn<QByteArray>("data");
1163 QTest::addColumn<bool>("expected");
1164
1165 QTest::newRow("emptymap") << raw("\xa0") << false;
1166 QTest::newRow("_emptymap") << raw("\xbf\xff") << false;
1167
1168 // maps not containing our items
1169 QTest::newRow("absent-unsigned-unsigned") << raw("\xa1\0\0") << false;
1170 QTest::newRow("absent-taggedunsigned-unsigned") << raw("\xa1\xc0\0\0") << false;
1171 QTest::newRow("absent-unsigned-taggedunsigned") << raw("\xa1\0\xc0\0") << false;
1172 QTest::newRow("absent-taggedunsigned-taggedunsigned") << raw("\xa1\xc0\0\xc0\0") << false;
1173 QTest::newRow("absent-string-unsigned") << raw("\xa1\x68haystack\0") << false;
1174 QTest::newRow("absent-taggedstring-unsigned") << raw("\xa1\xc0\x68haystack\0") << false;
1175 QTest::newRow("absent-string-taggedunsigned") << raw("\xa1\x68haystack\xc0\0") << false;
1176 QTest::newRow("absent-taggedstring-taggedunsigned") << raw("\xa1\xc0\x68haystack\xc0\0") << false;
1177 QTest::newRow("absent-string-string") << raw("\xa1\x68haystack\x66needle") << false;
1178 QTest::newRow("absent-string-taggedstring") << raw("\xa1\x68haystack\xc0\x66needle") << false;
1179 QTest::newRow("absent-taggedstring-string") << raw("\xa1\xc0\x68haystack\x66needle") << false;
1180 QTest::newRow("absent-string-taggedstring") << raw("\xa1\xc0\x68haystack\xc0\x66needle") << false;
1181
1182 QTest::newRow("absent-string-emptyarray") << raw("\xa1\x68haystack\x80") << false;
1183 QTest::newRow("absent-string-_emptyarray") << raw("\xa1\x68haystack\x9f\xff") << false;
1184 QTest::newRow("absent-string-array1") << raw("\xa1\x68haystack\x81\0") << false;
1185 QTest::newRow("absent-string-array2") << raw("\xa1\x68haystack\x85\0\1\2\3\4") << false;
1186 QTest::newRow("absent-string-array3") << raw("\xa1\x68haystack\x85\x63one\x63two\x65three\x64""four\x64""five") << false;
1187
1188 QTest::newRow("absent-string-emptymap") << raw("\xa1\x68haystack\xa0") << false;
1189 QTest::newRow("absent-string-_emptymap") << raw("\xa1\x68haystack\xbf\xff") << false;
1190 QTest::newRow("absent-string-map") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle") << false;
1191 QTest::newRow("absent-string-map2") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle\61z\62yx") << false;
1192
1193 // maps containing our items
1194 QTest::newRow("alone") << raw("\xa1\x66needle\xd8\x2a\x68haystack") << true;
1195 QTest::newRow("tagged") << raw("\xa1\xc1\x66needle\xd8\x2a\x68haystack") << true;
1196 QTest::newRow("doubletagged") << raw("\xa1\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true;
1197 QTest::newRow("chunked") << raw("\xa1\x7f\x66needle\xff\xd8\x2a\x68haystack") << true;
1198 QTest::newRow("chunked*2") << raw("\xa1\x7f\x60\x66needle\xff\xd8\x2a\x68haystack") << true;
1199 QTest::newRow("chunked*2bis") << raw("\xa1\x7f\x66needle\x60\xff\xd8\x2a\x68haystack") << true;
1200 QTest::newRow("chunked*3") << raw("\xa1\x7f\x62ne\x62""ed\x62le\xff\xd8\x2a\x68haystack") << true;
1201 QTest::newRow("chunked*8") << raw("\xa1\x7f\x61n\x61""e\x60\x61""e\x61""d\x60\x62le\x60\xff\xd8\x2a\x68haystack") << true;
1202
1203 QTest::newRow("1before") << raw("\xa2\x68haystack\x66needle\x66needle\xd8\x2a\x68haystack") << true;
1204 QTest::newRow("tagged-1before") << raw("\xa2\xc1\x68haystack\x66needle\xc1\x66needle\xd8\x2a\x68haystack") << true;
1205 QTest::newRow("doubletagged-1before2") << raw("\xa2\xc1\xc2\x68haystack\x66needle\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true;
1206
1207 QTest::newRow("arraybefore") << raw("\xa2\x61z\x80\x66needle\xd8\x2a\x68haystack") << true;
1208 QTest::newRow("nestedarraybefore") << raw("\xa2\x61z\x81\x81\0\x66needle\xd8\x2a\x68haystack") << true;
1209 QTest::newRow("arrayarraybefore") << raw("\xa2\x82\1\2\x80\x66needle\xd8\x2a\x68haystack") << true;
1210
1211 QTest::newRow("mapbefore") << raw("\xa2\x61z\xa0\x66needle\xd8\x2a\x68haystack") << true;
1212 QTest::newRow("nestedmapbefore") << raw("\xa2\x61z\xa1\0\x81\0\x66needle\xd8\x2a\x68haystack") << true;
1213 QTest::newRow("mapmapbefore") << raw("\xa2\xa1\1\2\xa0\x66needle\xd8\x2a\x68haystack") << true;
1214 }
1215
mapFind()1216 void tst_Parser::mapFind()
1217 {
1218 QFETCH(QByteArray, data);
1219 QFETCH(bool, expected);
1220
1221 ParserWrapper w;
1222 CborError err = w.init(data);
1223 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1224
1225 CborValue element;
1226 err = cbor_value_map_find_value(&w.first, "needle", &element);
1227 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1228
1229 if (expected) {
1230 QCOMPARE(int(element.type), int(CborTagType));
1231
1232 CborTag tag;
1233 err = cbor_value_get_tag(&element, &tag);
1234 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1235 QCOMPARE(int(tag), 42);
1236
1237 bool equals;
1238 err = cbor_value_text_string_equals(&element, "haystack", &equals);
1239 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1240 QVERIFY(equals);
1241 } else {
1242 QCOMPARE(int(element.type), int(CborInvalidType));
1243 }
1244 }
1245
checkedIntegers_data()1246 void tst_Parser::checkedIntegers_data()
1247 {
1248 QTest::addColumn<QByteArray>("data");
1249 QTest::addColumn<QVariant>("result"); // QVariant so we can note numbers out of int64_t range
1250
1251 QTest::newRow("0") << raw("\x00") << QVariant(Q_INT64_C(0));
1252 QTest::newRow("1") << raw("\x01") << QVariant(Q_INT64_C(1));
1253 QTest::newRow("10") << raw("\x0a") << QVariant(Q_INT64_C(10));
1254 QTest::newRow("23") << raw("\x17") << QVariant(Q_INT64_C(23));
1255 QTest::newRow("24") << raw("\x18\x18") << QVariant(Q_INT64_C(24));
1256 QTest::newRow("UINT8_MAX") << raw("\x18\xff") << QVariant(Q_INT64_C(255));
1257 QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << QVariant(Q_INT64_C(256));
1258 QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << QVariant(Q_INT64_C(65535));
1259 QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << QVariant(Q_INT64_C(65536));
1260 QTest::newRow("INT32_MAX") << raw("\x1a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(2147483647));
1261 QTest::newRow("INT32_MAX+1") << raw("\x1a\x80\x00\x00\x00") << QVariant(Q_INT64_C(2147483648));
1262 QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295));
1263 QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296));
1264 QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
1265 << QVariant(); // out of range
1266
1267 // negative integers
1268 QTest::newRow("-1") << raw("\x20") << QVariant(Q_INT64_C(-1));
1269 QTest::newRow("-2") << raw("\x21") << QVariant(Q_INT64_C(-2));
1270 QTest::newRow("-24") << raw("\x37") << QVariant(Q_INT64_C(-24));
1271 QTest::newRow("-25") << raw("\x38\x18") << QVariant(Q_INT64_C(-25));
1272 QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(Q_INT64_C(-256));
1273 QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(Q_INT64_C(-257));
1274 QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(Q_INT64_C(-65536));
1275 QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(Q_INT64_C(-65537));
1276 QTest::newRow("INT32_MIN") << raw("\x3a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(-2147483648));
1277 QTest::newRow("INT32_MIN-1") << raw("\x3a\x80\x00\x00\x00") << QVariant(Q_INT64_C(-2147483649));
1278 QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296));
1279 QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297));
1280 QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
1281 << QVariant(std::numeric_limits<qint64>::min() + 1);
1282 QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
1283 << QVariant(std::numeric_limits<qint64>::min());
1284 QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << QVariant(); // out of range
1285 QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
1286 << QVariant(); // out of range
1287 QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
1288 << QVariant(); // out of range
1289 }
1290
checkedIntegers()1291 void tst_Parser::checkedIntegers()
1292 {
1293 QFETCH(QByteArray, data);
1294 QFETCH(QVariant, result);
1295 int64_t expected = result.toLongLong();
1296
1297 ParserWrapper w;
1298 CborError err = w.init(data);
1299 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1300
1301 int64_t v;
1302 err = cbor_value_get_int64_checked(&w.first, &v);
1303 if (result.isNull()) {
1304 QCOMPARE(err, CborErrorDataTooLarge);
1305 } else {
1306 QCOMPARE(v, expected);
1307 }
1308
1309 int v2;
1310 err = cbor_value_get_int_checked(&w.first, &v2);
1311 if (result.isNull() || expected < std::numeric_limits<int>::min() || expected > std::numeric_limits<int>::max()) {
1312 QCOMPARE(err, CborErrorDataTooLarge);
1313 } else {
1314 QCOMPARE(int64_t(v2), expected);
1315 }
1316 }
1317
validation_data()1318 void tst_Parser::validation_data()
1319 {
1320 addValidationColumns();
1321 addValidationData();
1322 }
1323
validation()1324 void tst_Parser::validation()
1325 {
1326 QFETCH(QByteArray, data);
1327 QFETCH(int, flags);
1328 QFETCH(CborError, expectedError);
1329
1330 QString decoded;
1331 ParserWrapper w;
1332 CborError err = w.init(data, uint32_t(flags));
1333 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1334
1335 CborError err2 = cbor_value_validate_basic(&w.first);
1336 CborError err3 = cbor_value_validate(&w.first, CborValidateBasic);
1337 err = parseOne(&w.first, &decoded);
1338 QCOMPARE(err, expectedError);
1339 if (!QByteArray(QTest::currentDataTag()).contains("utf8")) {
1340 QCOMPARE(err2, expectedError);
1341 QCOMPARE(err3, expectedError);
1342 }
1343 }
1344
strictValidation_data()1345 void tst_Parser::strictValidation_data()
1346 {
1347 addValidationColumns();
1348
1349 // Canonical validation - fixed types
1350 QTest::newRow("unsigned-0") << raw("\x00") << int(CborValidateCanonicalFormat) << CborNoError;
1351 QTest::newRow("unsigned-24") << raw("\x18\x18") << int(CborValidateCanonicalFormat) << CborNoError;
1352 QTest::newRow("unsigned-256") << raw("\x19\1\0") << int(CborValidateCanonicalFormat) << CborNoError;
1353 QTest::newRow("unsigned-65536") << raw("\x1a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1354 QTest::newRow("unsigned-4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1355 QTest::newRow("overlong-unsigned-0*1") << raw("\x18\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1356 QTest::newRow("overlong-unsigned-0*2") << raw("\x19\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1357 QTest::newRow("overlong-unsigned-0*4") << raw("\x1a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1358 QTest::newRow("overlong-unsigned-0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1359 QTest::newRow("overlong-unsigned-24*2") << raw("\x19\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1360 QTest::newRow("overlong-unsigned-24*4") << raw("\x1a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1361 QTest::newRow("overlong-unsigned-24*8") << raw("\x1b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1362 QTest::newRow("overlong-unsigned-256*4") << raw("\x1a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1363 QTest::newRow("overlong-unsigned-256*8") << raw("\x1b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1364 QTest::newRow("overlong-unsigned-65536*8") << raw("\x1b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1365 QTest::newRow("negative-1") << raw("\x20") << int(CborValidateCanonicalFormat) << CborNoError;
1366 QTest::newRow("negative-25") << raw("\x38\x38") << int(CborValidateCanonicalFormat) << CborNoError;
1367 QTest::newRow("negative-257") << raw("\x39\1\0") << int(CborValidateCanonicalFormat) << CborNoError;
1368 QTest::newRow("negative-65537") << raw("\x3a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1369 QTest::newRow("negative-4294967297") << raw("\x3b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
1370 QTest::newRow("overlong-negative-1*1") << raw("\x38\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1371 QTest::newRow("overlong-negative-1*2") << raw("\x39\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1372 QTest::newRow("overlong-negative-1*4") << raw("\x3a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1373 QTest::newRow("overlong-negative-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1374 QTest::newRow("overlong-negative-25*2") << raw("\x39\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1375 QTest::newRow("overlong-negative-25*4") << raw("\x3a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1376 QTest::newRow("overlong-negative-25*8") << raw("\x3b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1377 QTest::newRow("overlong-negative-257*4") << raw("\x3a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1378 QTest::newRow("overlong-negative-257*8") << raw("\x3b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1379 QTest::newRow("overlong-negative-65537*8") << raw("\x3b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1380 QTest::newRow("simple-0") << raw("\xe0") << int(CborValidateCanonicalFormat) << CborNoError;
1381 QTest::newRow("false") << raw("\xf4") << int(CborValidateCanonicalFormat) << CborNoError;
1382 QTest::newRow("true") << raw("\xf5") << int(CborValidateCanonicalFormat) << CborNoError;
1383 QTest::newRow("null") << raw("\xf6") << int(CborValidateCanonicalFormat) << CborNoError;
1384 QTest::newRow("undefined") << raw("\xf7") << int(CborValidateCanonicalFormat) << CborNoError;
1385 QTest::newRow("simple-32") << raw("\xf8\x20") << int(CborValidateCanonicalFormat) << CborNoError;
1386 QTest::newRow("fp-nan") << raw("\xf9\x7e\00") << int(CborValidateCanonicalFormat) << CborNoError;
1387 QTest::newRow("fp--inf") << raw("\xf9\xfc\00") << int(CborValidateCanonicalFormat) << CborNoError;
1388 QTest::newRow("fp-+inf") << raw("\xf9\x7c\00") << int(CborValidateCanonicalFormat) << CborNoError;
1389 QTest::newRow("overlong-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1390 QTest::newRow("overlong-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1391 QTest::newRow("overlong-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1392 QTest::newRow("overlong-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1393 QTest::newRow("overlong-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1394 QTest::newRow("overlong-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1395
1396 // canonical - lengths
1397 QByteArray data24(24, 0x20); // also decodes as -1
1398 QByteArray data256(256, 0x40); // also decodes as h''
1399 QByteArray data65536(65536, 0x60);// also decodes as ""
1400 QTest::newRow("bytearray-0") << raw("\x40") << int(CborValidateCanonicalFormat) << CborNoError;
1401 QTest::newRow("bytearray-24") << (raw("\x58\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
1402 QTest::newRow("bytearray-256") << (raw("\x59\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
1403 QTest::newRow("bytearray-65536") << (raw("\x5a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
1404 QTest::newRow("_bytearray-0") << raw("\x5f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1405 QTest::newRow("overlong-bytearray-0*1") << raw("\x58\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1406 QTest::newRow("overlong-bytearray-0*2") << raw("\x59\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1407 QTest::newRow("overlong-bytearray-0*4") << raw("\x5a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1408 QTest::newRow("overlong-bytearray-0*8") << raw("\x5b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1409 QTest::newRow("overlong-bytearray-24*2") << (raw("\x59\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1410 QTest::newRow("overlong-bytearray-24*4") << (raw("\x5a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1411 QTest::newRow("overlong-bytearray-24*8") << (raw("\x5b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1412 QTest::newRow("overlong-bytearray-256*4") << (raw("\x5a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1413 QTest::newRow("overlong-bytearray-256*8") << (raw("\x5b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1414 QTest::newRow("overlong-bytearray-65536*8") << (raw("\x5b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1415 QTest::newRow("string-0") << raw("\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1416 QTest::newRow("string-24") << (raw("\x78\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
1417 QTest::newRow("string-256") << (raw("\x79\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
1418 QTest::newRow("string-65536") << (raw("\x7a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
1419 QTest::newRow("_string-0") << raw("\x7f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1420 QTest::newRow("overlong-string-0*1") << raw("\x78\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1421 QTest::newRow("overlong-string-0*2") << raw("\x79\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1422 QTest::newRow("overlong-string-0*4") << raw("\x7a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1423 QTest::newRow("overlong-string-0*8") << raw("\x7b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1424 QTest::newRow("overlong-string-24*2") << (raw("\x79\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1425 QTest::newRow("overlong-string-24*4") << (raw("\x7a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1426 QTest::newRow("overlong-string-24*8") << (raw("\x7b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1427 QTest::newRow("overlong-string-256*4") << (raw("\x7a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1428 QTest::newRow("overlong-string-256*8") << (raw("\x7b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1429 QTest::newRow("overlong-string-65536*8") << (raw("\x7b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1430 QTest::newRow("array-0") << raw("\x80") << int(CborValidateCanonicalFormat) << CborNoError;
1431 QTest::newRow("array-24") << (raw("\x98\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
1432 QTest::newRow("array-256") << (raw("\x99\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
1433 QTest::newRow("array-65536") << (raw("\x9a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
1434 QTest::newRow("_array-0") << raw("\x9f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1435 QTest::newRow("overlong-array-0*1") << raw("\x98\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1436 QTest::newRow("overlong-array-0*2") << raw("\x99\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1437 QTest::newRow("overlong-array-0*4") << raw("\x9a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1438 QTest::newRow("overlong-array-0*8") << raw("\x9b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1439 QTest::newRow("overlong-array-24*2") << (raw("\x99\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1440 QTest::newRow("overlong-array-24*4") << (raw("\x9a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1441 QTest::newRow("overlong-array-24*8") << (raw("\x9b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1442 QTest::newRow("overlong-array-256*4") << (raw("\x9a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1443 QTest::newRow("overlong-array-256*8") << (raw("\x9b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1444 QTest::newRow("overlong-array-65536*8") << (raw("\x9b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1445
1446 // we need unique, sorted, string keys for map
1447 // we'll make all key-value pairs a total of 4 bytes
1448 char mapentry[] = { 0x62, 0, 0, 0x20 };
1449 QByteArray mapdata24(24 * sizeof(mapentry), Qt::Uninitialized);
1450 QByteArray mapdata256(256 * sizeof(mapentry), Qt::Uninitialized);
1451 char *mapdata24ptr = mapdata24.data();
1452 char *mapdata256ptr = mapdata256.data();
1453 for (int i = 0; i < 256; ++i) {
1454 mapentry[1] = 'A' + (i >> 4);
1455 mapentry[2] = 'a' + (i & 0xf);
1456 memcpy(mapdata256ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry));
1457 if (i < 24)
1458 memcpy(mapdata24ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry));
1459 }
1460 QTest::newRow("map-0") << raw("\xa0") << int(CborValidateCanonicalFormat) << CborNoError;
1461 QTest::newRow("map-24") << (raw("\xb8\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborNoError;
1462 QTest::newRow("map-256") << (raw("\xb9\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborNoError;
1463 QTest::newRow("_map-0") << raw("\xbf\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
1464 QTest::newRow("overlong-map-0*1") << raw("\xb8\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1465 QTest::newRow("overlong-map-0*2") << raw("\xb9\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1466 QTest::newRow("overlong-map-0*4") << raw("\xba\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1467 QTest::newRow("overlong-map-0*8") << raw("\xbb\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1468 QTest::newRow("overlong-map-24*2") << (raw("\xb9\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1469 QTest::newRow("overlong-map-24*4") << (raw("\xba\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1470 QTest::newRow("overlong-map-24*8") << (raw("\xbb\0\0\0\0\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1471 QTest::newRow("overlong-map-256*4") << (raw("\xba\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1472 QTest::newRow("overlong-map-256*8") << (raw("\xbb\0\0\0\0\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1473 QTest::newRow("unsorted-length-map-UU") << raw("\xa2\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1474 QTest::newRow("unsorted-length-map-UUU") << raw("\xa3\1\1\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1475 QTest::newRow("unsorted-length-map-SS") << raw("\xa2\x61z\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1476 QTest::newRow("unsorted-length-map-SSS") << raw("\xa3\x61z\1\x61z\2\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1477 QTest::newRow("unsorted-length-map-SB") << raw("\xa2\x61z\1\x40\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1478 QTest::newRow("unsorted-length-map-AS") << raw("\xa2\x83\0\x20\x45Hello\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1479 QTest::newRow("unsorted-content-map-SS") << raw("\xa2\x61z\1\x61y\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1480 QTest::newRow("unsorted-content-map-AS") << raw("\xa2\x81\x21\1\x61\x21\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
1481
1482 QTest::newRow("tag-0") << raw("\xc0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1483 QTest::newRow("tag-24") << raw("\xd8\x18\x40") << int(CborValidateCanonicalFormat) << CborNoError;
1484 QTest::newRow("tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1485 QTest::newRow("tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
1486 QTest::newRow("overlong-tag-0*1") << raw("\xd8\x00\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1487 QTest::newRow("overlong-tag-0*2") << raw("\xd9\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1488 QTest::newRow("overlong-tag-0*4") << raw("\xda\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1489 QTest::newRow("overlong-tag-0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1490 QTest::newRow("overlong-tag-24*2") << raw("\xd9\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1491 QTest::newRow("overlong-tag-24*4") << raw("\xda\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1492 QTest::newRow("overlong-tag-24*8") << raw("\xdb\0\0\0\0\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1493 QTest::newRow("overlong-tag-256*4") << raw("\xda\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1494 QTest::newRow("overlong-tag-256*8") << raw("\xdb\0\0\0\0\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1495 QTest::newRow("overlong-tag-65536*8") << raw("\xdb\0\0\0\0\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
1496
1497 // non-canonical: string length in chunked transfer
1498 QTest::newRow("overlong-_bytearray-0*1") << raw("\x5f\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1499 QTest::newRow("overlong-_bytearray-0*2") << raw("\x5f\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1500 QTest::newRow("overlong-_bytearray-0*4") << raw("\x5f\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1501 QTest::newRow("overlong-_bytearray-0*8") << raw("\x5f\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1502 QTest::newRow("overlong-_bytearray-24*2") << (raw("\x5f\x59\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1503 QTest::newRow("overlong-_bytearray-24*4") << (raw("\x5f\x5a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1504 QTest::newRow("overlong-_bytearray-24*8") << (raw("\x5f\x5b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1505 QTest::newRow("overlong-_bytearray-256*4") << (raw("\x5f\x5a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1506 QTest::newRow("overlong-_bytearray-256*8") << (raw("\x5f\x5b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1507 QTest::newRow("overlong-_bytearray-65536*8") << (raw("\x5f\x5b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1508 QTest::newRow("overlong-_bytearrayx2-0*1") << raw("\x5f\x40\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1509 QTest::newRow("overlong-_bytearrayx2-0*2") << raw("\x5f\x40\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1510 QTest::newRow("overlong-_bytearrayx2-0*4") << raw("\x5f\x40\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1511 QTest::newRow("overlong-_bytearrayx2-0*8") << raw("\x5f\x40\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1512 QTest::newRow("overlong-_string-0*1") << raw("\x7f\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1513 QTest::newRow("overlong-_string-0*2") << raw("\x7f\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1514 QTest::newRow("overlong-_string-0*4") << raw("\x7f\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1515 QTest::newRow("overlong-_string-0*8") << raw("\x7f\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1516 QTest::newRow("overlong-_string-24*2") << (raw("\x7f\x79\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1517 QTest::newRow("overlong-_string-24*4") << (raw("\x7f\x7a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1518 QTest::newRow("overlong-_string-24*8") << (raw("\x7f\x7b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1519 QTest::newRow("overlong-_string-256*4") << (raw("\x7f\x7a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1520 QTest::newRow("overlong-_string-256*8") << (raw("\x7f\x7b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1521 QTest::newRow("overlong-_string-65536*8") << (raw("\x7f\x7b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1522 QTest::newRow("overlong-_stringx2-0*1") << raw("\x7f\x60\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1523 QTest::newRow("overlong-_stringx2-0*2") << raw("\x7f\x60\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1524 QTest::newRow("overlong-_stringx2-0*4") << raw("\x7f\x60\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1525 QTest::newRow("overlong-_stringx2-0*8") << raw("\x7f\x60\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
1526
1527 // strict mode
1528 // UTF-8 sequences with invalid continuation bytes
1529 QTest::newRow("invalid-utf8-bad-continuation-1char") << raw("\x61\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1530 QTest::newRow("invalid-utf8-bad-continuation-2chars-1") << raw("\x62\xc2\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1531 QTest::newRow("invalid-utf8-bad-continuation-2chars-2") << raw("\x62\xc3\xdf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1532 QTest::newRow("invalid-utf8-bad-continuation-2chars-3") << raw("\x62\xc7\xf0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1533 QTest::newRow("invalid-utf8-bad-continuation-3chars-1") << raw("\x63\xe0\xa0\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1534 QTest::newRow("invalid-utf8-bad-continuation-3chars-2") << raw("\x63\xe0\xc0\xa0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1535 QTest::newRow("invalid-utf8-bad-continuation-4chars-1") << raw("\x64\xf0\x90\x80\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1536 QTest::newRow("invalid-utf8-bad-continuation-4chars-2") << raw("\x64\xf0\x90\xc0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1537 QTest::newRow("invalid-utf8-bad-continuation-4chars-3") << raw("\x64\xf0\xc0\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1538 // 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)
1539 QTest::newRow("invalid-utf8-too-short-2chars") << raw("\x82\x61\xc2\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1540 QTest::newRow("invalid-utf8-too-short-3chars-1") << raw("\x82\x61\xe0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1541 QTest::newRow("invalid-utf8-too-short-3chars-2") << raw("\x82\x62\xe0\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1542 QTest::newRow("invalid-utf8-too-short-4chars-1") << raw("\x82\x61\xf0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1543 QTest::newRow("invalid-utf8-too-short-4chars-2") << raw("\x82\x62\xf0\x90\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1544 QTest::newRow("invalid-utf8-too-short-4chars-3") << raw("\x82\x63\xf0\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1545 // UTF-16 surrogages encoded in UTF-8
1546 QTest::newRow("invalid-utf8-hi-surrogate") << raw("\x63\xed\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1547 QTest::newRow("invalid-utf8-lo-surrogate") << raw("\x63\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1548 QTest::newRow("invalid-utf8-surrogate-pair") << raw("\x66\xed\xa0\x80\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1549 // Non-Unicode UTF-8 sequences
1550 QTest::newRow("invalid-utf8-non-unicode-1") << raw("\x64\xf4\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1551 QTest::newRow("invalid-utf8-non-unicode-2") << raw("\x65\xf8\x88\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1552 QTest::newRow("invalid-utf8-non-unicode-3") << raw("\x66\xfc\x84\x80\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1553 QTest::newRow("invalid-utf8-non-unicode-4") << raw("\x66\xfd\xbf\xbf\xbf\xbf\xbf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1554 // invalid bytes in UTF-8
1555 QTest::newRow("invalid-utf8-fe") << raw("\x61\xfe") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1556 QTest::newRow("invalid-utf8-ff") << raw("\x61\xff") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1557 // Overlong sequences
1558 QTest::newRow("invalid-utf8-overlong-1-2") << raw("\x62\xc1\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1559 QTest::newRow("invalid-utf8-overlong-1-3") << raw("\x63\xe0\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1560 QTest::newRow("invalid-utf8-overlong-1-4") << raw("\x64\xf0\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1561 QTest::newRow("invalid-utf8-overlong-1-5") << raw("\x65\xf8\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1562 QTest::newRow("invalid-utf8-overlong-1-6") << raw("\x66\xfc\x80\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1563 QTest::newRow("invalid-utf8-overlong-2-3") << raw("\x63\xe0\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1564 QTest::newRow("invalid-utf8-overlong-2-4") << raw("\x64\xf0\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1565 QTest::newRow("invalid-utf8-overlong-2-5") << raw("\x65\xf8\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1566 QTest::newRow("invalid-utf8-overlong-2-6") << raw("\x66\xfc\x80\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1567 QTest::newRow("invalid-utf8-overlong-3-4") << raw("\x64\xf0\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1568 QTest::newRow("invalid-utf8-overlong-3-5") << raw("\x65\xf8\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1569 QTest::newRow("invalid-utf8-overlong-3-6") << raw("\x66\xfc\x80\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1570 QTest::newRow("invalid-utf8-overlong-4-5") << raw("\x65\xf8\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1571 QTest::newRow("invalid-utf8-overlong-4-6") << raw("\x66\xfc\x80\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
1572
1573 QTest::newRow("nonunique-content-map-UU") << raw("\xa2\0\1\0\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
1574 QTest::newRow("nonunique-content-map-SS") << raw("\xa2\x61z\1\x61z\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
1575 QTest::newRow("nonunique-content-map-AA") << raw("\xa2\x81\x65Hello\1\x81\x65Hello\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
1576
1577 QTest::newRow("tag-0-unsigned") << raw("\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1578 QTest::newRow("tag-0-bytearray") << raw("\xc0\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1579 QTest::newRow("tag-0-string") << raw("\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
1580 QTest::newRow("tag-0-tag-0-string") << raw("\xc0\xc0\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1581 QTest::newRow("tag-1-unsigned") << raw("\xc1\x00") << int(CborValidateStrictMode) << CborNoError;
1582 QTest::newRow("tag-1-negative") << raw("\xc1\x20") << int(CborValidateStrictMode) << CborNoError;
1583 QTest::newRow("tag-1-bytearray") << raw("\xc1\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1584 QTest::newRow("tag-2-bytearray") << raw("\xc2\x40") << int(CborValidateStrictMode) << CborNoError;
1585 QTest::newRow("tag-2-string") << raw("\xc2\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1586 QTest::newRow("tag-3-bytearray") << raw("\xc3\x40") << int(CborValidateStrictMode) << CborNoError;
1587 QTest::newRow("tag-3-string") << raw("\xc3\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1588 QTest::newRow("tag-4-string") << raw("\xc4\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1589 QTest::newRow("tag-4-array") << raw("\xc4\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
1590 QTest::newRow("tag-5-string") << raw("\xc5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1591 QTest::newRow("tag-5-array") << raw("\xc5\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
1592 QTest::newRow("tag-21-bytearray") << raw("\xd5\x40") << int(CborValidateStrictMode) << CborNoError;
1593 QTest::newRow("tag-21-string") << raw("\xd5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1594 QTest::newRow("tag-21-array") << raw("\xd5\x80") << int(CborValidateStrictMode) << CborNoError;
1595 QTest::newRow("tag-21-map") << raw("\xd5\xa0") << int(CborValidateStrictMode) << CborNoError;
1596 QTest::newRow("tag-22-bytearray") << raw("\xd6\x40") << int(CborValidateStrictMode) << CborNoError;
1597 QTest::newRow("tag-22-string") << raw("\xd6\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1598 QTest::newRow("tag-22-array") << raw("\xd6\x80") << int(CborValidateStrictMode) << CborNoError;
1599 QTest::newRow("tag-22-map") << raw("\xd6\xa0") << int(CborValidateStrictMode) << CborNoError;
1600 QTest::newRow("tag-23-bytearray") << raw("\xd7\x40") << int(CborValidateStrictMode) << CborNoError;
1601 QTest::newRow("tag-23-string") << raw("\xd7\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1602 QTest::newRow("tag-23-array") << raw("\xd7\x80") << int(CborValidateStrictMode) << CborNoError;
1603 QTest::newRow("tag-23-map") << raw("\xd7\xa0") << int(CborValidateStrictMode) << CborNoError;
1604 QTest::newRow("tag-24-bytearray") << raw("\xd8\x18\x40") << int(CborValidateStrictMode) << CborNoError;
1605 QTest::newRow("tag-24-string") << raw("\xd8\x18\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1606 QTest::newRow("tag-32-bytearray") << raw("\xd8\x20\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1607 QTest::newRow("tag-32-string") << raw("\xd8\x20\x60") << int(CborValidateStrictMode) << CborNoError;
1608 QTest::newRow("tag-33-bytearray") << raw("\xd8\x21\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1609 QTest::newRow("tag-33-string") << raw("\xd8\x21\x60") << int(CborValidateStrictMode) << CborNoError;
1610 QTest::newRow("tag-34-bytearray") << raw("\xd8\x22\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1611 QTest::newRow("tag-34-string") << raw("\xd8\x22\x60") << int(CborValidateStrictMode) << CborNoError;
1612 QTest::newRow("tag-35-bytearray") << raw("\xd8\x23\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1613 QTest::newRow("tag-35-string") << raw("\xd8\x23\x60") << int(CborValidateStrictMode) << CborNoError;
1614 QTest::newRow("tag-36-bytearray") << raw("\xd8\x24\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1615 QTest::newRow("tag-36-string") << raw("\xd8\x24\x60") << int(CborValidateStrictMode) << CborNoError;
1616 QTest::newRow("tag-55799-unsigned") << raw("\xd9\xd9\xf7\x00") << int(CborValidateStrictMode) << CborNoError;
1617 QTest::newRow("tag-55799-negative") << raw("\xd9\xd9\xf7\x20") << int(CborValidateStrictMode) << CborNoError;
1618 QTest::newRow("tag-55799-bytearray") << raw("\xd9\xd9\xf7\x40") << int(CborValidateStrictMode) << CborNoError;
1619 QTest::newRow("tag-55799-string") << raw("\xd9\xd9\xf7\x60") << int(CborValidateStrictMode) << CborNoError;
1620 QTest::newRow("tag-55799-array") << raw("\xd9\xd9\xf7\x80") << int(CborValidateStrictMode) << CborNoError;
1621 QTest::newRow("tag-55799-map") << raw("\xd9\xd9\xf7\xa0") << int(CborValidateStrictMode) << CborNoError;
1622 QTest::newRow("tag-55799-tag-0-unsigned") << raw("\xd9\xd9\xf7\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1623 QTest::newRow("tag-55799-tag-0-string") << raw("\xd9\xd9\xf7\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
1624 QTest::newRow("tag-55799-simple0") << raw("\xd9\xd9\xf7\xe0") << int(CborValidateStrictMode) << CborNoError;
1625 QTest::newRow("tag-55799-false") << raw("\xd9\xd9\xf7\xf4") << int(CborValidateStrictMode) << CborNoError;
1626 QTest::newRow("tag-55799-true") << raw("\xd9\xd9\xf7\xf5") << int(CborValidateStrictMode) << CborNoError;
1627 QTest::newRow("tag-55799-null") << raw("\xd9\xd9\xf7\xf6") << int(CborValidateStrictMode) << CborNoError;
1628 QTest::newRow("tag-55799-undefined") << raw("\xd9\xd9\xf7\xf7") << int(CborValidateStrictMode) << CborNoError;
1629 QTest::newRow("tag-55799-simple32") << raw("\xd9\xd9\xf7\xf8\x20") << int(CborValidateStrictMode) << CborNoError;
1630 QTest::newRow("tag-55799-half") << raw("\xd9\xd9\xf7\xf9\0\0") << int(CborValidateStrictMode) << CborNoError;
1631 QTest::newRow("tag-55799-float") << raw("\xd9\xd9\xf7\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
1632 QTest::newRow("tag-55799-double") << raw("\xd9\xd9\xf7\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
1633
1634 // excluded non-finite
1635 QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1636 QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1637 QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1638 QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1639 QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1640 QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1641
1642 // excluded undefined
1643 QTest::newRow("no-undefined") << raw("\xf7") << int(CborValidateNoUndefined) << CborErrorExcludedType;
1644
1645 // exclude non-finite
1646 QTest::newRow("excluded-fp-nan_f16") << raw("\xf9\x7e\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1647 QTest::newRow("excluded-fp--inf_f16") << raw("\xf9\xfc\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1648 QTest::newRow("excluded-fp-+inf_f16") << raw("\xf9\x7c\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1649 QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1650 QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1651 QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1652 QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1653 QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1654 QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
1655
1656 // exclude non-string keys in maps
1657 QTest::newRow("excluded-map-unsigned") << raw("\xa1\x00\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1658 QTest::newRow("excluded-map-negative") << raw("\xa1\x20\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1659 QTest::newRow("excluded-map-bytearray") << raw("\xa1\x40\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1660 QTest::newRow("map-string") << raw("\xa1\x60\1") << int(CborValidateMapKeysAreString) << CborNoError;
1661 QTest::newRow("map-tag-0-string") << raw("\xa1\xc0\x60\1") << int(CborValidateMapKeysAreString) << CborNoError;
1662 QTest::newRow("excluded-map-array") << raw("\xa1\x80\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1663 QTest::newRow("excluded-map-map") << raw("\xa1\xa0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1664 QTest::newRow("excluded-map-simple-0") << raw("\xa1\xe0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1665 QTest::newRow("excluded-map-false") << raw("\xa1\xf4\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1666 QTest::newRow("excluded-map-true") << raw("\xa1\xf5\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1667 QTest::newRow("excluded-map-null") << raw("\xa1\xf6\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1668 QTest::newRow("excluded-map-undefined") << raw("\xa1\xf7\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1669 QTest::newRow("excluded-map-half") << raw("\xa1\xf9\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1670 QTest::newRow("excluded-map-float") << raw("\xa1\xfa\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1671 QTest::newRow("excluded-map-double") << raw("\xa1\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
1672
1673 // unknown simple types
1674 QTest::newRow("unknown-simple-type-0") << raw("\xe0") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType;
1675 QTest::newRow("unknown-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType;
1676 QTest::newRow("allowed-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypesSA) << CborNoError;
1677
1678 // unknown tags
1679 QTest::newRow("unknown-tag-6") << raw("\xc6\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
1680 QTest::newRow("unknown-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
1681 QTest::newRow("unknown-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
1682 QTest::newRow("unknown-tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
1683 QTest::newRow("unknown-tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
1684 QTest::newRow("allowed-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTagsSA) << CborNoError;
1685 QTest::newRow("allowed-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTagsSR) << CborNoError;
1686
1687 // excluded tags
1688 QTest::newRow("excluded-tag-0") << raw("\xc0\x60") << int(CborValidateNoTags) << CborErrorExcludedType;
1689 QTest::newRow("excluded-tag-24") << raw("\xd8\x18\x40") << int(CborValidateNoTags) << CborErrorExcludedType;
1690 QTest::newRow("excluded-tag-55799") << raw("\xd9\xd9\xf7\x60") << int(CborValidateNoTags) << CborErrorExcludedType;
1691
1692 // complete data
1693 QTest::newRow("garbage-data-0") << raw("\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1694 QTest::newRow("garbage-data-1") << raw("\x20\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1695 QTest::newRow("garbage-data-2") << raw("\x40\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1696 QTest::newRow("garbage-data-3") << raw("\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1697 QTest::newRow("garbage-data-4") << raw("\x80\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1698 QTest::newRow("garbage-data-5") << raw("\xa0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1699 QTest::newRow("garbage-data-6") << raw("\xc0\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1700 QTest::newRow("garbage-data-7") << raw("\xf4\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1701 QTest::newRow("garbage-data-f16") << raw("\xf9\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1702 QTest::newRow("garbage-data-f32") << raw("\xfa\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1703 QTest::newRow("garbage-data-f64") << raw("\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
1704 }
1705
strictValidation()1706 void tst_Parser::strictValidation()
1707 {
1708 QFETCH(QByteArray, data);
1709 QFETCH(int, flags);
1710 QFETCH(CborError, expectedError);
1711
1712 QString decoded;
1713 ParserWrapper w;
1714 CborError err = w.init(data);
1715 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1716
1717 err = cbor_value_validate(&w.first, flags);
1718 QCOMPARE(err, expectedError);
1719 }
1720
incompleteData_data()1721 void tst_Parser::incompleteData_data()
1722 {
1723 addColumns();
1724 addFixedData();
1725 addStringsData();
1726 addTagsData();
1727 addMapMixedData();
1728 }
1729
incompleteData()1730 void tst_Parser::incompleteData()
1731 {
1732 QFETCH(QByteArray, data);
1733 QFETCH(QString, expected);
1734
1735 for (int len = 0; len < data.length() - 1; ++len) {
1736 ParserWrapper w;
1737 CborError err = w.init(data.constData(), len);
1738 if (!err) {
1739 QString decoded;
1740 err = parseOne(&w.first, &decoded);
1741 }
1742 if (err != CborErrorUnexpectedEOF)
1743 qDebug() << "Length is" << len;
1744 QCOMPARE(err, CborErrorUnexpectedEOF);
1745 }
1746 }
1747
endPointer_data()1748 void tst_Parser::endPointer_data()
1749 {
1750 QTest::addColumn<QByteArray>("data");
1751 QTest::addColumn<int>("offset");
1752
1753 QTest::newRow("number1") << raw("\x81\x01\x01") << 2;
1754 QTest::newRow("number24") << raw("\x81\x18\x18\x01") << 3;
1755 QTest::newRow("string") << raw("\x81\x61Z\x01") << 3;
1756 QTest::newRow("indefinite-string") << raw("\x81\x7f\x61Z\xff\x01") << 5;
1757 QTest::newRow("array") << raw("\x81\x02\x01") << 2;
1758 QTest::newRow("indefinite-array") << raw("\x81\x9f\x02\xff\x01") << 4;
1759 QTest::newRow("object") << raw("\x81\xa1\x03\x02\x01") << 4;
1760 QTest::newRow("indefinite-object") << raw("\x81\xbf\x03\x02\xff\x01") << 5;
1761 }
1762
endPointer()1763 void tst_Parser::endPointer()
1764 {
1765 QFETCH(QByteArray, data);
1766 QFETCH(int, offset);
1767
1768 QString decoded;
1769 ParserWrapper w;
1770 CborError err = w.init(data);
1771 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1772
1773 err = parseOne(&w.first, &decoded);
1774 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1775 QCOMPARE(int(cbor_value_get_next_byte(&w.first) - w.begin()), offset);
1776 }
1777
recursionLimit_data()1778 void tst_Parser::recursionLimit_data()
1779 {
1780 static const int recursions = CBOR_PARSER_MAX_RECURSIONS + 2;
1781 QTest::addColumn<QByteArray>("data");
1782
1783 QTest::newRow("array") << QByteArray(recursions, '\x81') + '\x20';
1784 QTest::newRow("_array") << QByteArray(recursions, '\x9f') + '\x20' + QByteArray(recursions, '\xff');
1785
1786 QByteArray data;
1787 for (int i = 0; i < recursions; ++i)
1788 data += "\xa1\x65Hello";
1789 data += '\2';
1790 QTest::newRow("map-recursive-values") << data;
1791
1792 data.clear();
1793 for (int i = 0; i < recursions; ++i)
1794 data += "\xbf\x65World";
1795 data += '\2';
1796 for (int i = 0; i < recursions; ++i)
1797 data += "\xff";
1798 QTest::newRow("_map-recursive-values") << data;
1799
1800 data = QByteArray(recursions, '\xa1');
1801 data += '\2';
1802 for (int i = 0; i < recursions; ++i)
1803 data += "\x7f\x64quux\xff";
1804 QTest::newRow("map-recursive-keys") << data;
1805
1806 data = QByteArray(recursions, '\xbf');
1807 data += '\2';
1808 for (int i = 0; i < recursions; ++i)
1809 data += "\1\xff";
1810 QTest::newRow("_map-recursive-keys") << data;
1811
1812 data.clear();
1813 for (int i = 0; i < recursions / 2; ++i)
1814 data += "\x81\xa1\1";
1815 data += '\2';
1816 QTest::newRow("mixed") << data;
1817 }
1818
recursionLimit()1819 void tst_Parser::recursionLimit()
1820 {
1821 QFETCH(QByteArray, data);
1822
1823 ParserWrapper w;
1824 CborError err = w.init(data);
1825 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1826
1827 // check that it is valid:
1828 CborValue it = w.first;
1829 {
1830 QString dummy;
1831 err = parseOne(&it, &dummy);
1832 QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
1833 }
1834
1835 it = w.first;
1836 err = cbor_value_advance(&it);
1837 QCOMPARE(err, CborErrorNestingTooDeep);
1838
1839 it = w.first;
1840 if (cbor_value_is_map(&it)) {
1841 CborValue dummy;
1842 err = cbor_value_map_find_value(&it, "foo", &dummy);
1843 QCOMPARE(err, CborErrorNestingTooDeep);
1844 }
1845 }
1846
1847 QTEST_MAIN(tst_Parser)
1848 #include "tst_parser.moc"
1849