blob: a02a06ea3ff12c579389e8256fe682d88c03393b [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
Laurence Lundblade7023b952018-10-02 01:54:24 -0700194const QCBORStringAllocator *QCBORDecode_GetAllocator(QCBORDecodeContext *pCtx)
195{
196 return pCtx->pStringAllocator;
197}
198
199
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700200
201/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700202 This decodes the fundamental part of a CBOR data item, the type and number
203
204 This is the Counterpart to InsertEncodedTypeAndNumber().
205
206 This does the network->host byte order conversion. The conversion here
207 also results in the conversion for floats in addition to that for
208 lengths, tags and integer values.
209
210 */
211inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
212{
213 int nReturn;
214
215 // Get the initial byte that every CBOR data item has
216 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
217
218 // Break down the initial byte
219 const uint8_t uTmpMajorType = InitialByte >> 5;
220 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
221
222 // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
223 // Also convert from network byte order. Call ntohxx on simple variables in case they are macros that
224 // reference their argument multiple times.
225 uint64_t uTmpValue;
226 switch(uAdditionalInfo) {
227
228 case LEN_IS_ONE_BYTE:
229 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
230 break;
231
232 case LEN_IS_TWO_BYTES:
233 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
234 break;
235
236 case LEN_IS_FOUR_BYTES:
237 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
238 break;
239
240 case LEN_IS_EIGHT_BYTES:
241 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
242 break;
243
244 case ADDINFO_RESERVED1: // reserved by CBOR spec
245 case ADDINFO_RESERVED2: // reserved by CBOR spec
246 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247 nReturn = QCBOR_ERR_UNSUPPORTED;
248 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700249
250 case LEN_IS_INDEFINITE:
251 // Fall through OK to see what happens: TODO: check this.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700252 default:
253 uTmpValue = uAdditionalInfo;
254 break;
255 }
256
257 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
258 // There is no harm in this. This following check takes care of catching all of
259 // these errors.
260
261 if(UsefulInputBuf_GetError(pUInBuf)) {
262 nReturn = QCBOR_ERR_HIT_END;
263 goto Done;
264 }
265
266 // All successful if we got here.
267 nReturn = QCBOR_SUCCESS;
268 *pnMajorType = uTmpMajorType;
269 *puNumber = uTmpValue;
270 *puAdditionalInfo = uAdditionalInfo;
271
272Done:
273 return nReturn;
274}
275
276
277/*
278 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
279 use it these days and the test vectors in the RFC are so. All integers in the CBOR
280 structure are positive and the major type indicates positive or negative.
281 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
282 and negative integers down to 2^x. Note that negative numbers can be one
283 more away from zero than positive.
284 Stdint, as far as I can tell, uses two's compliment to represent
285 negative integers.
286
287 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
288 used here in any way including in the interface
289 */
290inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
291{
292 int nReturn = QCBOR_SUCCESS;
293
294 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
295 if (uNumber <= INT64_MAX) {
296 pDecodedItem->val.int64 = (int64_t)uNumber;
297 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
298
299 } else {
300 pDecodedItem->val.uint64 = uNumber;
301 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
302
303 }
304 } else {
305 if(uNumber <= INT64_MAX) {
306 pDecodedItem->val.int64 = -uNumber-1;
307 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
308
309 } else {
310 // C can't represent a negative integer in this range
311 // so it is an error. todo -- test this condition
312 nReturn = QCBOR_ERR_INT_OVERFLOW;
313 }
314 }
315
316 return nReturn;
317}
318
319// Make sure #define value line up as DecodeSimple counts on this.
320#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
321#error QCBOR_TYPE_FALSE macro value wrong
322#endif
323
324#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
325#error QCBOR_TYPE_TRUE macro value wrong
326#endif
327
328#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
329#error QCBOR_TYPE_NULL macro value wrong
330#endif
331
332#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
333#error QCBOR_TYPE_UNDEF macro value wrong
334#endif
335
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700336#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
337#error QCBOR_TYPE_BREAK macro value wrong
338#endif
339
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700340#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
341#error QCBOR_TYPE_DOUBLE macro value wrong
342#endif
343
344#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
345#error QCBOR_TYPE_FLOAT macro value wrong
346#endif
347
348/*
349 Decode true, false, floats, break...
350 */
351
352inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
353{
354 int nReturn = QCBOR_SUCCESS;
355
356 // uAdditionalInfo is 5 bits from the initial byte
357 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
358 pDecodedItem->uDataType = uAdditionalInfo;
359
360 switch(uAdditionalInfo) {
361 case ADDINFO_RESERVED1: // 28
362 case ADDINFO_RESERVED2: // 29
363 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700364 nReturn = QCBOR_ERR_UNSUPPORTED;
365 break;
366
367 case CBOR_SIMPLEV_FALSE: // 20
368 case CBOR_SIMPLEV_TRUE: // 21
369 case CBOR_SIMPLEV_NULL: // 22
370 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700371 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700372 break; // nothing to do
373
374 case CBOR_SIMPLEV_ONEBYTE: // 24
375 if(uNumber <= CBOR_SIMPLE_BREAK) {
376 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
377 nReturn = QCBOR_ERR_INVALID_CBOR;
378 goto Done;
379 }
380 // fall through intentionally
381
382 default: // 0-19
383 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
384 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
385 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
386 pDecodedItem->val.uSimple = (uint8_t)uNumber;
387 break;
388 }
389
390Done:
391 return nReturn;
392}
393
394
395
396/*
397 Decode text and byte strings
398 */
399inline static int DecodeBytes(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
400{
401 const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
402
403 int nReturn = QCBOR_ERR_HIT_END;
404
405 if(pBytes != NULL) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700406 pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
407 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700408 nReturn = QCBOR_SUCCESS;
409 }
410
411 return nReturn;
412}
413
414
415/*
416 Mostly just assign the right data type for the date string.
417 */
418inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
419{
420 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
421 return QCBOR_ERR_BAD_OPT_TAG;
422 }
423 pDecodedItem->val.dateString = Item.val.string;
424 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
425 pDecodedItem->uTagBits = Item.uTagBits;
426 pDecodedItem->uTag = Item.uTag;
427 return QCBOR_SUCCESS;
428}
429
430
431/*
432 Mostly just assign the right data type for the bignum.
433 */
434inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
435{
436 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
437 return QCBOR_ERR_BAD_OPT_TAG;
438 }
439 pDecodedItem->val.bigNum = Item.val.string;
440 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
441 pDecodedItem->uTagBits = Item.uTagBits;
442 pDecodedItem->uTag = Item.uTag;
443 return QCBOR_SUCCESS;
444}
445
446
447/*
448 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
449 */
450static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
451{
452 int nReturn = QCBOR_SUCCESS;
453
454 pDecodedItem->uTagBits = Item.uTagBits;
455 pDecodedItem->uTag = Item.uTag;
456 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
457 pDecodedItem->val.epochDate.fSecondsFraction = 0;
458
459 switch (Item.uDataType) {
460
461 case QCBOR_TYPE_INT64:
462 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
463 break;
464
465 case QCBOR_TYPE_UINT64:
466 if(Item.val.uint64 > INT64_MAX) {
467 nReturn = QCBOR_ERR_DATE_OVERFLOW;
468 goto Done;
469 }
470 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
471 break;
472
473 default:
474 nReturn = QCBOR_ERR_BAD_OPT_TAG;
475 }
476
477Done:
478 return nReturn;
479}
480
481
482/*
483 Decode the optional tagging that preceeds the real data value. There could be lots of them.
484 */
485static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional);
486
487/*
488 Returns an error if there was something wrong with the optional item or it couldn't
489 be handled.
490 */
491static int DecodeOptional(UsefulInputBuf *pUInBuf, uint64_t uInputTag, QCBORItem *pDecodedItem)
492{
493 int nReturn = QCBOR_SUCCESS;
494
495 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
496 uint64_t uTagToProcess = uInputTag; // First process tag passed in
497
498 QCBORItem Item;
499
500 do {
501 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
502 uTagFlags |= 0x01LL << uTagToProcess;
503 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
504 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
505 }
506 /* This code ignores the all but the first tag of value
507 greater than 63. Ignoring tags that are not understoof
508 is allowed by the standard. Multiple tags are
509 presumably rare. */
510
511 nReturn = GetAnItem(pUInBuf, &Item, 1);
512 if(nReturn) {
513 // Bail out of the whole item fetch on any sort of error here
514 goto Done;
515 }
516
517 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
518 break;
519 }
520
521 uTagToProcess = Item.uTag;
522 } while (1);
523
524
525 /*
526 CBOR allows multiple tags on a data item. It also defines
527 a number of standard tag values, most of which are
528 less than 64. This code can deal with multiple tag
529 values that are less than 64 and the last tag of multiple
530 if the value is more than 64. Or said another way
531 if there is one tag with a value >64 this code works.
532
533 The assumption is that multiple tag values > 64 are rare.
534
535 At this point in this code. uTagFlags has all the flags
536 < 64 and uTagToProcess has the last tag.
537
538 Does this deal with multiple tags on an item we process?
539 */
540
541 Item.uTagBits = uTagFlags;
542 Item.uTag = uTagToProcess;
543
544 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
545 case 0:
546 // No tags we know about. Pass them up
547 *pDecodedItem = Item;
548 break;
549
550 case QCBOR_TAGFLAG_DATE_STRING:
551 nReturn = DecodeDateString(Item, pDecodedItem);
552 break;
553
554 case QCBOR_TAGFLAG_DATE_EPOCH:
555 nReturn = DecodeDateEpoch(Item, pDecodedItem);
556 break;
557
558 case QCBOR_TAGFLAG_POS_BIGNUM:
559 case QCBOR_TAGFLAG_NEG_BIGNUM:
560 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
561 break;
562
563 default:
564 // Encountering some mixed up CBOR like something that
565 // is tagged as both a string and integer date.
566 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
567 }
568
569Done:
570 return nReturn;
571}
572
573
574
575// Make sure the constants align as this is assumed by the GetAnItem() implementation
576#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
577#error QCBOR_TYPE_ARRAY value not lined up with major type
578#endif
579#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
580#error QCBOR_TYPE_MAP value not lined up with major type
581#endif
582
583/*
584 This gets a single data item and decodes it including preceding optional tagging. This does not
585 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
586 maps are handled at the next level up in GetNext().
587
588 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
589 a few forms of invalid encoded CBOR
590 */
591
592static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional)
593{
594 int nReturn;
595
596 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
597 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
598 int uMajorType;
599 uint64_t uNumber;
600 uint8_t uAdditionalInfo;
601
602 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
603
604 // Error out here if we got into trouble on the type and number.
605 // The code after this will not work if the type and number is not good.
606 if(nReturn)
607 goto Done;
608
609 pDecodedItem->uTagBits = 0;
610 pDecodedItem->uTag = 0;
611
612 // At this point the major type and the value are valid. We've got the type and the number that
613 // starts every CBOR data item.
614 switch (uMajorType) {
615 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
616 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundblade4c34c002018-09-30 21:50:08 -0700617 if(uAdditionalInfo == 31) {// TODO: right constant
618 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
619 pDecodedItem->val.string = (UsefulBufC){NULL, 0xffff};
620 } else {
621 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
622 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 break;
624
625 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
626 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
627 nReturn = DecodeBytes(uMajorType, uNumber, pUInBuf, pDecodedItem);
628 break;
629
630 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
631 case CBOR_MAJOR_TYPE_MAP: // Major type 5
632 // Record the number of items in the array or map
633 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
634 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
635 goto Done;
636 }
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700637 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
638 pDecodedItem->val.uCount = UINT16_MAX;
639 } else {
640 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
641 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
643 break;
644
645 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
646 pDecodedItem->uTag = uNumber;
647 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
648 if(!bCalledFromDecodeOptional) {
649 // There can be a more than one optional tag in front of an actual data item
650 // they are all handled by looping in DecodeOptional which calls back here
651 // this test avoids infinite recursion.
652 nReturn = DecodeOptional(pUInBuf, uNumber, pDecodedItem);
653 }
654 break;
655
656 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
657 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
658 break;
659
660 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
661 nReturn = QCBOR_ERR_UNSUPPORTED;
662 break;
663 }
664
665Done:
666 return nReturn;
667}
668
669
670/*
Laurence Lundblade4c34c002018-09-30 21:50:08 -0700671 Layer to process indefinite lengths
672
673 */
674
675UsefulBuf XX(QCBORStringAllocator *pAlloc, UsefulBufC yy, size_t add)
676{
Laurence Lundblade4c34c002018-09-30 21:50:08 -0700677 // TODO: pointer arithmatic
Laurence Lundblade7023b952018-10-02 01:54:24 -0700678 uint8_t *x = (*pAlloc->AllocatorFunction) (pAlloc->pAllocaterContext, yy.ptr, yy.len + add );
Laurence Lundblade4c34c002018-09-30 21:50:08 -0700679 return (UsefulBuf) {x, yy.len + add};
680}
681
682int GetFullItem(QCBORStringAllocator *pAlloc, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional)
683{
684 int nReturn = GetAnItem(pUInBuf, pDecodedItem, bCalledFromDecodeOptional);
685
686 if(pDecodedItem->uDataType != CBOR_MAJOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != CBOR_MAJOR_TYPE_TEXT_STRING) {
687 return nReturn;
688 }
689
690 if(pDecodedItem->val.uCount != 0xffff) {
691 return nReturn;
692 }
693
694 if(pAlloc == NULL) {
695 return -99; // TODO: error
696 }
697
698 QCBORItem Item = *pDecodedItem;
699 UsefulOutBuf UOB;
700 UsefulOutBuf_Init(&UOB, XX(pAlloc, (UsefulBufC){NULL,0}, 0)); // Dummy storage allocation to start
701
702 // loop getting segments of indefinite string
703
704 do {
705 UsefulOutBuf_Realloc(&UOB, XX(pAlloc, UsefulOutBuf_OutUBuf(&UOB), Item.val.string.len));
706 UsefulOutBuf_AppendUsefulBuf(&UOB, Item.val.string);
707
708 int xx = GetAnItem(pUInBuf, &Item, bCalledFromDecodeOptional);
709 // Lots of error conditions here
710
711 } while(Item.uDataType != QCBOR_TYPE_BREAK);
712
713 pDecodedItem->val.string = UsefulOutBuf_OutUBuf(&UOB);
714
715 return 0;
716
717}
718
719
720/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 Public function, see header qcbor.h file
722 */
723int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
724{
725 int nReturn;
726
727 if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
728 nReturn = QCBOR_ERR_HIT_END;
729 goto Done;
730 }
731
732 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
733 if(nReturn)
734 goto Done;
735
736 // If in a map and the right decoding mode, get the label
737 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
738 // In a map and caller wants maps decoded, not treated as arrays
739
740 // Get the next item which will be the real data; Item will be the label
741 QCBORItem LabelItem = *pDecodedItem;
742 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
743 if(nReturn)
744 goto Done;
745
746 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
747 // strings are always good labels
748 pDecodedItem->label.string = LabelItem.val.string;
749 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
750 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
751 // It's not a string and we only want strings, probably for easy translation to JSON
752 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
753 goto Done;
754 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
755 pDecodedItem->label.int64 = LabelItem.val.int64;
756 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
757 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
758 pDecodedItem->label.uint64 = LabelItem.val.uint64;
759 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
760 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
761 pDecodedItem->label.string = LabelItem.val.string;
762 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
763 } else {
764 // label is not an int or a string. It is an arrray
765 // or a float or such and this implementation doesn't handle that.
766 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
767 goto Done;
768 }
769 }
770
771 // Record the nesting level for this data item
772 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
773
774 // If the new item is a non-empty array or map, the nesting level descends
775 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount) {
776 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount);
777 } else {
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700778 if(!IsIndefiniteLength(&(me->nesting))) {
779 // Is a definite length array or map
780 // Track number of items in maps and arrays and ascend nesting if all are consumed
781 // Note that an empty array or map is like a integer or string in effect here
782 DecodeNesting_Decrement(&(me->nesting));
783 } else {
784 // Is an indefinite length array or map
785 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
786 // Only decrement when the end is encountered.
787 DecodeNesting_Decrement(&(me->nesting));
788 // TODO: get another item here....
789 }
790 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791 }
792
793Done:
794 return nReturn;
795}
796
797
798/*
799 Public function, see header qcbor.h file
800 */
801int QCBORDecode_Finish(QCBORDecodeContext *me)
802{
803 return UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) ? QCBOR_ERR_EXTRA_BYTES : QCBOR_SUCCESS;
804}
805
806
807
Laurence Lundblade7023b952018-10-02 01:54:24 -0700808/*
809
810 Use the 64-bit map. 48 8-bit tags built in, 1 16 bit tag, 15 64-bit tags can be assigned as of interest
811
812 There is a tag map.
813
814 TODO: how does tinyCBOR do it?
815
816
817
818
819
820 */
821
822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823/*
824
825Decoder errors handled in this file
826
827 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
828
829 - indefinite length, currently not supported QCBOR_ERR_UNSUPPORTED
830
831 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
832
833 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
834
835 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
836
837 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
838
839 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
840
841 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
842
843 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
844
845 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
846
847 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
848
849 */
850