blob: 2328912bf36fe769260bf75b1d6b3cccbe51170f [file] [log] [blame]
Laurence Lundblade2ded3d92018-10-09 21:36:11 +08001/*==============================================================================
2Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28==============================================================================*/
29
30#include "qcbor.h"
31#include "qcbor_decode_tests.h"
32#include <stdio.h>
33#include <strings.h>
34#include <float.h>
35#include <math.h>
36#include <stdlib.h>
37
38
39// TODO: test other than the normal decoder mode
40
41static void printencoded(const char *szLabel, const uint8_t *pEncoded, size_t nLen)
42{
43 if(szLabel) {
44 printf("%s ", szLabel);
45 }
46
47 int i;
48 for(i = 0; i < nLen; i++) {
49 uint8_t Z = pEncoded[i];
50 printf("%02x ", Z);
51 }
52 printf("\n");
53
54 fflush(stdout);
55}
56
57
58// TODO: -- add a test for counting the top level items and adding it back in with AddRaw()
59
60
61static const uint8_t pExpectedEncodedInts[] = {
62 0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
63 0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01,
64 0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff,
65 0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff,
66 0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff,
67 0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01,
68 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39,
69 0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd,
70 0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38,
71 0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00,
72 0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18,
73 0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00,
74 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff,
75 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00,
76 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02,
77 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff,
78 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a,
79 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff,
80 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00,
81 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
82 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
83 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85 0xff, 0xff};
86
87
88
89
90
91
92
93
94
95// return CBOR error or -1 if type of value doesn't match
96
97static int IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx)
98{
99 QCBORItem Item;
100 int nCBORError;
101
102 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
103 return nCBORError;
104 if(Item.uDataType != QCBOR_TYPE_ARRAY)
105 return -1;
106
107 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
108 return nCBORError;
109 if(Item.uDataType != QCBOR_TYPE_INT64 || // Todo; fix this for 32-bit machines
110 Item.val.uint64 != -9223372036854775807LL - 1)
111 return -1;
112
113 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
114 return nCBORError;
115 if(Item.uDataType != QCBOR_TYPE_INT64 ||
116 Item.val.uint64 != -4294967297)
117 return -1;
118
119 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
120 return nCBORError;
121 if(Item.uDataType != QCBOR_TYPE_INT64 ||
122 Item.val.uint64 != -4294967296)
123 return -1;
124
125 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
126 return nCBORError;
127 if(Item.uDataType != QCBOR_TYPE_INT64 ||
128 Item.val.uint64 != -4294967295)
129 return -1;
130
131 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
132 return nCBORError;
133 if(Item.uDataType != QCBOR_TYPE_INT64 ||
134 Item.val.uint64 != -4294967294)
135 return -1;
136
137
138 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
139 return nCBORError;
140 if(Item.uDataType != QCBOR_TYPE_INT64 ||
141 Item.val.int64 != -2147483648)
142 return -1;
143
144 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
145 return nCBORError;
146 if(Item.uDataType != QCBOR_TYPE_INT64 ||
147 Item.val.int64 != -2147483647)
148 return -1;
149
150 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
151 return nCBORError;
152 if(Item.uDataType != QCBOR_TYPE_INT64 ||
153 Item.val.int64 != -65538)
154 return -1;
155
156 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
157 return nCBORError;
158 if(Item.uDataType != QCBOR_TYPE_INT64 ||
159 Item.val.int64 != -65537)
160 return -1;
161
162 if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
163 return nCBORError;
164 if(Item.uDataType != QCBOR_TYPE_INT64 ||
165 Item.val.int64 != -65536)
166 return -1;
167
168
169 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
170 return nCBORError;
171 if(Item.uDataType != QCBOR_TYPE_INT64 ||
172 Item.val.int64 != -65535)
173 return -1;
174
175
176 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
177 return nCBORError;
178 if(Item.uDataType != QCBOR_TYPE_INT64 ||
179 Item.val.int64 != -65534)
180 return -1;
181
182
183 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
184 return nCBORError;
185 if(Item.uDataType != QCBOR_TYPE_INT64 ||
186 Item.val.int64 != -257)
187 return -1;
188
189 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
190 return nCBORError;
191 if(Item.uDataType != QCBOR_TYPE_INT64 ||
192 Item.val.int64 != -256)
193 return -1;
194
195 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
196 return nCBORError;
197 if(Item.uDataType != QCBOR_TYPE_INT64 ||
198 Item.val.int64 != -255)
199 return -1;
200
201 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
202 return nCBORError;
203 if(Item.uDataType != QCBOR_TYPE_INT64 ||
204 Item.val.int64 != -254)
205 return -1;
206
207
208 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
209 return nCBORError;
210 if(Item.uDataType != QCBOR_TYPE_INT64 ||
211 Item.val.int64 != -25)
212 return -1;
213
214
215 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
216 return nCBORError;
217 if(Item.uDataType != QCBOR_TYPE_INT64 ||
218 Item.val.int64 != -24)
219 return -1;
220
221
222 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
223 return nCBORError;
224 if(Item.uDataType != QCBOR_TYPE_INT64 ||
225 Item.val.int64 != -23)
226 return -1;
227
228
229 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
230 return nCBORError;
231 if(Item.uDataType != QCBOR_TYPE_INT64 ||
232 Item.val.int64 != -1)
233 return -1;
234
235
236 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
237 return nCBORError;
238 if(Item.uDataType != QCBOR_TYPE_INT64 ||
239 Item.val.int64 != 0)
240 return -1;
241
242
243 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
244 return nCBORError;
245 if(Item.uDataType != QCBOR_TYPE_INT64 ||
246 Item.val.int64 != 0)
247 return -1;
248
249 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
250 return nCBORError;
251 if(Item.uDataType != QCBOR_TYPE_INT64 ||
252 Item.val.int64 != 1)
253 return -1;
254
255
256 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
257 return nCBORError;
258 if(Item.uDataType != QCBOR_TYPE_INT64 ||
259 Item.val.int64 != 22)
260 return -1;
261
262
263 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
264 return nCBORError;
265 if(Item.uDataType != QCBOR_TYPE_INT64 ||
266 Item.val.int64 != 23)
267 return -1;
268
269
270 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
271 return nCBORError;
272 if(Item.uDataType != QCBOR_TYPE_INT64 ||
273 Item.val.int64 != 24)
274 return -1;
275
276
277 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
278 return nCBORError;
279 if(Item.uDataType != QCBOR_TYPE_INT64 ||
280 Item.val.int64 != 25)
281 return -1;
282
283 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
284 return nCBORError;
285 if(Item.uDataType != QCBOR_TYPE_INT64 ||
286 Item.val.int64 != 26)
287 return -1;
288
289
290 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
291 return nCBORError;
292 if(Item.uDataType != QCBOR_TYPE_INT64 ||
293 Item.val.int64 != 254)
294 return -1;
295
296
297 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
298 return nCBORError;
299 if(Item.uDataType != QCBOR_TYPE_INT64 ||
300 Item.val.int64 != 255)
301 return -1;
302
303
304 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
305 return nCBORError;
306 if(Item.uDataType != QCBOR_TYPE_INT64 ||
307 Item.val.int64 != 256)
308 return -1;
309
310
311 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
312 return nCBORError;
313 if(Item.uDataType != QCBOR_TYPE_INT64 ||
314 Item.val.int64 != 257)
315 return -1;
316
317 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
318 return nCBORError;
319 if(Item.uDataType != QCBOR_TYPE_INT64 ||
320 Item.val.int64 != 65534)
321 return -1;
322
323
324 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
325 return nCBORError;
326 if(Item.uDataType != QCBOR_TYPE_INT64 ||
327 Item.val.int64 != 65535)
328 return -1;
329
330
331 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
332 return nCBORError;
333 if(Item.uDataType != QCBOR_TYPE_INT64 ||
334 Item.val.int64 != 65536)
335 return -1;
336
337 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
338 return nCBORError;
339 if(Item.uDataType != QCBOR_TYPE_INT64 ||
340 Item.val.int64 != 65537)
341 return -1;
342
343 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
344 return nCBORError;
345 if(Item.uDataType != QCBOR_TYPE_INT64 ||
346 Item.val.int64 != 65538)
347 return -1;
348
349 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
350 return nCBORError;
351 if(Item.uDataType != QCBOR_TYPE_INT64 ||
352 Item.val.int64 != 2147483647)
353 return -1;
354
355 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
356 return nCBORError;
357 if(Item.uDataType != QCBOR_TYPE_INT64 ||
358 Item.val.int64 != 2147483647)
359 return -1;
360
361 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
362 return nCBORError;
363 if(Item.uDataType != QCBOR_TYPE_INT64 ||
364 Item.val.int64 != 2147483648)
365 return -1;
366
367 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
368 return nCBORError;
369 if(Item.uDataType != QCBOR_TYPE_INT64 ||
370 Item.val.int64 != 2147483649)
371 return -1;
372
373 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
374 return nCBORError;
375 if(Item.uDataType != QCBOR_TYPE_INT64 ||
376 Item.val.int64 != 4294967294)
377 return -1;
378
379
380 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
381 return nCBORError;
382 if(Item.uDataType != QCBOR_TYPE_INT64 ||
383 Item.val.int64 != 4294967295)
384 return -1;
385
386
387 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
388 return nCBORError;
389 if(Item.uDataType != QCBOR_TYPE_INT64 ||
390 Item.val.int64 != 4294967296)
391 return -1;
392
393
394 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
395 return nCBORError;
396 if(Item.uDataType != QCBOR_TYPE_INT64 ||
397 Item.val.int64 != 4294967297)
398 return -1;
399
400
401
402 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
403 return nCBORError;
404 if(Item.uDataType != QCBOR_TYPE_INT64 ||
405 Item.val.int64 != 9223372036854775807LL)
406 return -1;
407
408
409 if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
410 return nCBORError;
411 if(Item.uDataType != QCBOR_TYPE_UINT64 ||
412 Item.val.uint64 != 18446744073709551615ULL)
413 return -1;
414
415
416 if(QCBORDecode_Finish(pDCtx) != QCBOR_SUCCESS) {
417 return -1;
418 }
419
420 return 0;
421}
422
423
424/*
425 Tests the decoding of lots of different integers sizes
426 and values.
427
428 Todo: test values 254, 255 and 256
429
430 */
431
432int IntegerValuesParseTest()
433{
434 int n;
435 QCBORDecodeContext DCtx;
436
437 QCBORDecode_Init(&DCtx, (UsefulBufC){pExpectedEncodedInts, sizeof(pExpectedEncodedInts)}, QCBOR_DECODE_MODE_NORMAL);
438
439 n = IntegerValuesParseTestInternal(&DCtx);
440
441 return(n);
442}
443
444
445/*
446 Creates a simple CBOR array and returns it in *pEncoded. The array is malloced
447 and needs to be freed. This is used by several tests.
448
449 Two of the inputs can be set. Two other items in the array are fixed.
450
451 */
452
453static int CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen)
454{
455 QCBOREncodeContext ECtx;
456 int nReturn = -1;
457
458 *pEncoded = NULL;
459 *pEncodedLen = INT32_MAX;
460
461 // loop runs CBOR encoding twice. First with no buffer to
462 // calucate the length so buffer can be allocated correctly,
463 // and last with the buffer to do the actual encoding
464 do {
465 QCBOREncode_Init(&ECtx, *pEncoded, *pEncodedLen);
466 QCBOREncode_OpenArray(&ECtx);
467 QCBOREncode_AddInt64(&ECtx, nInt1);
468 QCBOREncode_AddInt64(&ECtx, nInt2);
469 QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"galactic", 8}));
470 QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"haven token", 11}));
471 QCBOREncode_CloseArray(&ECtx);
472
473 if(QCBOREncode_Finish(&ECtx, pEncodedLen))
474 goto Done;
475
476 if(*pEncoded != NULL) {
477 nReturn = 0;
478 goto Done;
479 }
480 *pEncoded = malloc(*pEncodedLen);
481 if(*pEncoded == NULL) {
482 nReturn = -1;
483 goto Done;
484 }
485
486 } while(1);
487Done:
488 return (nReturn);
489
490}
491
492
493
494/*
495 {"first integer": 42,
496 "an array of two strings": ["string1", "string2"],
497 "map in a map": {
498 "bytes 1": h'78787878',
499 "bytes 2": h'79797979',
500 "another int": 98, "text 2":
501 "lies, damn lies and statistics"}
502 }
503 */
504
505static uint8_t pValidMapEncoded[] = {
506 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a,
507 0x77, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x77, 0x6f, 0x20,
508 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x67,
509 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
510 0x6d, 0x61, 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, 0x44, 0x78, 0x78, 0x78, 0x78,
511 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, 0x6e, 0x6f,
512 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32,
513 0x78, 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73,
514 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73 } ;
515
516
517
518
519
520
521
522static int ParseOrderedArray(const uint8_t *pEncoded, size_t nLen, int64_t *pInt1, int64_t *pInt2, const uint8_t **pBuf3, size_t *pBuf3Len, const uint8_t **pBuf4, size_t *pBuf4Len)
523{
524 QCBORDecodeContext DCtx;
525 QCBORItem Item;
526 int nReturn = -1; // assume error until success
527
528 QCBORDecode_Init(&DCtx, (UsefulBufC){pEncoded, nLen}, QCBOR_DECODE_MODE_NORMAL);
529
530 // Make sure the first thing is a map
531 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_ARRAY)
532 goto Done;
533
534 // First integer
535 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 | Item.uDataType != QCBOR_TYPE_INT64)
536 goto Done;
537 *pInt1 = Item.val.int64;
538
539 // Second integer
540 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_INT64)
541 goto Done;
542 *pInt2 = Item.val.int64;
543
544 // First string
545 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_BYTE_STRING)
546 goto Done;
547 *pBuf3 = Item.val.string.ptr;
548 *pBuf3Len = Item.val.string.len;
549
550 // Second string
551 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_BYTE_STRING)
552 goto Done;
553 *pBuf4 = Item.val.string.ptr;
554 *pBuf4Len = Item.val.string.len;
555
556 nReturn = 0;
557
558Done:
559 return(nReturn);
560}
561
562
563
564int SimpleArrayTest()
565{
566 uint8_t *pEncoded;
567 size_t nEncodedLen;
568
569 int64_t i1, i2;
570 size_t i3, i4;
571 const uint8_t *s3, *s4;
572
573
574 if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) {
575 return(-1);
576 }
577
578 ParseOrderedArray(pEncoded, nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4);
579
580 if(i1 != 23 ||
581 i2 != 6000 ||
582 i3 != 8 ||
583 i4 != 11 ||
584 bcmp("galactic", s3, 8) !=0 ||
585 bcmp("haven token", s4, 11) !=0) {
586 printf("SimpleArraryTest Failed\n");
587 return(-1);
588 }
589
590 return(0);
591}
592
593
594static uint8_t s_pDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
595
596int ParseDeepArrayTest()
597{
598 QCBORDecodeContext DCtx;
599 int nReturn = 0;
600 int i;
601
602 QCBORDecode_Init(&DCtx, (UsefulBufC){s_pDeepArrays, sizeof(s_pDeepArrays)}, QCBOR_DECODE_MODE_NORMAL);
603
604 for(i = 0; i < 10; i++) {
605 QCBORItem Item;
606
607 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
608 Item.uDataType != QCBOR_TYPE_ARRAY ||
609 Item.uNestingLevel != i) {
610 nReturn = -1;
611 break;
612 }
613 }
614
615 return(nReturn);
616}
617
618
619
620static uint8_t s_pTooDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
621
622int ParseTooDeepArrayTest()
623{
624 QCBORDecodeContext DCtx;
625 int nReturn = 0;
626 int i;
627 QCBORItem Item;
628
629
630 QCBORDecode_Init(&DCtx, (UsefulBufC){s_pTooDeepArrays, sizeof(s_pTooDeepArrays)}, QCBOR_DECODE_MODE_NORMAL);
631
632 for(i = 0; i < 10; i++) {
633
634 if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
635 Item.uDataType != QCBOR_TYPE_ARRAY ||
636 Item.uNestingLevel != i) {
637 nReturn = -1;
638 break;
639 }
640 }
641
642 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP)
643 nReturn = -1;
644
645 return(nReturn);
646}
647
648
649
650
651static uint8_t s_indefiniteLenString[] = { 0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff};
652
653
654int UnsupportedCBORDecodeTest()
655{
656 QCBORDecodeContext DCtx;
657 QCBORItem Item;
658
659 QCBORDecode_Init(&DCtx, (UsefulBufC){s_indefiniteLenString, sizeof(s_indefiniteLenString)}, QCBOR_DECODE_MODE_NORMAL);
660 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_UNSUPPORTED)
661 return -1;
662
663 return 0;
664}
665
666
667
668int ShortBufferParseTest()
669{
670 int nResult = 0;
671 QCBORDecodeContext DCtx;
672 int num;
673
674 for(num = sizeof(pExpectedEncodedInts)-1; num; num--) {
675 int n;
676
677 QCBORDecode_Init(&DCtx, (UsefulBufC){pExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL);
678
679 n = IntegerValuesParseTestInternal(&DCtx);
680
681 //printf("Len %d, result: %d\n", num, n);
682
683 if(n != QCBOR_ERR_HIT_END) {
684 nResult = -1;
685 goto Done;
686 }
687 }
688Done:
689 return nResult;
690}
691
692
693int ShortBufferParseTest2()
694{
695 uint8_t *pEncoded;
696 int nReturn;
697 size_t nEncodedLen;
698
699 int64_t i1, i2;
700 size_t i3, i4;
701 const uint8_t *s3, *s4;
702
703 nReturn = 0;
704
705 if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) {
706 return(-1);
707 }
708
709 //printencoded(pEncoded, nEncodedLen);
710
711 for(nEncodedLen--; nEncodedLen; nEncodedLen--) {
712 int nResult = ParseOrderedArray(pEncoded, (uint32_t)nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4);
713 if(nResult == 0) {
714 nReturn = -1;
715 }
716 }
717
718 return(nReturn);
719}
720
721
722
723static int ParseMapTest1()
724{
725 QCBORDecodeContext DCtx;
726 QCBORItem Item;
727 int nCBORError;
728
729
730 QCBORDecode_Init(&DCtx, (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, QCBOR_DECODE_MODE_NORMAL);
731
732 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
733 return nCBORError;
734 if(Item.uDataType != QCBOR_TYPE_MAP ||
735 Item.val.uCount != 3)
736 return -1;
737
738
739
740 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
741 return nCBORError;
742 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
743 Item.label.string.len != 13 ||
744 Item.uDataType != QCBOR_TYPE_INT64 ||
745 Item.val.int64 != 42 ||
746 memcmp(Item.label.string.ptr, "first integer", 13))
747 return -1;
748
749 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
750 return nCBORError;
751 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
752 Item.label.string.len != 23 ||
753 memcmp(Item.label.string.ptr, "an array of two strings", 23) ||
754 Item.uDataType != QCBOR_TYPE_ARRAY ||
755 Item.val.uCount != 2)
756 return -1;
757
758 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
759 return nCBORError;
760 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
761 Item.val.string.len != 7 ||
762 memcmp(Item.val.string.ptr, "string1", 7))
763 return -1;
764
765 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
766 return nCBORError;
767 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
768 Item.val.string.len != 7 ||
769 memcmp(Item.val.string.ptr, "string2", 7))
770 return -1;
771
772 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
773 return nCBORError;
774 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
775 Item.label.string.len != 12 ||
776 memcmp(Item.label.string.ptr, "map in a map", 12) ||
777 Item.uDataType != QCBOR_TYPE_MAP ||
778 Item.val.uCount != 4)
779 return -1;
780
781 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
782 return nCBORError;
783 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
784 Item.label.string.len != 7 ||
785 memcmp(Item.label.string.ptr, "bytes 1", 7)||
786 Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
787 Item.val.string.len != 4 ||
788 memcmp(Item.val.string.ptr, "xxxx", 4))
789 return -1;
790
791 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
792 return nCBORError;
793 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
794 Item.label.string.len != 7 ||
795 memcmp(Item.label.string.ptr, "bytes 2", 7) ||
796 Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
797 Item.val.string.len != 4 ||
798 memcmp(Item.val.string.ptr, "yyyy", 4))
799 return -1;
800
801 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
802 return nCBORError;
803 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
804 Item.label.string.len != 11 ||
805 memcmp(Item.label.string.ptr, "another int", 11) ||
806 Item.uDataType != QCBOR_TYPE_INT64 ||
807 Item.val.int64 != 98)
808 return -1;
809
810 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
811 return nCBORError;
812 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
813 Item.label.string.len != 6 ||
814 memcmp(Item.label.string.ptr, "text 2", 6)||
815 Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
816 Item.val.string.len != 30 ||
817 memcmp(Item.val.string.ptr, "lies, damn lies and statistics", 30))
818 return -1;
819
820 return 0;
821}
822
823
824
825/*
826 This test parses pValidMapEncoded and checks for extra bytes along the way
827 */
828static int ExtraBytesTest()
829{
830 QCBORDecodeContext DCtx;
831 QCBORItem Item;
832 int nCBORError;
833
834
835 QCBORDecode_Init(&DCtx, (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, QCBOR_DECODE_MODE_NORMAL);
836
837 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
838 return -1;
839 }
840
841 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
842 return nCBORError;
843 if(Item.uDataType != QCBOR_TYPE_MAP ||
844 Item.val.uCount != 3)
845 return -1;
846
847 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
848 return -1;
849 }
850
851 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
852 return nCBORError;
853 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
854 Item.label.string.len != 13 ||
855 Item.uDataType != QCBOR_TYPE_INT64 ||
856 Item.val.uCount != 42 ||
857 memcmp(Item.label.string.ptr, "first integer", 13))
858 return -1;
859
860 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
861 return -1;
862 }
863
864 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
865 return nCBORError;
866 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
867 Item.label.string.len != 23 ||
868 memcmp(Item.label.string.ptr, "an array of two strings", 23) ||
869 Item.uDataType != QCBOR_TYPE_ARRAY ||
870 Item.val.uCount != 2)
871 return -1;
872
873 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
874 return -1;
875 }
876
877
878 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
879 return nCBORError;
880 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
881 Item.val.string.len != 7 ||
882 memcmp(Item.val.string.ptr, "string1", 7))
883 return -1;
884
885 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
886 return -1;
887 }
888
889 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
890 return nCBORError;
891 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
892 Item.val.string.len != 7 ||
893 memcmp(Item.val.string.ptr, "string2", 7))
894 return -1;
895
896 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
897 return -1;
898 }
899
900 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
901 return nCBORError;
902 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
903 Item.label.string.len != 12 ||
904 memcmp(Item.label.string.ptr, "map in a map", 12) ||
905 Item.uDataType != QCBOR_TYPE_MAP ||
906 Item.val.uCount != 4)
907 return -1;
908
909 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
910 return -1;
911 }
912
913 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
914 return nCBORError;
915 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
916 Item.label.string.len != 7 ||
917 memcmp(Item.label.string.ptr, "bytes 1", 7)||
918 Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
919 Item.val.string.len != 4 ||
920 memcmp(Item.val.string.ptr, "xxxx", 4))
921 return -1;
922
923 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
924 return -1;
925 }
926
927 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
928 return nCBORError;
929 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
930 Item.label.string.len != 7 ||
931 memcmp(Item.label.string.ptr, "bytes 2", 7) ||
932 Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
933 Item.val.string.len != 4 ||
934 memcmp(Item.val.string.ptr, "yyyy", 4))
935 return -1;
936
937 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
938 return -1;
939 }
940
941 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
942 return nCBORError;
943 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
944 Item.label.string.len != 11 ||
945 memcmp(Item.label.string.ptr, "another int", 11) ||
946 Item.uDataType != QCBOR_TYPE_INT64 ||
947 Item.val.int64 != 98)
948 return -1;
949
950 if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) {
951 return -1;
952 }
953
954 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
955 return nCBORError;
956 if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
957 Item.label.string.len != 6 ||
958 memcmp(Item.label.string.ptr, "text 2", 6)||
959 Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
960 Item.val.string.len != 30 ||
961 memcmp(Item.val.string.ptr, "lies, damn lies and statistics", 30))
962 return -1;
963
964 if(QCBORDecode_Finish(&DCtx) == QCBOR_ERR_EXTRA_BYTES) {
965 return -1;
966 }
967
968 return 0;
969}
970
971
972
973
974int ParseMapTest()
975{
976 int n = ParseMapTest1();
977
978 if(!n) {
979 n = ExtraBytesTest();
980 }
981
982 return(n);
983}
984
985
986static uint8_t s_pSimpleValues[] = {0x8a, 0xf4, 0xf5, 0xf6, 0xf7, 0xff, 0xe0, 0xf3, 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff};
987
988int ParseSimpleTest()
989{
990 QCBORDecodeContext DCtx;
991 QCBORItem Item;
992 int nCBORError;
993
994
995 QCBORDecode_Init(&DCtx, ByteArrayLiteralToUsefulBufC(s_pSimpleValues), QCBOR_DECODE_MODE_NORMAL);
996
997
998 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
999 return nCBORError;
1000 if(Item.uDataType != QCBOR_TYPE_ARRAY ||
1001 Item.val.uCount != 10)
1002 return -1;
1003
1004 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1005 return nCBORError;
1006 if(Item.uDataType != QCBOR_TYPE_FALSE)
1007 return -1;
1008
1009 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1010 return nCBORError;
1011 if(Item.uDataType != QCBOR_TYPE_TRUE)
1012 return -1;
1013
1014 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1015 return nCBORError;
1016 if(Item.uDataType != QCBOR_TYPE_NULL)
1017 return -1;
1018
1019 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1020 return nCBORError;
1021 if(Item.uDataType != QCBOR_TYPE_UNDEF)
1022 return -1;
1023
1024 // A break
1025 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_UNSUPPORTED)
1026 return -1;
1027
1028 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1029 return nCBORError;
1030 if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 0)
1031 return -1;
1032
1033 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1034 return nCBORError;
1035 if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 19)
1036 return -1;
1037
1038 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR)
1039 return -1;
1040
1041 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR)
1042 return -1;
1043
1044 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR)
1045 return -1;
1046
1047 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1048 return nCBORError;
1049 if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 32)
1050 return -1;
1051
1052 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1053 return nCBORError;
1054 if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 255)
1055 return -1;
1056
1057 return 0;
1058
1059}
1060
1061
1062struct FailInput {
1063 UsefulBufC Input;
1064 int nError;
1065};
1066
1067
1068struct FailInput Failures[] = {
1069 { {(uint8_t[]){0x18}, 1}, QCBOR_ERR_HIT_END }, // 1 byte integer missing the byte
1070 { {(uint8_t[]){0x1c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
1071 { {(uint8_t[]){0x1d}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 29
1072 { {(uint8_t[]){0x1e}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 30
1073 { {(uint8_t[]){0x1f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length integer
1074 { {(uint8_t[]){0x3c}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte
1075 { {(uint8_t[]){0x3d}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte
1076 { {(uint8_t[]){0x3e}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte
1077 { {(uint8_t[]){0x3f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length negative integer
1078 { {(uint8_t[]){0x41}, 1}, QCBOR_ERR_HIT_END }, // Short byte string
1079 { {(uint8_t[]){0x5c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
1080 { {(uint8_t[]){0x5f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length byte string
1081 { {(uint8_t[]){0x61}, 1}, QCBOR_ERR_HIT_END }, // Short UTF-8 string
1082 { {(uint8_t[]){0x7c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
1083 { {(uint8_t[]){0x7f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length UTF-8 string
1084 { {(uint8_t[]){0xff}, 1}, QCBOR_ERR_UNSUPPORTED } , // break
1085 { {(uint8_t[]){0xf8, 0x00}, 2}, QCBOR_ERR_INVALID_CBOR }, // An invalid encoding of a simple type
1086 { {(uint8_t[]){0xf8, 0x1f}, 2}, QCBOR_ERR_INVALID_CBOR }, // An invalid encoding of a simple type
1087 { {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, // Text-based date, with an integer
1088 { {(uint8_t[]){0xc1, 0x41, 0x33}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // Epoch date, with an byte string
1089 { {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // tagged as both epoch and string dates
1090 { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG } // big num tagged an int, not a byte string
1091
1092};
1093
1094
1095void Dump(UsefulBufC Input, int x)
1096{
1097 char label[10];
1098
1099 sprintf(label, "%d", x);
1100
1101 printencoded(label, Input.ptr, Input.len);
1102}
1103
1104
1105int FailureTests()
1106{
1107 int nResult = 0;
1108
1109 struct FailInput *pFEnd = &Failures[0] + sizeof(Failures)/sizeof(struct FailInput);
1110
1111 for(struct FailInput *pF = &Failures[0]; pF < pFEnd ;pF++) {
1112 QCBORDecodeContext DCtx;
1113 QCBORItem Item;
1114 int nCBORError;
1115
1116 QCBORDecode_Init(&DCtx, pF->Input, QCBOR_DECODE_MODE_NORMAL);
1117
1118 while(1) {
1119 nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
1120 if(QCBOR_ERR_HIT_END == nCBORError) {
1121 break;
1122 }
1123 if(nCBORError != pF->nError) {
1124 nResult = 1;
1125 // Dump(pF->Input, nCBORError);
1126 break;
1127 }
1128 }
1129 }
1130
1131 {
1132 QCBORDecodeContext DCtx;
1133 QCBORItem Item;
1134 int nCBORError;
1135
1136 QCBORDecode_Init(&DCtx, ByteArrayLiteralToUsefulBufC(s_pSimpleValues), QCBOR_DECODE_MODE_NORMAL);
1137
1138 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1139 return nCBORError;
1140 if(Item.uDataType != QCBOR_TYPE_ARRAY ||
1141 Item.val.uCount != 10)
1142 return -1;
1143
1144 DCtx.InBuf.magic = 0; // Corrupt the UsefulInputBuf
1145
1146 nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
1147 if(nCBORError != QCBOR_ERR_HIT_END)
1148 return -1;
1149 }
1150
1151
1152 return nResult;
1153}
1154
1155
1156
1157
1158static void Recurser(uint8_t *pBuf, int nLen, int nLenMax)
1159{
1160
1161 if(nLen >= nLenMax) {
1162 return;
1163 }
1164
1165 //printf("__%d__%d__\n", nLen, nLenMax);
1166
1167 for(int i = 0; i < 256; i++) {
1168 pBuf[nLen] = i;
1169
1170 QCBORDecodeContext DCtx;
1171 QCBORItem Item;
1172 int nCBORError;
1173
1174 UsefulBufC Input = {pBuf, nLen+1};
1175
1176 QCBORDecode_Init(&DCtx, Input, QCBOR_DECODE_MODE_NORMAL);
1177
1178 while(1) {
1179 nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
1180 if(QCBOR_ERR_HIT_END == nCBORError) {
1181 break;
1182 }
1183 if(nCBORError != QCBOR_SUCCESS) {
1184 if(nCBORError != QCBOR_ERR_UNSUPPORTED && nCBORError != QCBOR_ERR_HIT_END && nCBORError != QCBOR_ERR_INVALID_CBOR) {
1185 //Dump(Input, nCBORError);
1186 }
1187 break;
1188 }
1189 }
1190 //Dump(Input, -1);
1191
1192
1193 Recurser(pBuf, nLen+1, nLenMax);
1194 }
1195}
1196
1197
1198/*
1199 Runs all possible input strings of a given length. This is set to 3 to make the test
1200 run in reasonable time.
1201 Main point of this test is to not crash.
1202 */
1203
1204int ComprehensiveInputTest()
1205{
1206 uint8_t pBuf[3]; // 3 keeps it running in reasonable time. 4 takes tens of minutes.
1207
1208 Recurser(pBuf, 0, sizeof(pBuf));
1209
1210 return 0;
1211}
1212
1213
1214static uint8_t s_DateTestInput[] = {
1215 0xc0, // tag for string date
1216 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string
1217
1218 0xc1, // tag for epoch date
1219 0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
1220
1221 0xc1, 0xcf, 0xd8, 0xee, // Epoch date with extra tags
1222 0x1a, 0x53, 0x72, 0x4E, 0x01,
1223
1224 0xc1, // tag for epoch date
1225 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer
1226
1227 0xc1, // tag for epoch date
1228 0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1
1229
1230 0xc1, // tag for epoch date
1231 0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large
1232
1233};
1234
1235
1236// have to check float expected only to within an epsilon
1237int CHECK_EXPECTED_DOUBLE(double val, double expected) {
1238
1239 double diff = val - expected;
1240
1241 diff = fabs(diff);
1242
1243 return diff > 0.0000001;
1244}
1245
1246
1247int DateParseTest()
1248{
1249 QCBORDecodeContext DCtx;
1250 QCBORItem Item;
1251 int nCBORError;
1252
1253 QCBORDecode_Init(&DCtx, ByteArrayLiteralToUsefulBufC(s_DateTestInput), QCBOR_DECODE_MODE_NORMAL);
1254
1255 // String date
1256 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1257 return -1;
1258 if(Item.uDataType != QCBOR_TYPE_DATE_STRING ||
1259 UsefulBuf_Compare(Item.val.dateString, SZLiteralToUsefulBufC("1985-04-12"))){
1260 return -1;
1261 }
1262
1263 // Epoch date
1264 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1265 return -1;
1266 if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
1267 Item.val.epochDate.nSeconds != 1400000000 ||
1268 Item.val.epochDate.fSecondsFraction != 0 ) {
1269 return -1;
1270 }
1271
1272 // Epoch date with extra tags
1273 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1274 return -1;
1275 if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
1276 Item.val.epochDate.nSeconds != 1400000001 ||
1277 Item.val.epochDate.fSecondsFraction != 0 ||
1278 Item.uTagBits != (0x02 | (0x01 << 0x0f)) ||
1279 Item.uTag != 0xee) {
1280 return -1;
1281 }
1282
1283 // Epoch date that is too large for our representation
1284 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
1285 return -1;
1286 }
1287
1288 // Epoch date in float format with fractional seconds
1289 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1290 return -1;
1291 if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
1292 Item.val.epochDate.nSeconds != 1 ||
1293 CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) {
1294 return -1;
1295 }
1296
1297 // Epoch date float that is too large for our representation
1298 if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
1299 return -1;
1300 }
1301
1302 // TODO: could use a few more tests with float, double, and half precsion and negative (but coverage is still pretty good)
1303
1304 return 0;
1305}
1306
1307
1308static uint8_t s_OptTestInput[] = {
1309 0xd9, 0xd9, 0xf7, // CBOR magic number
1310 0x81,
1311 0xd8, 62, // 62 is decimal intentionally
1312 0x00};
1313
1314int OptTagParseTest()
1315{
1316 QCBORDecodeContext DCtx;
1317 QCBORItem Item;
1318 int nCBORError;
1319
1320
1321 QCBORDecode_Init(&DCtx, ByteArrayLiteralToUsefulBufC(s_OptTestInput), QCBOR_DECODE_MODE_NORMAL);
1322
1323 //
1324 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1325 return -1;
1326 if(Item.uDataType != QCBOR_TYPE_ARRAY ||
1327 Item.uTagBits != QCBOR_TAGFLAG_CBOR_MAGIC) {
1328 return -1;
1329 }
1330
1331 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1332 return -1;
1333 if(Item.uDataType != QCBOR_TYPE_INT64 ||
1334 Item.uTagBits != (0x01LL << 62) ||
1335 Item.val.int64 != 0)
1336 return -1;
1337
1338 return 0;
1339}
1340
1341
1342
1343
1344static uint8_t s_BigNumInput[] = {
1345 0x83,
1346 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348 0xA4,
1349 0x63, 0x42, 0x4E, 0x2B,
1350 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1351 0x18, 0x40,
1352 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1353 0x63, 0x42, 0x4E, 0x2D,
1354 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x38, 0x3F,
1356 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1357
1358
1359static uint8_t sBigNum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1360
1361
1362int BignumParseTest()
1363{
1364 QCBORDecodeContext DCtx;
1365 QCBORItem Item;
1366 int nCBORError;
1367
1368 QCBORDecode_Init(&DCtx, ByteArrayLiteralToUsefulBufC(s_BigNumInput), QCBOR_DECODE_MODE_NORMAL);
1369
1370
1371 //
1372 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1373 return -1;
1374 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
1375 return -1;
1376 }
1377
1378 //
1379 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1380 return -1;
1381 if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
1382 UsefulBuf_Compare(Item.val.bigNum, ByteArrayLiteralToUsefulBufC(sBigNum))){
1383 return -1;
1384 }
1385
1386 //
1387 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1388 return -1;
1389 if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
1390 UsefulBuf_Compare(Item.val.bigNum, ByteArrayLiteralToUsefulBufC(sBigNum))){
1391 return -1;
1392 }
1393
1394 //
1395 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1396 return -1;
1397 if(Item.uDataType != QCBOR_TYPE_MAP) {
1398 return -1;
1399 }
1400
1401 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1402 return -1;
1403 if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
1404 Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
1405 UsefulBuf_Compare(Item.val.bigNum, ByteArrayLiteralToUsefulBufC(sBigNum))){
1406 return -1;
1407 }
1408
1409 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1410 return -1;
1411 if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
1412 Item.uLabelType != QCBOR_TYPE_INT64 ||
1413 Item.label.int64 != 64 ||
1414 UsefulBuf_Compare(Item.val.bigNum, ByteArrayLiteralToUsefulBufC(sBigNum))){
1415 return -1;
1416 }
1417
1418 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1419 return -1;
1420 if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
1421 Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
1422 UsefulBuf_Compare(Item.val.bigNum, ByteArrayLiteralToUsefulBufC(sBigNum))){
1423 return -1;
1424 }
1425
1426 if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
1427 return -1;
1428 if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
1429 Item.uLabelType != QCBOR_TYPE_INT64 ||
1430 Item.label.int64 != -64 ||
1431 UsefulBuf_Compare(Item.val.bigNum, ByteArrayLiteralToUsefulBufC(sBigNum))){
1432 return -1;
1433 }
1434
1435 return 0;
1436}
1437
1438
1439
1440static int CheckItemWithIntLabel(QCBORDecodeContext *pCtx, uint8_t uDataType, uint8_t uNestingLevel, int64_t nLabel, QCBORItem *pItem)
1441{
1442 QCBORItem Item;
1443 int nCBORError;
1444
1445 if((nCBORError = QCBORDecode_GetNext(pCtx, &Item))) return -1;
1446 if(Item.uDataType != uDataType) return -1;
1447 if(uNestingLevel > 0) {
1448 if(Item.uLabelType != QCBOR_TYPE_INT64 && Item.uLabelType != QCBOR_TYPE_UINT64) return -1;
1449 if(Item.uLabelType == QCBOR_TYPE_INT64) {
1450 if(Item.label.int64 != nLabel) return -1;
1451 } else {
1452 if(Item.label.uint64 != nLabel) return -1;
1453 }
1454 }
1455 if(Item.uNestingLevel != uNestingLevel) return -1;
1456
1457 if(pItem) {
1458 *pItem = Item;
1459 }
1460 return 0;
1461}
1462
1463
1464/*
1465// cbor.me decoded output
1466{
1467 -23: {
1468 -20: {
1469 -18: "Organization",
1470 -17: "SSG",
1471 -15: "Confusion",
1472 -16: "San Diego",
1473 -14: "US"
1474 },
1475 -19: {
1476 -11: {
1477 -9: -7
1478 },
1479 -10: '\u0001\u0002\u0003\u0004\u0005\u0006\a\b\t\n'
1480 }
1481 },
1482 -22: {
1483 -5: -3
1484 }
1485}
1486 */
1487
1488static uint8_t s_CSRInput[] = {
1489 0xa2, 0x36, 0xa2, 0x33, 0xa5, 0x31, 0x6c, 0x4f,
1490 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74,
1491 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47,
1492 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73,
1493 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e,
1494 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62,
1495 0x55, 0x53, 0x32, 0xa2, 0x2a, 0xa1, 0x28, 0x26,
1496 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
1497 0x07, 0x08, 0x09, 0x0a, 0x35, 0xa1, 0x24, 0x22};
1498
1499int NestedMapTest()
1500{
1501 QCBORDecodeContext DCtx;
1502
1503 QCBORDecode_Init(&DCtx, ByteArrayLiteralToUsefulBufC(s_CSRInput), QCBOR_DECODE_MODE_NORMAL);
1504
1505 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_MAP, 0, 0, NULL)) return -1;
1506
1507 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_MAP, 1, -23, NULL)) return -1;
1508
1509 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_MAP, 2, -20, NULL)) return -1;
1510
1511 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_TEXT_STRING, 3, -18, NULL)) return -1;
1512 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_TEXT_STRING, 3, -17, NULL)) return -1;
1513 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_TEXT_STRING, 3, -15, NULL)) return -1;
1514 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_TEXT_STRING, 3, -16, NULL)) return -1;
1515 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_TEXT_STRING, 3, -14, NULL)) return -1;
1516
1517 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_MAP, 2, -19, NULL)) return -1;
1518 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_MAP, 3, -11, NULL)) return -1;
1519
1520 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_INT64, 4, -9, NULL)) return -1;
1521 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_BYTE_STRING, 3, -10, NULL)) return -1;
1522
1523 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_MAP, 1, -22, NULL)) return -1;
1524 if(CheckItemWithIntLabel(&DCtx, QCBOR_TYPE_INT64, 2, -5, NULL)) return -1;
1525
1526 return 0;
1527}
1528
1529
1530
1531
1532
1533
1534