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