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