blob: 7e441cdc22f07aad064ac2d1a1a7fb28644160cf [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
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 Lundblade624405d2018-09-18 20:10:47 -070030/*==============================================================================
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 Lundbladeb69cad72018-09-13 11:09:01 -070056/*===================================================================================
57 FILE: qcbor_decode.c
58
59 DESCRIPTION: This file contains the implementation of QCBOR.
60
61 EDIT HISTORY FOR FILE:
62
63 This section contains comments describing changes made to the module.
64 Notice that changes are listed in reverse chronological order.
65
66 when who what, where, why
67 -------- ---- ---------------------------------------------------
68 02/04/17 llundbla Work on CPUs that don's require pointer alignment
69 by making use of changes in UsefulBuf
70 03/01/17 llundbla More data types; decoding improvements and fixes
71 11/13/16 llundbla Integrate most TZ changes back into github version.
72 09/30/16 gkanike Porting to TZ.
73 03/15/16 llundbla Initial Version.
74
75 =====================================================================================*/
76
77#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070078#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070079
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070080
81
82/*
83 Collection of functions to track the map and array nesting for decoding
84 */
85
86inline static int IsMapOrArray(uint8_t uDataType)
87{
88 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
89}
90
91inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
92{
93 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
94}
95
96inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
97{
98 if(!DecodeNesting_IsNested(pNesting))
99 return 0;
100
101 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
102}
103
104inline static void DecodeNesting_Decrement(QCBORDecodeNesting *pNesting, uint8_t uDataType)
105{
106 if(!DecodeNesting_IsNested(pNesting)) {
107 return; // at top level where there is no tracking
108 }
109
110 // Decrement
111 pNesting->pCurrent->uCount--;
112
113 // Pop up nesting levels if the counts at the levels is zero
114 while(0 == pNesting->pCurrent->uCount && DecodeNesting_IsNested(pNesting)) {
115 pNesting->pCurrent--;
116 }
117}
118
119inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uMajorType, int uCount)
120{
121 int nReturn = QCBOR_SUCCESS;
122
123 if(uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
124 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
125 goto Done;
126 }
127
128 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
129 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
130 goto Done;
131 }
132
133 pNesting->pCurrent++;
134
135 pNesting->pCurrent->uMajorType = uMajorType;
136 pNesting->pCurrent->uCount = uCount;
137
138Done:
139 return nReturn;;
140}
141
142inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
143{
144 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
145}
146
147inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
148{
149 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
150}
151
152
153
154
155/*
156 Public function, see header file
157 */
158void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
159{
160 memset(me, 0, sizeof(QCBORDecodeContext));
161 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
162 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
163 // if the default normal mode of 0 was set.
164 me->uDecodeMode = nDecodeMode;
165 DecodeNesting_Init(&(me->nesting));
166}
167
168
169/*
170 This decodes the fundamental part of a CBOR data item, the type and number
171
172 This is the Counterpart to InsertEncodedTypeAndNumber().
173
174 This does the network->host byte order conversion. The conversion here
175 also results in the conversion for floats in addition to that for
176 lengths, tags and integer values.
177
178 */
179inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
180{
181 int nReturn;
182
183 // Get the initial byte that every CBOR data item has
184 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
185
186 // Break down the initial byte
187 const uint8_t uTmpMajorType = InitialByte >> 5;
188 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
189
190 // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
191 // Also convert from network byte order. Call ntohxx on simple variables in case they are macros that
192 // reference their argument multiple times.
193 uint64_t uTmpValue;
194 switch(uAdditionalInfo) {
195
196 case LEN_IS_ONE_BYTE:
197 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
198 break;
199
200 case LEN_IS_TWO_BYTES:
201 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
202 break;
203
204 case LEN_IS_FOUR_BYTES:
205 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
206 break;
207
208 case LEN_IS_EIGHT_BYTES:
209 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
210 break;
211
212 case ADDINFO_RESERVED1: // reserved by CBOR spec
213 case ADDINFO_RESERVED2: // reserved by CBOR spec
214 case ADDINFO_RESERVED3: // reserved by CBOR spec
215 case LEN_IS_INDEFINITE: // indefinite types not supported (yet)
216 nReturn = QCBOR_ERR_UNSUPPORTED;
217 goto Done;
218
219 default:
220 uTmpValue = uAdditionalInfo;
221 break;
222 }
223
224 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
225 // There is no harm in this. This following check takes care of catching all of
226 // these errors.
227
228 if(UsefulInputBuf_GetError(pUInBuf)) {
229 nReturn = QCBOR_ERR_HIT_END;
230 goto Done;
231 }
232
233 // All successful if we got here.
234 nReturn = QCBOR_SUCCESS;
235 *pnMajorType = uTmpMajorType;
236 *puNumber = uTmpValue;
237 *puAdditionalInfo = uAdditionalInfo;
238
239Done:
240 return nReturn;
241}
242
243
244/*
245 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
246 use it these days and the test vectors in the RFC are so. All integers in the CBOR
247 structure are positive and the major type indicates positive or negative.
248 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
249 and negative integers down to 2^x. Note that negative numbers can be one
250 more away from zero than positive.
251 Stdint, as far as I can tell, uses two's compliment to represent
252 negative integers.
253
254 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
255 used here in any way including in the interface
256 */
257inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
258{
259 int nReturn = QCBOR_SUCCESS;
260
261 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
262 if (uNumber <= INT64_MAX) {
263 pDecodedItem->val.int64 = (int64_t)uNumber;
264 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
265
266 } else {
267 pDecodedItem->val.uint64 = uNumber;
268 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
269
270 }
271 } else {
272 if(uNumber <= INT64_MAX) {
273 pDecodedItem->val.int64 = -uNumber-1;
274 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
275
276 } else {
277 // C can't represent a negative integer in this range
278 // so it is an error. todo -- test this condition
279 nReturn = QCBOR_ERR_INT_OVERFLOW;
280 }
281 }
282
283 return nReturn;
284}
285
286// Make sure #define value line up as DecodeSimple counts on this.
287#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
288#error QCBOR_TYPE_FALSE macro value wrong
289#endif
290
291#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
292#error QCBOR_TYPE_TRUE macro value wrong
293#endif
294
295#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
296#error QCBOR_TYPE_NULL macro value wrong
297#endif
298
299#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
300#error QCBOR_TYPE_UNDEF macro value wrong
301#endif
302
303#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
304#error QCBOR_TYPE_DOUBLE macro value wrong
305#endif
306
307#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
308#error QCBOR_TYPE_FLOAT macro value wrong
309#endif
310
311/*
312 Decode true, false, floats, break...
313 */
314
315inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
316{
317 int nReturn = QCBOR_SUCCESS;
318
319 // uAdditionalInfo is 5 bits from the initial byte
320 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
321 pDecodedItem->uDataType = uAdditionalInfo;
322
323 switch(uAdditionalInfo) {
324 case ADDINFO_RESERVED1: // 28
325 case ADDINFO_RESERVED2: // 29
326 case ADDINFO_RESERVED3: // 30
327 case CBOR_SIMPLE_BREAK: // 31
328 nReturn = QCBOR_ERR_UNSUPPORTED;
329 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700330
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700331 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700332 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
333 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
334 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700335 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700336 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
337 break;
338 case DOUBLE_PREC_FLOAT:
339 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
340 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700341
342 case CBOR_SIMPLEV_FALSE: // 20
343 case CBOR_SIMPLEV_TRUE: // 21
344 case CBOR_SIMPLEV_NULL: // 22
345 case CBOR_SIMPLEV_UNDEF: // 23
346 break; // nothing to do
347
348 case CBOR_SIMPLEV_ONEBYTE: // 24
349 if(uNumber <= CBOR_SIMPLE_BREAK) {
350 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
351 nReturn = QCBOR_ERR_INVALID_CBOR;
352 goto Done;
353 }
354 // fall through intentionally
355
356 default: // 0-19
357 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
358 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
359 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
360 pDecodedItem->val.uSimple = (uint8_t)uNumber;
361 break;
362 }
363
364Done:
365 return nReturn;
366}
367
368
369
370/*
371 Decode text and byte strings
372 */
373inline static int DecodeBytes(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
374{
375 const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
376
377 int nReturn = QCBOR_ERR_HIT_END;
378
379 if(pBytes != NULL) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700380 pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
381 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700382 nReturn = QCBOR_SUCCESS;
383 }
384
385 return nReturn;
386}
387
388
389/*
390 Mostly just assign the right data type for the date string.
391 */
392inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
393{
394 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
395 return QCBOR_ERR_BAD_OPT_TAG;
396 }
397 pDecodedItem->val.dateString = Item.val.string;
398 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
399 pDecodedItem->uTagBits = Item.uTagBits;
400 pDecodedItem->uTag = Item.uTag;
401 return QCBOR_SUCCESS;
402}
403
404
405/*
406 Mostly just assign the right data type for the bignum.
407 */
408inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
409{
410 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
411 return QCBOR_ERR_BAD_OPT_TAG;
412 }
413 pDecodedItem->val.bigNum = Item.val.string;
414 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
415 pDecodedItem->uTagBits = Item.uTagBits;
416 pDecodedItem->uTag = Item.uTag;
417 return QCBOR_SUCCESS;
418}
419
420
421/*
422 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
423 */
424static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
425{
426 int nReturn = QCBOR_SUCCESS;
427
428 pDecodedItem->uTagBits = Item.uTagBits;
429 pDecodedItem->uTag = Item.uTag;
430 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
431 pDecodedItem->val.epochDate.fSecondsFraction = 0;
432
433 switch (Item.uDataType) {
434
435 case QCBOR_TYPE_INT64:
436 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
437 break;
438
439 case QCBOR_TYPE_UINT64:
440 if(Item.val.uint64 > INT64_MAX) {
441 nReturn = QCBOR_ERR_DATE_OVERFLOW;
442 goto Done;
443 }
444 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
445 break;
446
447 default:
448 nReturn = QCBOR_ERR_BAD_OPT_TAG;
449 }
450
451Done:
452 return nReturn;
453}
454
455
456/*
457 Decode the optional tagging that preceeds the real data value. There could be lots of them.
458 */
459static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional);
460
461/*
462 Returns an error if there was something wrong with the optional item or it couldn't
463 be handled.
464 */
465static int DecodeOptional(UsefulInputBuf *pUInBuf, uint64_t uInputTag, QCBORItem *pDecodedItem)
466{
467 int nReturn = QCBOR_SUCCESS;
468
469 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
470 uint64_t uTagToProcess = uInputTag; // First process tag passed in
471
472 QCBORItem Item;
473
474 do {
475 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
476 uTagFlags |= 0x01LL << uTagToProcess;
477 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
478 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
479 }
480 /* This code ignores the all but the first tag of value
481 greater than 63. Ignoring tags that are not understoof
482 is allowed by the standard. Multiple tags are
483 presumably rare. */
484
485 nReturn = GetAnItem(pUInBuf, &Item, 1);
486 if(nReturn) {
487 // Bail out of the whole item fetch on any sort of error here
488 goto Done;
489 }
490
491 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
492 break;
493 }
494
495 uTagToProcess = Item.uTag;
496 } while (1);
497
498
499 /*
500 CBOR allows multiple tags on a data item. It also defines
501 a number of standard tag values, most of which are
502 less than 64. This code can deal with multiple tag
503 values that are less than 64 and the last tag of multiple
504 if the value is more than 64. Or said another way
505 if there is one tag with a value >64 this code works.
506
507 The assumption is that multiple tag values > 64 are rare.
508
509 At this point in this code. uTagFlags has all the flags
510 < 64 and uTagToProcess has the last tag.
511
512 Does this deal with multiple tags on an item we process?
513 */
514
515 Item.uTagBits = uTagFlags;
516 Item.uTag = uTagToProcess;
517
518 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
519 case 0:
520 // No tags we know about. Pass them up
521 *pDecodedItem = Item;
522 break;
523
524 case QCBOR_TAGFLAG_DATE_STRING:
525 nReturn = DecodeDateString(Item, pDecodedItem);
526 break;
527
528 case QCBOR_TAGFLAG_DATE_EPOCH:
529 nReturn = DecodeDateEpoch(Item, pDecodedItem);
530 break;
531
532 case QCBOR_TAGFLAG_POS_BIGNUM:
533 case QCBOR_TAGFLAG_NEG_BIGNUM:
534 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
535 break;
536
537 default:
538 // Encountering some mixed up CBOR like something that
539 // is tagged as both a string and integer date.
540 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
541 }
542
543Done:
544 return nReturn;
545}
546
547
548
549// Make sure the constants align as this is assumed by the GetAnItem() implementation
550#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
551#error QCBOR_TYPE_ARRAY value not lined up with major type
552#endif
553#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
554#error QCBOR_TYPE_MAP value not lined up with major type
555#endif
556
557/*
558 This gets a single data item and decodes it including preceding optional tagging. This does not
559 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
560 maps are handled at the next level up in GetNext().
561
562 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
563 a few forms of invalid encoded CBOR
564 */
565
566static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional)
567{
568 int nReturn;
569
570 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
571 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
572 int uMajorType;
573 uint64_t uNumber;
574 uint8_t uAdditionalInfo;
575
576 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
577
578 // Error out here if we got into trouble on the type and number.
579 // The code after this will not work if the type and number is not good.
580 if(nReturn)
581 goto Done;
582
583 pDecodedItem->uTagBits = 0;
584 pDecodedItem->uTag = 0;
585
586 // At this point the major type and the value are valid. We've got the type and the number that
587 // starts every CBOR data item.
588 switch (uMajorType) {
589 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
590 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
591 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
592 break;
593
594 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
595 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
596 nReturn = DecodeBytes(uMajorType, uNumber, pUInBuf, pDecodedItem);
597 break;
598
599 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
600 case CBOR_MAJOR_TYPE_MAP: // Major type 5
601 // Record the number of items in the array or map
602 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
603 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
604 goto Done;
605 }
606 pDecodedItem->val.uCount = uNumber; // type conversion OK because of check above
607 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
608 break;
609
610 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
611 pDecodedItem->uTag = uNumber;
612 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
613 if(!bCalledFromDecodeOptional) {
614 // There can be a more than one optional tag in front of an actual data item
615 // they are all handled by looping in DecodeOptional which calls back here
616 // this test avoids infinite recursion.
617 nReturn = DecodeOptional(pUInBuf, uNumber, pDecodedItem);
618 }
619 break;
620
621 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
622 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
623 break;
624
625 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
626 nReturn = QCBOR_ERR_UNSUPPORTED;
627 break;
628 }
629
630Done:
631 return nReturn;
632}
633
634
635/*
636 Public function, see header qcbor.h file
637 */
638int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
639{
640 int nReturn;
641
642 if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
643 nReturn = QCBOR_ERR_HIT_END;
644 goto Done;
645 }
646
647 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
648 if(nReturn)
649 goto Done;
650
651 // If in a map and the right decoding mode, get the label
652 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
653 // In a map and caller wants maps decoded, not treated as arrays
654
655 // Get the next item which will be the real data; Item will be the label
656 QCBORItem LabelItem = *pDecodedItem;
657 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
658 if(nReturn)
659 goto Done;
660
661 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
662 // strings are always good labels
663 pDecodedItem->label.string = LabelItem.val.string;
664 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
665 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
666 // It's not a string and we only want strings, probably for easy translation to JSON
667 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
668 goto Done;
669 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
670 pDecodedItem->label.int64 = LabelItem.val.int64;
671 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
672 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
673 pDecodedItem->label.uint64 = LabelItem.val.uint64;
674 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
675 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
676 pDecodedItem->label.string = LabelItem.val.string;
677 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
678 } else {
679 // label is not an int or a string. It is an arrray
680 // or a float or such and this implementation doesn't handle that.
681 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
682 goto Done;
683 }
684 }
685
686 // Record the nesting level for this data item
687 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
688
689 // If the new item is a non-empty array or map, the nesting level descends
690 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount) {
691 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount);
692 } else {
693 // Track number of items in maps and arrays and ascend nesting if all are consumed
694 // Note that an empty array or map is like a integer or string in effect here
695 DecodeNesting_Decrement(&(me->nesting), pDecodedItem->uDataType);
696 }
697
698Done:
699 return nReturn;
700}
701
702
703/*
704 Public function, see header qcbor.h file
705 */
706int QCBORDecode_Finish(QCBORDecodeContext *me)
707{
708 return UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) ? QCBOR_ERR_EXTRA_BYTES : QCBOR_SUCCESS;
709}
710
711
712
713/*
714
715Decoder errors handled in this file
716
717 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
718
719 - indefinite length, currently not supported QCBOR_ERR_UNSUPPORTED
720
721 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
722
723 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
724
725 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
726
727 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
728
729 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
730
731 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
732
733 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
734
735 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
736
737 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
738
739 */
740