xref: /optee_os/core/lib/qcbor/src/qcbor_decode.c (revision b586599be35c4311337a5d8db5f4b5e5c81a754d)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*==============================================================================
3  Copyright (c) 2016-2018, The Linux Foundation.
4  Copyright (c) 2018-2024, Laurence Lundblade.
5  Copyright (c) 2021, Arm Limited.
6  All rights reserved.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11     * Redistributions of source code must retain the above copyright
12       notice, this list of conditions and the following disclaimer.
13     * Redistributions in binary form must reproduce the above
14       copyright notice, this list of conditions and the following
15       disclaimer in the documentation and/or other materials provided
16       with the distribution.
17     * Neither the name of The Linux Foundation nor the names of its
18       contributors, nor the name "Laurence Lundblade" may be used to
19       endorse or promote products derived from this software without
20       specific prior written permission.
21 
22 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
23 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
25 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
26 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  =============================================================================*/
34 
35 
36 #include "qcbor/qcbor_decode.h"
37 #include "qcbor/qcbor_spiffy_decode.h"
38 #include "ieee754.h" /* Does not use math.h */
39 
40 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
41 
42 #include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
43                    * pow(), exp2()
44                    */
45 #include <fenv.h> /* feclearexcept(), fetestexcept() */
46 
47 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
48 
49 
50 #if (defined(__GNUC__) && !defined(__clang__))
51 /*
52  * This is how the -Wmaybe-uninitialized compiler warning is
53  * handled. It can’t be ignored because some version of gcc enable it
54  * with -Wall which is a common and useful gcc warning option. It also
55  * can’t be ignored because it is the goal of QCBOR to compile clean
56  * out of the box in all environments.
57  *
58  * The big problem with -Wmaybe-uninitialized is that it generates
59  * false positives. It complains things are uninitialized when they
60  * are not. This is because it is not a thorough static analyzer. This
61  * is why “maybe” is in its name. The problem is it is just not
62  * thorough enough to understand all the code (and someone saw fit to
63  * put it in gcc and worse to enable it with -Wall).
64  *
65  * One solution would be to change the code so -Wmaybe-uninitialized
66  * doesn’t get confused, for example adding an unnecessary extra
67  * initialization to zero. (If variables were truly uninitialized, the
68  * correct path is to understand the code thoroughly and set them to
69  * the correct value at the correct time; in essence this is already
70  * done; -Wmaybe-uninitialized just can’t tell). This path is not
71  * taken because it makes the code bigger and is kind of the tail
72  * wagging the dog.
73  *
74  * The solution here is to just use a pragma to disable it for the
75  * whole file. Disabling it for each line makes the code fairly ugly
76  * requiring #pragma to push, pop and ignore. Another reason is the
77  * warnings issues vary by version of gcc and which optimization
78  * optimizations are selected. Another reason is that compilers other
79  * than gcc don’t have -Wmaybe-uninitialized.
80  *
81  * One may ask how to be sure these warnings are false positives and
82  * not real issues. 1) The code has been read carefully to check. 2)
83  * Testing is pretty thorough. 3) This code has been run through
84  * thorough high-quality static analyzers.
85  *
86  * In particularly, most of the warnings are about
87  * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
88  * *always* sets this value and test case confirm
89  * this. -Wmaybe-uninitialized just can't tell.
90  *
91  * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
92  */
93 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
94 #endif
95 
96 
97 
98 
99 #define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
100 
101 
102 
103 
104 static bool
QCBORItem_IsMapOrArray(const QCBORItem Item)105 QCBORItem_IsMapOrArray(const QCBORItem Item)
106 {
107    const uint8_t uDataType = Item.uDataType;
108    return uDataType == QCBOR_TYPE_MAP ||
109 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
110           uDataType == QCBOR_TYPE_MAP_AS_ARRAY ||
111 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
112           uDataType == QCBOR_TYPE_ARRAY;
113 }
114 
115 static bool
QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)116 QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)
117 {
118    if(!QCBORItem_IsMapOrArray(Item)){
119       return false;
120    }
121 
122    if(Item.val.uCount != 0) {
123       return false;
124    }
125    return true;
126 }
127 
128 static bool
QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)129 QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)
130 {
131 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
132    if(!QCBORItem_IsMapOrArray(Item)){
133       return false;
134    }
135 
136    if(Item.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
137       return false;
138    }
139    return true;
140 #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
141    (void)Item;
142    return false;
143 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
144 }
145 
146 /* Return true if the labels in Item1 and Item2 are the same.
147    Works only for integer and string labels. Returns false
148    for any other type. */
149 static bool
QCBORItem_MatchLabel(const QCBORItem Item1,const QCBORItem Item2)150 QCBORItem_MatchLabel(const QCBORItem Item1, const QCBORItem Item2)
151 {
152    if(Item1.uLabelType == QCBOR_TYPE_INT64) {
153       if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
154          return true;
155       }
156 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
157    } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
158       if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
159          return true;
160       }
161    } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
162       if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
163          return true;
164       }
165    } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
166       if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
167          return true;
168       }
169 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
170    }
171 
172    /* Other label types are never matched */
173    return false;
174 }
175 
176 
177 /*
178  Returns true if Item1 and Item2 are the same type
179  or if either are of QCBOR_TYPE_ANY.
180  */
181 static bool
QCBORItem_MatchType(const QCBORItem Item1,const QCBORItem Item2)182 QCBORItem_MatchType(const QCBORItem Item1, const QCBORItem Item2)
183 {
184    if(Item1.uDataType == Item2.uDataType) {
185       return true;
186    } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
187       return true;
188    } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
189       return true;
190    }
191    return false;
192 }
193 
194 
195 /*===========================================================================
196    DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
197   ===========================================================================*/
198 
199 /*
200  * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
201  * the data structure all these functions work on.
202  */
203 
204 
205 static uint8_t
DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting * pNesting)206 DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
207 {
208    const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
209    /* Limit in DecodeNesting_Descend against more than
210     * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
211     */
212    return (uint8_t)nLevel;
213 }
214 
215 
216 static uint8_t
DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting * pNesting)217 DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
218 {
219    const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
220    /* Limit in DecodeNesting_Descend against more than
221     * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
222     */
223    return (uint8_t)nLevel;
224 }
225 
226 
227 static uint32_t
DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting * pNesting)228 DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
229 {
230    return pNesting->pCurrentBounded->u.ma.uStartOffset;
231 }
232 
233 
234 static bool
DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting * pNesting)235 DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
236 {
237    if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
238       return true;
239    } else {
240       return false;
241    }
242 }
243 
244 
245 static bool
DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting * pNesting)246 DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
247 {
248    if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
249       return true;
250    } else {
251       return false;
252    }
253 }
254 
255 
256 static bool
DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting * pNesting)257 DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
258 {
259    if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
260       /* Not a map or array */
261       return false;
262    }
263 
264 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
265    if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
266       /* Is indefinite */
267       return false;
268    }
269 
270 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
271 
272    /* All checks passed; is a definte length map or array */
273    return true;
274 }
275 
276 static bool
DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting * pNesting)277 DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
278 {
279    if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
280       /* is a byte string */
281       return true;
282    }
283    return false;
284 }
285 
286 
287 static bool
DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting * pNesting)288 DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
289 {
290    if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
291       return true;
292    }
293    if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
294       return true;
295    }
296    return false;
297 }
298 
299 
300 static void
DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting * pNesting,bool bIsEmpty,size_t uStart)301 DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
302 {
303    /* Should be only called on maps and arrays */
304    /*
305     * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
306     * larger than DecodeNesting_EnterBoundedMode which keeps it less than
307     * uin32_t so the cast is safe.
308     */
309    pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
310 
311    if(bIsEmpty) {
312       pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
313    }
314 }
315 
316 
317 static void
DecodeNesting_ClearBoundedMode(QCBORDecodeNesting * pNesting)318 DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
319 {
320    pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
321 }
322 
323 
324 static bool
DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting * pNesting)325 DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
326 {
327    if(pNesting->pCurrentBounded == NULL) {
328       /* No bounded map or array set up */
329       return false;
330    }
331    if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
332       /* Not a map or array; end of those is by byte count */
333       return false;
334    }
335    if(!DecodeNesting_IsCurrentBounded(pNesting)) {
336       /* In a traveral at a level deeper than the bounded level */
337       return false;
338    }
339    /* Works for both definite- and indefinitelength maps/arrays */
340    if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
341       pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
342       /* Count is not zero, still unconsumed item */
343       return false;
344    }
345    /* All checks passed, got to the end of an array or map*/
346    return true;
347 }
348 
349 
350 static bool
DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting * pNesting)351 DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
352 {
353    /* Must only be called on map / array */
354    if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
355       return true;
356    } else {
357       return false;
358    }
359 }
360 
361 
362 static bool
DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting * pNesting)363 DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
364 {
365    if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
366       return true;
367    } else {
368       return false;
369    }
370 }
371 
372 
373 static bool
DecodeNesting_IsBoundedType(const QCBORDecodeNesting * pNesting,uint8_t uType)374 DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
375 {
376    if(pNesting->pCurrentBounded == NULL) {
377       return false;
378    }
379 
380    uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
381 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
382    if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
383       uItemDataType = QCBOR_TYPE_ARRAY;
384    }
385 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
386 
387    if(uItemDataType != uType) {
388       return false;
389    }
390 
391    return true;
392 }
393 
394 
395 static void
DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting * pNesting)396 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
397 {
398    /* Only call on a definite-length array / map */
399    pNesting->pCurrent->u.ma.uCountCursor--;
400 }
401 
402 
403 static void
DecodeNesting_ReverseDecrement(QCBORDecodeNesting * pNesting)404 DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
405 {
406    /* Only call on a definite-length array / map */
407    pNesting->pCurrent->u.ma.uCountCursor++;
408 }
409 
410 
411 static void
DecodeNesting_Ascend(QCBORDecodeNesting * pNesting)412 DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
413 {
414    pNesting->pCurrent--;
415 }
416 
417 
418 static QCBORError
DecodeNesting_Descend(QCBORDecodeNesting * pNesting,uint8_t uType)419 DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
420 {
421    /* Error out if nesting is too deep */
422    if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
423       return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
424    }
425 
426    /* The actual descend */
427    pNesting->pCurrent++;
428 
429    pNesting->pCurrent->uLevelType = uType;
430 
431    return QCBOR_SUCCESS;
432 }
433 
434 
435 static QCBORError
DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting * pNesting,bool bIsEmpty,size_t uOffset)436 DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
437                                      bool                bIsEmpty,
438                                      size_t              uOffset)
439 {
440    /*
441     * Should only be called on map/array.
442     *
443     * Have descended into this before this is called. The job here is
444     * just to mark it in bounded mode.
445     *
446     * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
447     * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
448     *
449     * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
450     */
451    if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
452       return QCBOR_ERR_INPUT_TOO_LARGE;
453    }
454 
455    pNesting->pCurrentBounded = pNesting->pCurrent;
456 
457    DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
458 
459    return QCBOR_SUCCESS;
460 }
461 
462 
463 static QCBORError
DecodeNesting_DescendMapOrArray(QCBORDecodeNesting * pNesting,uint8_t uQCBORType,uint64_t uCount)464 DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
465                                 uint8_t             uQCBORType,
466                                 uint64_t            uCount)
467 {
468    QCBORError uError = QCBOR_SUCCESS;
469 
470    if(uCount == 0) {
471       /* Nothing to do for empty definite-length arrays. They are just are
472        * effectively the same as an item that is not a map or array.
473        */
474       goto Done;
475       /* Empty indefinite-length maps and arrays are handled elsewhere */
476    }
477 
478    /* Error out if arrays is too long to handle */
479    if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
480       uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
481       uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
482       goto Done;
483    }
484 
485    uError = DecodeNesting_Descend(pNesting, uQCBORType);
486    if(uError != QCBOR_SUCCESS) {
487       goto Done;
488    }
489 
490    /* Fill in the new map/array level. Check above makes casts OK. */
491    pNesting->pCurrent->u.ma.uCountCursor  = (uint16_t)uCount;
492    pNesting->pCurrent->u.ma.uCountTotal   = (uint16_t)uCount;
493 
494    DecodeNesting_ClearBoundedMode(pNesting);
495 
496 Done:
497    return uError;;
498 }
499 
500 
501 static void
DecodeNesting_LevelUpCurrent(QCBORDecodeNesting * pNesting)502 DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
503 {
504    pNesting->pCurrent = pNesting->pCurrentBounded - 1;
505 }
506 
507 
508 static void
DecodeNesting_LevelUpBounded(QCBORDecodeNesting * pNesting)509 DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
510 {
511    while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
512       pNesting->pCurrentBounded--;
513       if(DecodeNesting_IsCurrentBounded(pNesting)) {
514          break;
515       }
516    }
517 }
518 
519 
520 static void
DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting * pNesting)521 DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
522 {
523    pNesting->pCurrent = pNesting->pCurrentBounded;
524 }
525 
526 
527 static QCBORError
DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting * pNesting,uint32_t uEndOffset,uint32_t uStartOffset)528 DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
529                                      uint32_t            uEndOffset,
530                                      uint32_t            uStartOffset)
531 {
532    QCBORError uError;
533 
534    uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
535    if(uError != QCBOR_SUCCESS) {
536       goto Done;
537    }
538 
539    /* Fill in the new byte string level */
540    pNesting->pCurrent->u.bs.uSavedEndOffset  = uEndOffset;
541    pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
542 
543    /* Bstr wrapped levels are always bounded */
544    pNesting->pCurrentBounded = pNesting->pCurrent;
545 
546 Done:
547    return uError;;
548 }
549 
550 
551 static void
DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting * pNesting)552 DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
553 {
554    pNesting->pCurrent->u.ma.uCountCursor = 0;
555 }
556 
557 
558 static void
DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting * pNesting)559 DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
560 {
561    if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
562       pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
563    }
564 }
565 
566 
567 static void
DecodeNesting_Init(QCBORDecodeNesting * pNesting)568 DecodeNesting_Init(QCBORDecodeNesting *pNesting)
569 {
570    /* Assumes that *pNesting has been zero'd before this call. */
571    pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
572    pNesting->pCurrent = &(pNesting->pLevels[0]);
573 }
574 
575 
576 static void
DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting * pNesting,QCBORDecodeNesting * pSave)577 DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
578                                   QCBORDecodeNesting *pSave)
579 {
580    *pSave = *pNesting;
581 }
582 
583 
584 static void
DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting * pNesting,const QCBORDecodeNesting * pSave)585 DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
586                                    const QCBORDecodeNesting *pSave)
587 {
588    *pNesting = *pSave;
589 }
590 
591 
592 static uint32_t
DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting * pMe)593 DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
594 {
595    return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
596 }
597 
598 
599 
600 
601 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
602 /*===========================================================================
603    QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
604 
605    The following four functions are pretty wrappers for invocation of
606    the string allocator supplied by the caller.
607 
608   ===========================================================================*/
609 
610 static void
StringAllocator_Free(const QCBORInternalAllocator * pMe,const void * pMem)611 StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
612 {
613    /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
614     * This is the one place where the const needs to be cast away so const can
615     * be use in the rest of the code.
616     */
617    (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
618 }
619 
620 // StringAllocator_Reallocate called with pMem NULL is
621 // equal to StringAllocator_Allocate()
622 static UsefulBuf
StringAllocator_Reallocate(const QCBORInternalAllocator * pMe,const void * pMem,size_t uSize)623 StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
624                            const void *pMem,
625                            size_t uSize)
626 {
627    /* See comment in StringAllocator_Free() */
628    return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
629 }
630 
631 static UsefulBuf
StringAllocator_Allocate(const QCBORInternalAllocator * pMe,size_t uSize)632 StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
633 {
634    return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
635 }
636 
637 static void
StringAllocator_Destruct(const QCBORInternalAllocator * pMe)638 StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
639 {
640    /* See comment in StringAllocator_Free() */
641    if(pMe->pfAllocator) {
642       (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
643    }
644 }
645 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
646 
647 
648 
649 
650 /*===========================================================================
651  QCBORDecode -- The main implementation of CBOR decoding
652 
653  See qcbor/qcbor_decode.h for definition of the object
654  used here: QCBORDecodeContext
655   ===========================================================================*/
656 /*
657  * Public function, see header file
658  */
659 void
QCBORDecode_Init(QCBORDecodeContext * pMe,UsefulBufC EncodedCBOR,QCBORDecodeMode nDecodeMode)660 QCBORDecode_Init(QCBORDecodeContext *pMe,
661                  UsefulBufC          EncodedCBOR,
662                  QCBORDecodeMode     nDecodeMode)
663 {
664    memset(pMe, 0, sizeof(QCBORDecodeContext));
665    UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
666    /* Don't bother with error check on decode mode. If a bad value is
667     * passed it will just act as if the default normal mode of 0 was set.
668     */
669    pMe->uDecodeMode = (uint8_t)nDecodeMode;
670    DecodeNesting_Init(&(pMe->nesting));
671 
672    /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
673     * GetNext_TaggedItem() and MapTagNumber(). */
674    memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
675 }
676 
677 
678 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
679 
680 /*
681  * Public function, see header file
682  */
683 void
QCBORDecode_SetUpAllocator(QCBORDecodeContext * pMe,QCBORStringAllocate pfAllocateFunction,void * pAllocateContext,bool bAllStrings)684 QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
685                            QCBORStringAllocate pfAllocateFunction,
686                            void               *pAllocateContext,
687                            bool                bAllStrings)
688 {
689    pMe->StringAllocator.pfAllocator   = pfAllocateFunction;
690    pMe->StringAllocator.pAllocateCxt  = pAllocateContext;
691    pMe->bStringAllocateAll            = bAllStrings;
692 }
693 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
694 
695 
696 
697 
698 /*
699  * Deprecated public function, see header file
700  */
701 void
QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext * pMe,const QCBORTagListIn * pTagList)702 QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext   *pMe,
703                                        const QCBORTagListIn *pTagList)
704 {
705    /* This does nothing now. It is retained for backwards compatibility */
706    (void)pMe;
707    (void)pTagList;
708 }
709 
710 
711 
712 
713 /*
714  * Decoding items is done in six layers, one calling the next one
715  * down. If a layer has no work to do for a particular item, it
716  * returns quickly.
717  *
718  * 1. QCBORDecode_Private_GetNextTagContent - The top layer processes
719  * tagged data items, turning them into the local C representation.
720  * For the most simple it is just associating a QCBOR_TYPE with the
721  * data. For the complex ones that an aggregate of data items, there
722  * is some further decoding and some limited recursion.
723  *
724  * 2. QCBORDecode_Private_GetNextMapOrArray - This manages the
725  * beginnings and ends of maps and arrays. It tracks descending into
726  * and ascending out of maps/arrays. It processes breaks that
727  * terminate indefinite-length maps and arrays.
728  *
729  * 3. QCBORDecode_Private_GetNextMapEntry - This handles the combining
730  * of two items, the label and the data, that make up a map entry.  It
731  * only does work on maps. It combines the label and data items into
732  * one labeled item.
733  *
734  * 4. QCBORDecode_Private_GetNextTagNumber - This decodes type 6 tag
735  * numbers. It turns the tag numbers into bit flags associated with
736  * the data item. No actual decoding of the contents of the tag is
737  * performed here.
738  *
739  * 5. QCBORDecode_Private_GetNextFullString - This assembles the
740  * sub-items that make up an indefinite-length string into one string
741  * item. It uses the string allocator to create contiguous space for
742  * the item. It processes all breaks that are part of
743  * indefinite-length strings.
744  *
745  * 6. QCBOR_Private_DecodeAtomicDataItem - This decodes the atomic
746  * data items in CBOR. Each atomic data item has a "major type", an
747  * integer "argument" and optionally some content. For text and byte
748  * strings, the content is the bytes that make up the string. These
749  * are the smallest data items that are considered to be well-formed.
750  * The content may also be other data items in the case of aggregate
751  * types. They are not handled in this layer.
752  *
753  * This uses about 350 bytes of stack. This number comes from
754  * instrumenting (printf address of stack variables) the code on x86
755  * compiled for size optimization.
756  */
757 
758 
759 /*
760  * Note about use of int and unsigned variables.
761  *
762  * See http://www.unix.org/whitepapers/64bit.html for reasons int is
763  * used carefully here, and in particular why it isn't used in the
764  * public interface.  Also see
765  * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
766  *
767  * Int is used for values that need less than 16-bits and would be
768  * subject to integer promotion and result in complaining from static
769  * analyzers.
770  */
771 
772 
773 /**
774  * @brief Decode the CBOR head, the type and argument.
775  *
776  * @param[in] pUInBuf            The input buffer to read from.
777  * @param[out] pnMajorType       The decoded major type.
778  * @param[out] puArgument        The decoded argument.
779  * @param[out] pnAdditionalInfo  The decoded Lower 5 bits of initial byte.
780  *
781  * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
782  * @retval QCBOR_ERR_HIT_END Unexpected end of input
783  *
784  * This decodes the CBOR "head" that every CBOR data item has. See
785  * longer explaination of the head in documentation for
786  * QCBOREncode_EncodeHead().
787  *
788  * This does the network->host byte order conversion. The conversion
789  * here also results in the conversion for floats in addition to that
790  * for lengths, tags and integer values.
791  *
792  * The int type is preferred to uint8_t for some variables as this
793  * avoids integer promotions, can reduce code size and makes static
794  * analyzers happier.
795  */
796 static QCBORError
QCBOR_Private_DecodeHead(UsefulInputBuf * pUInBuf,int * pnMajorType,uint64_t * puArgument,int * pnAdditionalInfo)797 QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
798                          int            *pnMajorType,
799                          uint64_t       *puArgument,
800                          int            *pnAdditionalInfo)
801 {
802    QCBORError uReturn;
803 
804    /* Get the initial byte that every CBOR data item has and break it
805     * down. */
806    const int nInitialByte    = (int)UsefulInputBuf_GetByte(pUInBuf);
807    const int nTmpMajorType   = nInitialByte >> 5;
808    const int nAdditionalInfo = nInitialByte & 0x1f;
809 
810    /* Where the argument accumulates */
811    uint64_t uArgument;
812 
813    if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
814       /* Need to get 1,2,4 or 8 additional argument bytes. Map
815        * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
816        */
817       static const uint8_t aIterate[] = {1,2,4,8};
818 
819       /* Loop getting all the bytes in the argument */
820       uArgument = 0;
821       for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
822          /* This shift and add gives the endian conversion. */
823          uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
824       }
825    } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
826       /* The reserved and thus-far unused additional info values */
827       uReturn = QCBOR_ERR_UNSUPPORTED;
828       goto Done;
829    } else {
830       /* Less than 24, additional info is argument or 31, an
831        * indefinite-length.  No more bytes to get.
832        */
833       uArgument = (uint64_t)nAdditionalInfo;
834    }
835 
836    if(UsefulInputBuf_GetError(pUInBuf)) {
837       uReturn = QCBOR_ERR_HIT_END;
838       goto Done;
839    }
840 
841    /* All successful if arrived here. */
842    uReturn           = QCBOR_SUCCESS;
843    *pnMajorType      = nTmpMajorType;
844    *puArgument       = uArgument;
845    *pnAdditionalInfo = nAdditionalInfo;
846 
847 Done:
848    return uReturn;
849 }
850 
851 
852 /**
853  * @brief Decode integer types, major types 0 and 1.
854  *
855  * @param[in] nMajorType       The CBOR major type (0 or 1).
856  * @param[in] uArgument        The argument from the head.
857  * @param[in] nAdditionalInfo  So it can be error-checked.
858  * @param[out] pDecodedItem    The filled in decoded item.
859  *
860  * @retval QCBOR_ERR_INT_OVERFLOW  Too-large negative encountered.
861  * @retval QCBOR_ERR_BAD_INT       nAdditionalInfo indicated indefinte.
862  *
863  * Must only be called when major type is 0 or 1.
864  *
865  * CBOR doesn't explicitly specify two's compliment for integers but
866  * all CPUs use it these days and the test vectors in the RFC are
867  * so. All integers in the CBOR structure are positive and the major
868  * type indicates positive or negative.  CBOR can express positive
869  * integers up to 2^x - 1 where x is the number of bits and negative
870  * integers down to 2^x.  Note that negative numbers can be one more
871  * away from zero than positive.  Stdint, as far as I can tell, uses
872  * two's compliment to represent negative integers.
873  */
874 static QCBORError
QCBOR_Private_DecodeInteger(const int nMajorType,const uint64_t uArgument,const int nAdditionalInfo,QCBORItem * pDecodedItem)875 QCBOR_Private_DecodeInteger(const int      nMajorType,
876                             const uint64_t uArgument,
877                             const int      nAdditionalInfo,
878                             QCBORItem     *pDecodedItem)
879 {
880    QCBORError uReturn = QCBOR_SUCCESS;
881 
882    if(nAdditionalInfo == LEN_IS_INDEFINITE) {
883       uReturn = QCBOR_ERR_BAD_INT;
884       goto Done;
885    }
886 
887    if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
888       if (uArgument <= INT64_MAX) {
889          pDecodedItem->val.int64 = (int64_t)uArgument;
890          pDecodedItem->uDataType = QCBOR_TYPE_INT64;
891 
892       } else {
893          pDecodedItem->val.uint64 = uArgument;
894          pDecodedItem->uDataType  = QCBOR_TYPE_UINT64;
895       }
896 
897    } else {
898       if(uArgument <= INT64_MAX) {
899          /* CBOR's representation of negative numbers lines up with
900           * the two-compliment representation. A negative integer has
901           * one more in range than a positive integer. INT64_MIN is
902           * equal to (-INT64_MAX) - 1.
903           */
904          pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
905          pDecodedItem->uDataType = QCBOR_TYPE_INT64;
906 
907       } else {
908          /* C can't represent a negative integer in this range so it
909           * is an error.
910           */
911          uReturn = QCBOR_ERR_INT_OVERFLOW;
912       }
913    }
914 
915 Done:
916    return uReturn;
917 }
918 
919 
920 /**
921  * @brief Decode text and byte strings
922  *
923  * @param[in] pMe              Decoder context.
924  * @param[in] bAllocate        Whether to allocate and copy string.
925  * @param[in] nMajorType       Whether it is a byte or text string.
926  * @param[in] uStrLen          The length of the string.
927  * @param[in] nAdditionalInfo  Whether it is an indefinite-length string.
928  * @param[out] pDecodedItem    The filled-in decoded item.
929  *
930  * @retval QCBOR_ERR_HIT_END          Unexpected end of input.
931  * @retval QCBOR_ERR_STRING_ALLOCATE  Out of memory.
932  * @retval QCBOR_ERR_STRING_TOO_LONG  String longer than SIZE_MAX - 4.
933  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR  Allocation requested, but no allocator
934  *
935  * This reads @c uStrlen bytes from the input and fills in @c
936  * pDecodedItem. If @c bAllocate is true, then memory for the string
937  * is allocated.
938  */
939 static QCBORError
QCBOR_Private_DecodeString(QCBORDecodeContext * pMe,const bool bAllocate,const int nMajorType,const uint64_t uStrLen,const int nAdditionalInfo,QCBORItem * pDecodedItem)940 QCBOR_Private_DecodeString(QCBORDecodeContext  *pMe,
941                            const bool           bAllocate,
942                            const int            nMajorType,
943                            const uint64_t       uStrLen,
944                            const int            nAdditionalInfo,
945                            QCBORItem           *pDecodedItem)
946 {
947    QCBORError uReturn = QCBOR_SUCCESS;
948 
949    /* ---- Figure out the major type ---- */
950    #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
951    #error QCBOR_TYPE_BYTE_STRING not lined up with major type
952    #endif
953 
954    #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
955    #error QCBOR_TYPE_TEXT_STRING not lined up with major type
956    #endif
957    pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
958 
959    if(nAdditionalInfo == LEN_IS_INDEFINITE) {
960       /* --- Just the head of an indefinite-length string --- */
961       pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
962 
963    } else {
964       /* --- A definite-length string --- */
965       /* --- (which might be a chunk of an indefinte-length string) --- */
966 
967       /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
968        * CPUs.  This check makes the casts to size_t below safe.
969        *
970        * The max is 4 bytes less than the largest sizeof() so this can be
971        * tested by putting a SIZE_MAX length in the CBOR test input (no
972        * one will care the limit on strings is 4 bytes shorter).
973        */
974       if(uStrLen > SIZE_MAX-4) {
975          uReturn = QCBOR_ERR_STRING_TOO_LONG;
976          goto Done;
977       }
978 
979       const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
980       if(UsefulBuf_IsNULLC(Bytes)) {
981          /* Failed to get the bytes for this string item */
982          uReturn = QCBOR_ERR_HIT_END;
983          goto Done;
984       }
985 
986       if(bAllocate) {
987 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
988          /* --- Put string in allocated memory --- */
989 
990          /* Note that this is not where allocation to coalesce
991           * indefinite-length strings is done. This is for when the
992           * caller has requested all strings be allocated. Disabling
993           * indefinite length strings also disables this allocate-all
994           * option.
995           */
996 
997          if(pMe->StringAllocator.pfAllocator == NULL) {
998             uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
999             goto Done;
1000          }
1001          UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
1002          if(UsefulBuf_IsNULL(NewMem)) {
1003             uReturn = QCBOR_ERR_STRING_ALLOCATE;
1004             goto Done;
1005          }
1006          pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
1007          pDecodedItem->uDataAlloc = 1;
1008 #else
1009          uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1010 #endif /*  ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1011       } else {
1012          /* --- Normal case with no string allocator --- */
1013          pDecodedItem->val.string = Bytes;
1014       }
1015    }
1016 
1017 Done:
1018    return uReturn;
1019 }
1020 
1021 
1022 /**
1023  * @brief Decode array or map.
1024  *
1025  * @param[in] uMode            Decoder mode.
1026  * @param[in] nMajorType       Whether it is a byte or text string.
1027  * @param[in] uItemCount       The length of the string.
1028  * @param[in] nAdditionalInfo  Whether it is an indefinite-length.
1029  * @param[out] pDecodedItem    The filled-in decoded item.
1030  *
1031  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
1032  * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG     Too many items in array/map.
1033  *
1034  * Not much to do for arrays and maps. Just the type item count (but a
1035  * little messy because of ifdefs for indefinite-lengths and
1036  * map-as-array decoding).
1037  *
1038  * This also does the bulk of the work for @ref
1039  * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
1040  * arbitrarily complex map labels. This ifdefs out with
1041  * QCBOR_DISABLE_NON_INTEGER_LABELS.
1042  */
1043 static QCBORError
QCBOR_Private_DecodeArrayOrMap(const uint8_t uMode,const int nMajorType,const uint64_t uItemCount,const int nAdditionalInfo,QCBORItem * pDecodedItem)1044 QCBOR_Private_DecodeArrayOrMap(const uint8_t  uMode,
1045                                const int      nMajorType,
1046                                const uint64_t uItemCount,
1047                                const int      nAdditionalInfo,
1048                                QCBORItem     *pDecodedItem)
1049 {
1050    QCBORError uReturn;
1051 
1052    /* ------ Sort out the data type ------ */
1053    #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1054    #error QCBOR_TYPE_ARRAY value not lined up with major type
1055    #endif
1056 
1057    #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1058    #error QCBOR_TYPE_MAP value not lined up with major type
1059    #endif
1060    pDecodedItem->uDataType = (uint8_t)nMajorType;
1061 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1062    if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
1063       pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1064    }
1065 #else
1066    (void)uMode;
1067 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1068 
1069    uReturn = QCBOR_SUCCESS;
1070 
1071    if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1072       /* ------ Indefinite-length array/map ----- */
1073 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1074       pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1075 #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1076       uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1077 #endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1078    } else {
1079 
1080 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1081       if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
1082          /* ------ Definite-length map as array ------ */
1083 
1084          if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1085             uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1086          } else {
1087             /* cast OK because of check above */
1088             pDecodedItem->val.uCount = (uint16_t)uItemCount*2;
1089          }
1090 
1091       } else
1092 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1093       {
1094          /* ------ Definite-length array/map ------ */
1095          if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
1096             uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1097          } else {
1098             /* cast OK because of check above */
1099             pDecodedItem->val.uCount = (uint16_t)uItemCount;
1100          }
1101       }
1102    }
1103 
1104    return uReturn;
1105 }
1106 
1107 
1108 /**
1109  * @brief Decode a tag number.
1110  *
1111  * @param[in] uTagNumber       The length of the string.
1112  * @param[in] nAdditionalInfo  So this can be error-checked.
1113  * @param[out] pDecodedItem    The filled-in decoded item.
1114  *
1115  * @retval QCBOR_ERR_BAD_INT        nAdditionalInfo is LEN_IS_INDEFINITE.
1116  * @retval QCBOR_ERR_TAGS_DISABLED  QCBOR_DISABLE_TAGS is defined.
1117  *
1118  * Not much to do for tags, but fill in pDecodedItem and check for
1119  * error in nAdditionalInfo.
1120  */
1121 static QCBORError
QCBOR_Private_DecodeTag(const uint64_t uTagNumber,const int nAdditionalInfo,QCBORItem * pDecodedItem)1122 QCBOR_Private_DecodeTag(const uint64_t uTagNumber,
1123                         const int      nAdditionalInfo,
1124                         QCBORItem     *pDecodedItem)
1125 {
1126 #ifndef QCBOR_DISABLE_TAGS
1127    if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1128       return QCBOR_ERR_BAD_INT;
1129    } else {
1130       pDecodedItem->val.uTagV = uTagNumber;
1131       pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1132       return QCBOR_SUCCESS;
1133    }
1134 #else /* QCBOR_DISABLE_TAGS */
1135    (void)nAdditionalInfo;
1136    (void)uTagNumber;
1137    (void)pDecodedItem;
1138    return QCBOR_ERR_TAGS_DISABLED;
1139 #endif /* QCBOR_DISABLE_TAGS */
1140 }
1141 
1142 
1143 /* Make sure #define value line up as DecodeSimple counts on this. */
1144 #if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
1145 #error QCBOR_TYPE_FALSE macro value wrong
1146 #endif
1147 
1148 #if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
1149 #error QCBOR_TYPE_TRUE macro value wrong
1150 #endif
1151 
1152 #if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
1153 #error QCBOR_TYPE_NULL macro value wrong
1154 #endif
1155 
1156 #if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
1157 #error QCBOR_TYPE_UNDEF macro value wrong
1158 #endif
1159 
1160 #if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
1161 #error QCBOR_TYPE_BREAK macro value wrong
1162 #endif
1163 
1164 #if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
1165 #error QCBOR_TYPE_DOUBLE macro value wrong
1166 #endif
1167 
1168 #if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
1169 #error QCBOR_TYPE_FLOAT macro value wrong
1170 #endif
1171 
1172 
1173 /**
1174  * @brief Decode major type 7 -- true, false, floating-point, break...
1175  *
1176  * @param[in] nAdditionalInfo   The lower five bits from the initial byte.
1177  * @param[in] uArgument         The argument from the head.
1178  * @param[out] pDecodedItem     The filled in decoded item.
1179  *
1180  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1181  *                                           of half-precision disabled
1182  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all float
1183  *                                           decode is disabled.
1184  * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of simple
1185  *                                           type in input.
1186  */
1187 static QCBORError
QCBOR_Private_DecodeType7(const int nAdditionalInfo,const uint64_t uArgument,QCBORItem * pDecodedItem)1188 QCBOR_Private_DecodeType7(const int      nAdditionalInfo,
1189                           const uint64_t uArgument,
1190                           QCBORItem     *pDecodedItem)
1191 {
1192    QCBORError uReturn = QCBOR_SUCCESS;
1193 
1194    /* uAdditionalInfo is 5 bits from the initial byte. Compile time
1195     * checks above make sure uAdditionalInfo values line up with
1196     * uDataType values.  DecodeHead() never returns an AdditionalInfo
1197     * > 0x1f so cast is safe.
1198     */
1199    pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
1200 
1201    switch(nAdditionalInfo) {
1202       /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
1203        * are caught before this is called.
1204        */
1205 
1206       case HALF_PREC_FLOAT: /* 25 */
1207 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1208          /* Half-precision is returned as a double.  The cast to
1209           * uint16_t is safe because the encoded value was 16 bits. It
1210           * was widened to 64 bits to be passed in here.
1211           */
1212          pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
1213          pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
1214 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1215          uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
1216          break;
1217       case SINGLE_PREC_FLOAT: /* 26 */
1218 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
1219          /* Single precision is normally returned as a double since
1220           * double is widely supported, there is no loss of precision,
1221           * it makes it easy for the caller in most cases and it can
1222           * be converted back to single with no loss of precision
1223           *
1224           * The cast to uint32_t is safe because the encoded value was
1225           * 32 bits. It was widened to 64 bits to be passed in here.
1226           */
1227          {
1228             const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
1229 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
1230             /* In the normal case, use HW to convert float to
1231              * double. */
1232             pDecodedItem->val.dfnum = (double)f;
1233             pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
1234 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
1235             /* Use of float HW is disabled, return as a float. */
1236             pDecodedItem->val.fnum = f;
1237             pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
1238 
1239             /* IEEE754_FloatToDouble() could be used here to return as
1240              * a double, but it adds object code and most likely
1241              * anyone disabling FLOAT HW use doesn't care about floats
1242              * and wants to save object code.
1243              */
1244 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1245          }
1246 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1247          uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
1248          break;
1249 
1250       case DOUBLE_PREC_FLOAT: /* 27 */
1251 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
1252          pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
1253          pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
1254 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1255          uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
1256          break;
1257 
1258       case CBOR_SIMPLEV_FALSE: /* 20 */
1259       case CBOR_SIMPLEV_TRUE:  /* 21 */
1260       case CBOR_SIMPLEV_NULL:  /* 22 */
1261       case CBOR_SIMPLEV_UNDEF: /* 23 */
1262       case CBOR_SIMPLE_BREAK:  /* 31 */
1263          break; /* nothing to do */
1264 
1265       case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1266          if(uArgument <= CBOR_SIMPLE_BREAK) {
1267             /* This takes out f8 00 ... f8 1f which should be encoded
1268              * as e0 … f7
1269              */
1270             uReturn = QCBOR_ERR_BAD_TYPE_7;
1271             goto Done;
1272          }
1273          /* FALLTHROUGH */
1274 
1275       default: /* 0-19 */
1276          pDecodedItem->uDataType   = QCBOR_TYPE_UKNOWN_SIMPLE;
1277          /* DecodeHead() will make uArgument equal to
1278           * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1279           * safe because the 2, 4 and 8 byte lengths of uNumber are in
1280           * the double/float cases above
1281           */
1282          pDecodedItem->val.uSimple = (uint8_t)uArgument;
1283          break;
1284    }
1285 
1286 Done:
1287    return uReturn;
1288 }
1289 
1290 
1291 /**
1292  * @brief Decode a single primitive data item (decode layer 6).
1293  *
1294  * @param[in] pMe                Decoder context.
1295  * @param[in] bAllocateStrings   If true, use allocator for strings.
1296  * @param[out] pDecodedItem      The filled-in decoded item.
1297  *
1298  * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
1299  *                                           features
1300  * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
1301  * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
1302  * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
1303  * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
1304  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Allocation requested, but no allocator
1305  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1306  *                                           of half-precision disabled
1307  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
1308  *                                           float decode is disabled.
1309  * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
1310  *                                           simple type in input.
1311  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
1312  *                                              in input, but indefinite
1313  *                                              lengths disabled.
1314  * @retval QCBOR_ERR_BAD_INT                 nAdditionalInfo indicated indefinte.
1315  * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array/map.
1316  * @retval QCBOR_ERR_TAGS_DISABLED           QCBOR_DISABLE_TAGS is defined.
1317  *
1318  * This decodes the most primitive/atomic data item. It does no
1319  * combining of data items.
1320  */
1321 static QCBORError
QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext * pMe,const bool bAllocateStrings,QCBORItem * pDecodedItem)1322 QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext  *pMe,
1323                                    const bool           bAllocateStrings,
1324                                    QCBORItem           *pDecodedItem)
1325 {
1326    QCBORError uReturn;
1327    int        nMajorType = 0;
1328    uint64_t   uArgument = 0;
1329    int        nAdditionalInfo = 0;
1330 
1331    memset(pDecodedItem, 0, sizeof(QCBORItem));
1332 
1333    /* Decode the "head" that every CBOR item has into the major type,
1334     * argument and the additional info.
1335     */
1336    uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf), &nMajorType, &uArgument, &nAdditionalInfo);
1337    if(uReturn != QCBOR_SUCCESS) {
1338       return uReturn;
1339    }
1340 
1341    /* All the functions below get inlined by the optimizer. This code
1342     * is easier to read with them all being similar functions, even if
1343     * some functions don't do much.
1344     */
1345    switch (nMajorType) {
1346       case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1347       case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1348          return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
1349          break;
1350 
1351       case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1352       case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1353          return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
1354          break;
1355 
1356       case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1357       case CBOR_MAJOR_TYPE_MAP:   /* Major type 5 */
1358          return QCBOR_Private_DecodeArrayOrMap(pMe->uDecodeMode, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
1359          break;
1360 
1361       case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1362          return QCBOR_Private_DecodeTag(uArgument, nAdditionalInfo, pDecodedItem);
1363          break;
1364 
1365       case CBOR_MAJOR_TYPE_SIMPLE:
1366          /* Major type 7: float, double, true, false, null... */
1367          return QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1368          break;
1369 
1370       default:
1371          /* Never happens because DecodeHead() should never return > 7 */
1372          return QCBOR_ERR_UNSUPPORTED;
1373          break;
1374    }
1375 }
1376 
1377 
1378 /**
1379  * @brief Process indefinite-length strings (decode layer 5).
1380  *
1381  * @param[in] pMe   Decoder context
1382  * @param[out] pDecodedItem  The decoded item that work is done on.
1383  *
1384  * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
1385  *                                           features
1386  * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
1387  * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
1388  * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
1389  * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
1390  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1391  *                                           of half-precision disabled
1392  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
1393  *                                           float decode is disabled.
1394  * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
1395  *                                           simple type in input.
1396  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
1397  *                                              in input, but indefinite
1398  *                                              lengths disabled.
1399  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
1400  *                                           but no string allocator.
1401  * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
1402  * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
1403  *                                               input, but indefinite-length
1404  *                                               strings are disabled.
1405  *
1406  * If @c pDecodedItem is not an indefinite-length string, this does nothing.
1407  *
1408  * If it is, this loops getting the subsequent chunk data items that
1409  * make up the string.  The string allocator is used to make a
1410  * contiguous buffer for the chunks.  When this completes @c
1411  * pDecodedItem contains the put-together string.
1412  *
1413  * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
1414  */
1415 static QCBORError
QCBORDecode_Private_GetNextFullString(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)1416 QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1417                                       QCBORItem          *pDecodedItem)
1418 {
1419    /* Aproximate stack usage
1420     *                                             64-bit      32-bit
1421     *   local vars                                    32          16
1422     *   2 UsefulBufs                                  32          16
1423     *   QCBORItem                                     56          52
1424     *   TOTAL                                        120          74
1425     */
1426    QCBORError uReturn;
1427 
1428    /* A note about string allocation -- Memory for strings is
1429     * allocated either because 1) indefinte-length string chunks are
1430     * being coalecsed or 2) caller has requested all strings be
1431     * allocated.  The first case is handed below here. The second case
1432     * is handled in DecodeString if the bAllocate is true. That
1433     * boolean originates here with pMe->bStringAllocateAll immediately
1434     * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
1435     * in two different contexts here 1) main-line processing which is
1436     * where definite-length strings need to be allocated if
1437     * bStringAllocateAll is true and 2) processing chunks of
1438     * indefinite-lengths strings in in which case there must be no
1439     * allocation.
1440     */
1441 
1442 
1443    uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
1444    if(uReturn != QCBOR_SUCCESS) {
1445       goto Done;
1446    }
1447 
1448 
1449    /* This is where out-of-place break is detected for the whole
1450     * decoding stack. Break is an error for everything that calls
1451     * QCBORDecode_Private_GetNextFullString(), so the check is
1452     * centralized here.
1453     */
1454    if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1455       uReturn = QCBOR_ERR_BAD_BREAK;
1456       goto Done;
1457    }
1458 
1459 
1460    /* Skip out if not an indefinite-length string */
1461    const uint8_t uStringType = pDecodedItem->uDataType;
1462    if(uStringType != QCBOR_TYPE_BYTE_STRING &&
1463       uStringType != QCBOR_TYPE_TEXT_STRING) {
1464       goto Done;
1465    }
1466    if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1467       goto Done;
1468    }
1469 
1470 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1471    /* Can't decode indefinite-length strings without a string allocator */
1472    if(!pMe->StringAllocator.pfAllocator) {
1473       uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1474       goto Done;
1475    }
1476 
1477    /* Loop getting chunks of the indefinite-length string */
1478    UsefulBufC FullString = NULLUsefulBufC;
1479 
1480    for(;;) {
1481       /* Get QCBORItem for next chunk */
1482       QCBORItem StringChunkItem;
1483       /* Pass false to DecodeAtomicDataItem() because the individual
1484        * string chunks in an indefinite-length must not be
1485        * allocated. They are always copied into the allocated
1486        * contiguous buffer allocated here.
1487        */
1488       uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
1489       if(uReturn) {
1490          break;
1491       }
1492 
1493       /* Is item is the marker for end of the indefinite-length string? */
1494       if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
1495          /* String is complete */
1496          pDecodedItem->val.string = FullString;
1497          pDecodedItem->uDataAlloc = 1;
1498          break;
1499       }
1500 
1501       /* All chunks must be of the same type, the type of the item
1502        * that introduces the indefinite-length string. This also
1503        * catches errors where the chunk is not a string at all and an
1504        * indefinite-length string inside an indefinite-length string.
1505        */
1506       if(StringChunkItem.uDataType != uStringType ||
1507          StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1508          uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
1509          break;
1510       }
1511 
1512       if (StringChunkItem.val.string.len > 0) {
1513          /* The first time throurgh FullString.ptr is NULL and this is
1514           * equivalent to StringAllocator_Allocate(). Subsequently it is
1515           * not NULL and a reallocation happens.
1516           */
1517          UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
1518                                                        FullString.ptr,
1519                                                        FullString.len + StringChunkItem.val.string.len);
1520          if(UsefulBuf_IsNULL(NewMem)) {
1521             uReturn = QCBOR_ERR_STRING_ALLOCATE;
1522             break;
1523          }
1524 
1525          /* Copy new string chunk to the end of accumulated string */
1526          FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
1527       }
1528    }
1529 
1530    if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1531       /* Getting the item failed, clean up the allocated memory */
1532       StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
1533    }
1534 #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1535    uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1536 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1537 
1538 Done:
1539    return uReturn;
1540 }
1541 
1542 
1543 #ifndef QCBOR_DISABLE_TAGS
1544 /**
1545  * @brief This converts a tag number to a shorter mapped value for storage.
1546  *
1547  * @param[in] pMe                The decode context.
1548  * @param[in] uUnMappedTag       The tag number to map
1549  * @param[out] puMappedTagNumer  The stored tag number.
1550  *
1551  * @return error code.
1552  *
1553  * The main point of mapping tag numbers is make QCBORItem
1554  * smaller. With this mapping storage of 4 tags takes up 8
1555  * bytes. Without, it would take up 32 bytes.
1556  *
1557  * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1558  * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1559  *
1560  * See also UnMapTagNumber() and @ref QCBORItem.
1561  */
1562 static QCBORError
QCBORDecode_Private_MapTagNumber(QCBORDecodeContext * pMe,const uint64_t uUnMappedTag,uint16_t * puMappedTagNumer)1563 QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1564                                  const uint64_t      uUnMappedTag,
1565                                  uint16_t           *puMappedTagNumer)
1566 {
1567    if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1568       unsigned uTagMapIndex;
1569       /* Is there room in the tag map, or is it in it already? */
1570       for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1571          if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1572             break;
1573          }
1574          if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1575             break;
1576          }
1577       }
1578       if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1579          return QCBOR_ERR_TOO_MANY_TAGS;
1580       }
1581 
1582       /* Covers the cases where tag is new and were it is already in the map */
1583       pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1584       *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1585 
1586    } else {
1587       *puMappedTagNumer = (uint16_t)uUnMappedTag;
1588    }
1589 
1590    return QCBOR_SUCCESS;
1591 }
1592 
1593 
1594 /**
1595  * @brief This converts a mapped tag number to the actual tag number.
1596  *
1597  * @param[in] pMe               The decode context.
1598  * @param[in] uMappedTagNumber  The stored tag number.
1599  *
1600  * @return The actual tag number is returned or
1601  *         @ref CBOR_TAG_INVALID64 on error.
1602  *
1603  * This is the reverse of MapTagNumber()
1604  */
1605 static uint64_t
QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext * pMe,const uint16_t uMappedTagNumber)1606 QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1607                                    const uint16_t            uMappedTagNumber)
1608 {
1609    if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1610       return uMappedTagNumber;
1611    } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
1612       return CBOR_TAG_INVALID64;
1613    } else {
1614       /* This won't be negative because of code below in
1615        * MapTagNumber()
1616        */
1617       const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1618       return pMe->auMappedTags[uIndex];
1619    }
1620 }
1621 #endif /* QCBOR_DISABLE_TAGS */
1622 
1623 
1624 /**
1625  * @brief Aggregate all tags wrapping a data item (decode layer 4).
1626  *
1627  * @param[in] pMe            Decoder context
1628  * @param[out] pDecodedItem  The decoded item that work is done on.
1629  *
1630  * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
1631  *                                           features
1632  * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
1633  * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
1634  * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
1635  * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
1636  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1637  *                                           of half-precision disabled
1638  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
1639  *                                           float decode is disabled.
1640  * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
1641  *                                           simple type in input.
1642  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
1643  *                                              in input, but indefinite
1644  *                                              lengths disabled.
1645  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
1646  *                                           but no string allocator.
1647  * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
1648  * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
1649  *                                               input, but indefinite-length
1650  *                                               strings are disabled.
1651  * @retval QCBOR_ERR_TOO_MANY_TAGS           Too many tag numbers on item.
1652  *
1653  * This loops getting atomic data items until one is not a tag
1654  * number.  Usually this is largely pass-through because most
1655  * item are not tag numbers.
1656  */
1657 static QCBORError
QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)1658 QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1659                                      QCBORItem          *pDecodedItem)
1660 {
1661 #ifndef QCBOR_DISABLE_TAGS
1662    /* Accummulate the tags from multiple items here and then copy them
1663     * into the last item, the non-tag item.
1664     */
1665    uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1666 
1667    /* Initialize to CBOR_TAG_INVALID16 */
1668    #if CBOR_TAG_INVALID16 != 0xffff
1669    /* Be sure the memset does the right thing. */
1670    #err CBOR_TAG_INVALID16 tag not defined as expected
1671    #endif
1672    memset(auItemsTags, 0xff, sizeof(auItemsTags));
1673 
1674    QCBORError uReturn = QCBOR_SUCCESS;
1675 
1676    /* Loop fetching data items until the item fetched is not a tag */
1677    for(;;) {
1678       QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
1679       if(uErr != QCBOR_SUCCESS) {
1680          uReturn = uErr;
1681          goto Done;
1682       }
1683 
1684       if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
1685          /* Successful exit from loop; maybe got some tags, maybe not */
1686          memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
1687          break;
1688       }
1689 
1690       if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1691          /* No room in the tag list */
1692          uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1693          /* Continue on to get all tags wrapping this item even though
1694           * it is erroring out in the end. This allows decoding to
1695           * continue. This is a resource limit error, not a problem
1696           * with being well-formed CBOR.
1697           */
1698          continue;
1699       }
1700       /* Slide tags over one in the array to make room at index 0.
1701        * Must use memmove because the move source and destination
1702        * overlap.
1703        */
1704       memmove(&auItemsTags[1],
1705               auItemsTags,
1706               sizeof(auItemsTags) - sizeof(auItemsTags[0]));
1707 
1708       /* Map the tag */
1709       uint16_t uMappedTagNumber = 0;
1710       uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
1711       /* Continue even on error so as to consume all tags wrapping
1712        * this data item so decoding can go on. If MapTagNumber()
1713        * errors once it will continue to error.
1714        */
1715       auItemsTags[0] = uMappedTagNumber;
1716    }
1717 
1718 Done:
1719    return uReturn;
1720 
1721 #else /* QCBOR_DISABLE_TAGS */
1722 
1723    return QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
1724 
1725 #endif /* QCBOR_DISABLE_TAGS */
1726 }
1727 
1728 
1729 /**
1730  * @brief Combine a map entry label and value into one item (decode layer 3).
1731  *
1732  * @param[in] pMe            Decoder context
1733  * @param[out] pDecodedItem  The decoded item that work is done on.
1734  *
1735  * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
1736  *                                           features
1737  * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
1738  * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
1739  * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
1740  * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
1741  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1742  *                                           of half-precision disabled
1743  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
1744  *                                           float decode is disabled.
1745  * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
1746  *                                           simple type in input.
1747  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
1748  *                                              in input, but indefinite
1749  *                                              lengths disabled.
1750  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
1751  *                                           but no string allocator.
1752  * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
1753  * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
1754  *                                               input, but indefinite-length
1755  *                                               strings are disabled.
1756  * @retval QCBOR_ERR_TOO_MANY_TAGS           Too many tag numbers on item.
1757  * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array.
1758  * @retval QCBOR_ERR_MAP_LABEL_TYPE          Map label not string or integer.
1759  *
1760  * If the current nesting level is a map, then this combines pairs of
1761  * items into one data item with a label and value.
1762  *
1763  * This is passthrough if the current nesting level is not a map.
1764  *
1765  * This also implements maps-as-array mode where a map is treated like
1766  * an array to allow caller to do their own label processing.
1767  */
1768 
1769 static QCBORError
QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)1770 QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1771                                     QCBORItem          *pDecodedItem)
1772 {
1773    QCBORItem  LabelItem;
1774    QCBORError uErr;
1775 
1776    uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
1777    if(QCBORDecode_IsUnrecoverableError(uErr)) {
1778       goto Done;
1779    }
1780 
1781    if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1782       /* Not decoding a map. Nothing to do. */
1783       /* When decoding maps-as-arrays, the type will be
1784        * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
1785        * here. This is now map processing for maps-as-arrays is not
1786        * done. */
1787       goto Done;
1788    }
1789 
1790    /* Decoding a map entry, so the item decoded above was the label */
1791    LabelItem = *pDecodedItem;
1792 
1793    /* Get the value of the map item */
1794    uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
1795    if(QCBORDecode_IsUnrecoverableError(uErr)) {
1796       goto Done;
1797    }
1798 
1799    /* Combine the label item and value item into one */
1800    pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1801    pDecodedItem->uLabelType  = LabelItem.uDataType;
1802 
1803 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1804    /* QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
1805     * get rid of it in QCBOR 2.0
1806     */
1807    if(pMe->uDecodeMode == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
1808       LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
1809       uErr = QCBOR_ERR_MAP_LABEL_TYPE;
1810       goto Done;
1811    }
1812 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1813 
1814    switch(LabelItem.uDataType) {
1815       case QCBOR_TYPE_INT64:
1816          pDecodedItem->label.int64 = LabelItem.val.int64;
1817          break;
1818 
1819 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1820       case QCBOR_TYPE_UINT64:
1821          pDecodedItem->label.uint64 = LabelItem.val.uint64;
1822          break;
1823 
1824       case QCBOR_TYPE_TEXT_STRING:
1825       case QCBOR_TYPE_BYTE_STRING:
1826          pDecodedItem->label.string = LabelItem.val.string;
1827          break;
1828 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1829 
1830       default:
1831          uErr = QCBOR_ERR_MAP_LABEL_TYPE;
1832          goto Done;
1833    }
1834 
1835 Done:
1836    return uErr;
1837 }
1838 
1839 
1840 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1841 /**
1842  * @brief Peek and see if next data item is a break;
1843  *
1844  * param[in]  pUIB            UsefulInputBuf to read from.
1845  * @param[out] pbNextIsBreak   Indicate if next was a break or not.
1846  *
1847  * @return  Any decoding error.
1848  *
1849  * See if next item is a CBOR break. If it is, it is consumed,
1850  * if not it is not consumed.
1851 */
1852 static QCBORError
QCBOR_Private_NextIsBreak(QCBORDecodeContext * pMe,bool * pbNextIsBreak)1853 QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
1854 {
1855    *pbNextIsBreak = false;
1856    if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
1857       QCBORItem Peek;
1858       size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
1859       QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
1860       if(uReturn != QCBOR_SUCCESS) {
1861          return uReturn;
1862       }
1863       if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1864          /* It is not a break, rewind so it can be processed normally. */
1865          UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
1866       } else {
1867          *pbNextIsBreak = true;
1868       }
1869    }
1870 
1871    return QCBOR_SUCCESS;
1872 }
1873 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1874 
1875 
1876 /**
1877  * @brief Ascend up nesting levels if all items in them have been consumed.
1878  *
1879  * @param[in] pMe       The decode context.
1880  * @param[in] bMarkEnd  If true mark end of maps/arrays with count of zero.
1881  * @param[out] pbBreak  Set to true if extra break was consumed.
1882  *
1883  * An item was just consumed, now figure out if it was the
1884  * end of an array/map map that can be closed out. That
1885  * may in turn close out the above array/map...
1886  *
1887  * When ascending indefinite-length arrays and maps, this will correctly
1888  * consume the break for the level above. This is a problem for the
1889  * implementation of QCBORDecode_GetArray() that must not return
1890  * that break. @c pbBreak is set to true to indicate that one
1891  * byte should be removed.
1892  *
1893  * Improvement: this could reduced further if indef is disabled
1894  */
1895 static QCBORError
QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext * pMe,bool bMarkEnd,bool * pbBreak)1896 QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd, bool *pbBreak)
1897 {
1898    QCBORError uReturn;
1899 
1900    /* Loop ascending nesting levels as long as there is ascending to do */
1901    while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1902       if(pbBreak) {
1903          *pbBreak = false;
1904       }
1905 
1906       if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1907          /* Nesting level is bstr-wrapped CBOR */
1908 
1909          /* Ascent for bstr-wrapped CBOR is always by explicit call
1910           * so no further ascending can happen.
1911           */
1912          break;
1913 
1914       } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1915          /* Level is a definite-length array/map */
1916 
1917          /* Decrement the item count the definite-length array/map */
1918          DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1919          if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
1920              /* Didn't close out array/map, so all work here is done */
1921              break;
1922           }
1923           /* All items in a definite-length array were consumed so it
1924            * is time to ascend one level. This happens below.
1925            */
1926 
1927 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1928       } else {
1929          /* Level is an indefinite-length array/map. */
1930 
1931          /* Check for a break which is what ends indefinite-length arrays/maps */
1932          bool bIsBreak = false;
1933          uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
1934          if(uReturn != QCBOR_SUCCESS) {
1935             goto Done;
1936          }
1937 
1938          if(!bIsBreak) {
1939             /* Not a break so array/map does not close out. All work is done */
1940             break;
1941          }
1942 
1943          /* It was a break in an indefinitelength map / array so
1944           * it is time to ascend one level.
1945           */
1946          if(pbBreak) {
1947             *pbBreak = true;
1948          }
1949 
1950 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1951       }
1952 
1953 
1954       /* All items in the array/map have been consumed. */
1955 
1956       /* But ascent in bounded mode is only by explicit call to
1957        * QCBORDecode_ExitBoundedMode().
1958        */
1959       if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
1960          /* Set the count to zero for definite-length arrays to indicate
1961          * cursor is at end of bounded array/map */
1962          if(bMarkEnd) {
1963             /* Used for definite and indefinite to signal end */
1964             DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
1965 
1966          }
1967          break;
1968       }
1969 
1970       /* Finally, actually ascend one level. */
1971       DecodeNesting_Ascend(&(pMe->nesting));
1972    }
1973 
1974    uReturn = QCBOR_SUCCESS;
1975 
1976 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1977 Done:
1978 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1979 
1980    return uReturn;
1981 }
1982 
1983 
1984 /**
1985  * @brief Ascending & Descending out of nesting levels (decode layer 2).
1986  *
1987  * @param[in] pMe            Decoder context
1988  * @param[out] pbBreak       Set to true if extra break was consumed.
1989  * @param[out] pDecodedItem  The decoded item that work is done on.
1990 
1991  * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
1992  *                                           features
1993  * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
1994  * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
1995  * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
1996  * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
1997  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1998  *                                           of half-precision disabled
1999  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
2000  *                                           float decode is disabled.
2001  * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
2002  *                                           simple type in input.
2003  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
2004  *                                              in input, but indefinite
2005  *                                              lengths disabled.
2006  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
2007  *                                           but no string allocator.
2008  * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
2009  * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
2010  *                                               input, but indefinite-length
2011  *                                               strings are disabled.
2012  * @retval QCBOR_ERR_TOO_MANY_TAGS           Too many tag numbers on item.
2013  * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array.
2014  * @retval QCBOR_ERR_MAP_LABEL_TYPE          Map label not string or integer.
2015  * @retval QCBOR_ERR_NO_MORE_ITEMS           Need more items for map or array.
2016  * @retval QCBOR_ERR_BAD_BREAK               Indefinite-length break in wrong
2017  *                                           place.
2018  * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP  Nesting deeper than QCBOR
2019  *                                                  can handle.
2020  *
2021  * This handles the traversal descending into and asecnding out of
2022  * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
2023  * definite- and indefinte-length maps and arrays by looking at the
2024  * item count or finding CBOR breaks.  It detects the ends of the
2025  * top-level sequence and of bstr-wrapped CBOR by byte count.
2026  */
2027 static QCBORError
QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext * pMe,bool * pbBreak,QCBORItem * pDecodedItem)2028 QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
2029                                       bool               *pbBreak,
2030                                       QCBORItem          *pDecodedItem)
2031 {
2032    QCBORError uReturn;
2033    /* ==== First: figure out if at the end of a traversal ==== */
2034 
2035    /* If out of bytes to consume, it is either the end of the
2036     * top-level sequence of some bstr-wrapped CBOR that was entered.
2037     *
2038     * In the case of bstr-wrapped CBOR, the length of the
2039     * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
2040     * the bstr-wrapped CBOR is exited, the length is set back to the
2041     * top-level's length or to the next highest bstr-wrapped CBOR.
2042    */
2043    if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
2044       uReturn = QCBOR_ERR_NO_MORE_ITEMS;
2045       goto Done;
2046    }
2047 
2048    /* Check to see if at the end of a bounded definite-length map or
2049     * array. The check for a break ending indefinite-length array is
2050     * later in QCBORDecode_NestLevelAscender().
2051     */
2052    if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
2053       uReturn = QCBOR_ERR_NO_MORE_ITEMS;
2054       goto Done;
2055    }
2056 
2057    /* ==== Next: not at the end, so get another item ==== */
2058    uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
2059    if(QCBORDecode_IsUnrecoverableError(uReturn)) {
2060       /* Error is so bad that traversal is not possible. */
2061       goto Done;
2062    }
2063 
2064    /* Record the nesting level for this data item before processing
2065     * any of decrementing and descending.
2066     */
2067    pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
2068 
2069 
2070    /* ==== Next: Process the item for descent, ascent, decrement... ==== */
2071    if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
2072       /* If the new item is a map or array, descend.
2073        *
2074        * Empty indefinite-length maps and arrays are descended into,
2075        * but then ascended out of in the next chunk of code.
2076        *
2077        * Maps and arrays do count as items in the map/array that
2078        * encloses them so a decrement needs to be done for them too,
2079        * but that is done only when all the items in them have been
2080        * processed, not when they are opened with the exception of an
2081        * empty map or array.
2082        */
2083       QCBORError uDescendErr;
2084       uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
2085                                                 pDecodedItem->uDataType,
2086                                                 pDecodedItem->val.uCount);
2087       if(uDescendErr != QCBOR_SUCCESS) {
2088          /* This error is probably a traversal error and it overrides
2089           * the non-traversal error.
2090           */
2091          uReturn = uDescendErr;
2092          goto Done;
2093       }
2094    }
2095 
2096    if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2097        QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2098        QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
2099       /* The following cases are handled here:
2100        *  - A non-aggregate item like an integer or string
2101        *  - An empty definite-length map or array
2102        *  - An indefinite-length map or array that might be empty or might not.
2103        *
2104        * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2105        * for an definite-length map/array and break detection for an
2106        * indefinite-0length map/array. If the end of the map/array was
2107        * reached, then it ascends nesting levels, possibly all the way
2108        * to the top level.
2109        */
2110       QCBORError uAscendErr;
2111       uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true, pbBreak);
2112       if(uAscendErr != QCBOR_SUCCESS) {
2113          /* This error is probably a traversal error and it overrides
2114           * the non-traversal error.
2115           */
2116          uReturn = uAscendErr;
2117          goto Done;
2118       }
2119    }
2120 
2121    /* ==== Last: tell the caller the nest level of the next item ==== */
2122    /* Tell the caller what level is next. This tells them what
2123     * maps/arrays were closed out and makes it possible for them to
2124     * reconstruct the tree with just the information returned in a
2125     * QCBORItem.
2126    */
2127    if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
2128       /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
2129       pDecodedItem->uNextNestLevel = 0;
2130    } else {
2131       pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
2132    }
2133 
2134 Done:
2135    return uReturn;
2136 }
2137 
2138 
2139 #ifndef QCBOR_DISABLE_TAGS
2140 /**
2141  * @brief Shift 0th tag out of the tag list.
2142  *
2143  * pDecodedItem[in,out]  The data item to convert.
2144  *
2145  * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2146  * shifted into empty slot at the end of the tag list.
2147  */
2148 static void
QCBOR_Private_ShiftTags(QCBORItem * pDecodedItem)2149 QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
2150 {
2151    for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2152       pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2153    }
2154    pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
2155 }
2156 #endif /* QCBOR_DISABLE_TAGS */
2157 
2158 
2159 /**
2160  * @brief Convert different epoch date formats in to the QCBOR epoch date format
2161  *
2162  * pDecodedItem[in,out]  The data item to convert.
2163  *
2164  * @retval QCBOR_ERR_DATE_OVERFLOW              65-bit negative integer.
2165  * @retval QCBOR_ERR_FLOAT_DATE_DISABLED        Float-point date in input,
2166  *                                              floating-point date disabled.
2167  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED         Float-point date in input,
2168  *                                              all floating-point disabled.
2169  * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT  Unexpected and unrecoverable
2170  *                                              error decoding date.
2171  *
2172  * The epoch date tag defined in QCBOR allows for floating-point
2173  * dates. It even allows a protocol to flop between date formats when
2174  * ever it wants.  Floating-point dates aren't that useful as they are
2175  * only needed for dates beyond the age of the earth.
2176  *
2177  * This converts all the date formats into one format of an unsigned
2178  * integer plus a floating-point fraction.
2179  */
2180 static QCBORError
QCBOR_Private_DecodeDateEpoch(QCBORItem * pDecodedItem)2181 QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
2182 {
2183    QCBORError uReturn = QCBOR_SUCCESS;
2184 
2185 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
2186    pDecodedItem->val.epochDate.fSecondsFraction = 0;
2187 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
2188 
2189    switch (pDecodedItem->uDataType) {
2190 
2191       case QCBOR_TYPE_INT64:
2192          pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2193          break;
2194 
2195       case QCBOR_TYPE_UINT64:
2196          /* This only happens for CBOR type 0 > INT64_MAX so it is
2197           * always an overflow.
2198           */
2199          uReturn = QCBOR_ERR_DATE_OVERFLOW;
2200          goto Done;
2201          break;
2202 
2203       case QCBOR_TYPE_DOUBLE:
2204       case QCBOR_TYPE_FLOAT:
2205 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
2206       {
2207          /* Convert working value to double if input was a float */
2208          const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
2209                    pDecodedItem->val.dfnum :
2210                    (double)pDecodedItem->val.fnum;
2211 
2212          /* The conversion from float to integer requires overflow
2213           * detection since floats can be much larger than integers.
2214           * This implementation errors out on these large float values
2215           * since they are beyond the age of the earth.
2216           *
2217           * These constants for the overflow check are computed by the
2218           * compiler. They are not computed at run time.
2219           *
2220           * The factor of 0x7ff is added/subtracted to avoid a
2221           * rounding error in the wrong direction when the compiler
2222           * computes these constants. There is rounding because a
2223           * 64-bit integer has 63 bits of precision where a double
2224           * only has 53 bits. Without the 0x7ff factor, the compiler
2225           * may round up and produce a double for the bounds check
2226           * that is larger than can be stored in a 64-bit integer. The
2227           * amount of 0x7ff is picked because it has 11 bits set.
2228           *
2229           * Without the 0x7ff there is a ~30 minute range of time
2230           * values 10 billion years in the past and in the future
2231           * where this code could go wrong. Some compilers
2232           * generate a warning or error without the 0x7ff.
2233           */
2234          const double dDateMax = (double)(INT64_MAX - 0x7ff);
2235          const double dDateMin = (double)(INT64_MIN + 0x7ff);
2236 
2237          if(isnan(d) || d > dDateMax || d < dDateMin) {
2238             uReturn = QCBOR_ERR_DATE_OVERFLOW;
2239             goto Done;
2240          }
2241 
2242          /* The actual conversion */
2243          pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
2244          pDecodedItem->val.epochDate.fSecondsFraction =
2245                            d - (double)pDecodedItem->val.epochDate.nSeconds;
2246       }
2247 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
2248 
2249          uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
2250          goto Done;
2251 
2252 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
2253          break;
2254 
2255       default:
2256          /* It's the arrays and maps that are unrecoverable because
2257           * they are not consumed here. Since this is just an error
2258           * condition, no extra code is added here to make the error
2259           * recoverable for non-arrays and maps like strings. */
2260          uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
2261          goto Done;
2262    }
2263 
2264    pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2265 
2266 Done:
2267    return uReturn;
2268 }
2269 
2270 
2271 /**
2272  * @brief Convert the days epoch date.
2273  *
2274  * pDecodedItem[in,out]  The data item to convert.
2275  *
2276  * @retval QCBOR_ERR_DATE_OVERFLOW              65-bit negative integer.
2277  * @retval QCBOR_ERR_FLOAT_DATE_DISABLED        Float-point date in input,
2278  *                                              floating-point date disabled.
2279  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED         Float-point date in input,
2280  *                                              all floating-point disabled.
2281  * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT  Unexpected and unrecoverable
2282  *                                              error decoding date.
2283  *
2284  * This is much simpler than the other epoch date format because
2285  * floating-porint is not allowed. This is mostly a simple type check.
2286  */
2287 static QCBORError
QCBOR_Private_DecodeDaysEpoch(QCBORItem * pDecodedItem)2288 QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
2289 {
2290    QCBORError uReturn = QCBOR_SUCCESS;
2291 
2292    switch (pDecodedItem->uDataType) {
2293 
2294       case QCBOR_TYPE_INT64:
2295          pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2296          break;
2297 
2298       case QCBOR_TYPE_UINT64:
2299          /* This only happens for CBOR type 0 > INT64_MAX so it is
2300           * always an overflow.
2301           */
2302          uReturn = QCBOR_ERR_DATE_OVERFLOW;
2303          goto Done;
2304          break;
2305 
2306       default:
2307          /* It's the arrays and maps that are unrecoverable because
2308           * they are not consumed here. Since this is just an error
2309           * condition, no extra code is added here to make the error
2310           * recoverable for non-arrays and maps like strings. */
2311          uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
2312          goto Done;
2313          break;
2314    }
2315 
2316    pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2317 
2318 Done:
2319    return uReturn;
2320 }
2321 
2322 
2323 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
2324 
2325 /* Forward declaration is necessary for
2326  * QCBORDecode_MantissaAndExponent().  to be able to decode bignum
2327  * tags in the mantissa. If the mantissa is a decimal fraction or big
2328  * float in error, this will result in a recurive call to
2329  * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2330  * correctly and the correct error is returned.
2331  */
2332 static QCBORError
2333 QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2334                                       QCBORItem          *pDecodedItem);
2335 
2336 
2337 /**
2338  * @brief Decode decimal fractions and big floats.
2339  *
2340  * @param[in] pMe               The decode context.
2341  * @param[in,out] pDecodedItem  On input the array data item that
2342  *                              holds the mantissa and exponent.  On
2343  *                              output the decoded mantissa and
2344  *                              exponent.
2345  *
2346  * @returns  Decoding errors from getting primitive data items or
2347  *           \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2348  *
2349  * When called pDecodedItem must be the array with two members, the
2350  * exponent and mantissa.
2351  *
2352  * This will fetch and decode the exponent and mantissa and put the
2353  * result back into pDecodedItem.
2354  *
2355  * This does no checking or processing of tag numbers. That is to be
2356  * done by the code that calls this.
2357  *
2358  * This stuffs the type of the mantissa into pDecodedItem with the expectation
2359  * the caller will process it.
2360  */
2361 static QCBORError
QCBORDecode_Private_ExpMantissa(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)2362 QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2363                                 QCBORItem          *pDecodedItem)
2364 {
2365    QCBORError uReturn;
2366 
2367    /* --- Make sure it is an array; track nesting level of members --- */
2368    if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
2369       uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2370       goto Done;
2371    }
2372 
2373    /* A check for pDecodedItem->val.uCount == 2 would work for
2374     * definite-length arrays, but not for indefinite. Instead remember
2375     * the nesting level the two integers must be at, which is one
2376     * deeper than that of the array.
2377     */
2378    const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2379 
2380    /* --- Get the exponent --- */
2381    QCBORItem exponentItem;
2382    uReturn = QCBORDecode_GetNext(pMe, &exponentItem);
2383    if(uReturn != QCBOR_SUCCESS) {
2384       goto Done;
2385    }
2386    if(exponentItem.uNestingLevel != nNestLevel) {
2387       /* Array is empty or a map/array encountered when expecting an int */
2388       uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2389       goto Done;
2390    }
2391    if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
2392      /* Data arriving as an unsigned int < INT64_MAX has been
2393       * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2394       * also means that the only data arriving here of type
2395       * QCBOR_TYPE_UINT64 data will be too large for this to handle
2396       * and thus an error that will get handled in the next else.
2397       */
2398      pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2399    } else {
2400       /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2401       uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2402       goto Done;
2403    }
2404 
2405    /* --- Get the mantissa --- */
2406    QCBORItem mantissaItem;
2407    uReturn = QCBORDecode_GetNext(pMe, &mantissaItem);
2408    if(uReturn != QCBOR_SUCCESS) {
2409       goto Done;
2410    }
2411    if(mantissaItem.uNestingLevel != nNestLevel) {
2412       /* Mantissa missing or map/array encountered when expecting number */
2413       uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2414       goto Done;
2415    }
2416    /* Stuff the mantissa data type into the item to send it up to the
2417     * the next level. */
2418    pDecodedItem->uDataType = mantissaItem.uDataType;
2419    if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
2420       /* Data arriving as an unsigned int < INT64_MAX has been
2421        * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2422        * also means that the only data arriving here of type
2423        * QCBOR_TYPE_UINT64 data will be too large for this to handle
2424        * and thus an error that will get handled in an else below.
2425        */
2426       pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
2427 #ifndef QCBOR_DISABLE_TAGS
2428       /* With tags fully disabled a big number mantissa will error out
2429        * in the call to QCBORDecode_GetNextWithTags() because it has
2430        * a tag number.
2431        */
2432    }  else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2433               mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
2434       /* Got a good big num mantissa */
2435       pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
2436 #endif /* QCBOR_DISABLE_TAGS */
2437    } else {
2438       /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2439       uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2440       goto Done;
2441    }
2442 
2443    /* --- Check that array only has the two numbers --- */
2444    if(mantissaItem.uNextNestLevel == nNestLevel) {
2445       /* Extra items in the decimal fraction / big float */
2446       /* Improvement: this should probably be an unrecoverable error. */
2447       uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2448       goto Done;
2449    }
2450    pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
2451 
2452 Done:
2453   return uReturn;
2454 }
2455 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
2456 
2457 
2458 #ifndef QCBOR_DISABLE_TAGS
2459 
2460 #ifndef QCBOR_DISABLE_UNCOMMON_TAGS
2461 /**
2462  * @brief Decode the MIME type tag
2463  *
2464  * @param[in,out] pDecodedItem   The item to decode.
2465  *
2466  *  Handle the text and binary MIME type tags. Slightly too complicated
2467  *  f or ProcessTaggedString() because the RFC 7049 MIME type was
2468  *  incorreclty text-only.
2469  */
2470 static QCBORError
QCBOR_Private_DecodeMIME(QCBORItem * pDecodedItem)2471 QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
2472 {
2473    if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2474       pDecodedItem->uDataType = QCBOR_TYPE_MIME;
2475    } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
2476       pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2477    } else {
2478       /* It's the arrays and maps that are unrecoverable because
2479        * they are not consumed here. Since this is just an error
2480        * condition, no extra code is added here to make the error
2481        * recoverable for non-arrays and maps like strings. */
2482       return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
2483    }
2484 
2485    return QCBOR_SUCCESS;
2486 }
2487 #endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
2488 
2489 /**
2490  * Table of CBOR tags whose content is either a text string or a byte
2491  * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2492  * of uQCBORtype indicates the content should be a byte string rather
2493  * than a text string
2494  */
2495 struct StringTagMapEntry {
2496    uint16_t uTagNumber;
2497    uint8_t  uQCBORtype;
2498 };
2499 
2500 #define IS_BYTE_STRING_BIT 0x80
2501 #define QCBOR_TYPE_MASK   ~IS_BYTE_STRING_BIT
2502 
2503 static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
2504    {CBOR_TAG_DATE_STRING,   QCBOR_TYPE_DATE_STRING},
2505    {CBOR_TAG_DAYS_STRING,   QCBOR_TYPE_DAYS_STRING},
2506    {CBOR_TAG_POS_BIGNUM,    QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2507    {CBOR_TAG_NEG_BIGNUM,    QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2508    {CBOR_TAG_CBOR,          QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2509    {CBOR_TAG_URI,           QCBOR_TYPE_URI},
2510 #ifndef QCBOR_DISABLE_UNCOMMON_TAGS
2511    {CBOR_TAG_B64URL,        QCBOR_TYPE_BASE64URL},
2512    {CBOR_TAG_B64,           QCBOR_TYPE_BASE64},
2513    {CBOR_TAG_REGEX,         QCBOR_TYPE_REGEX},
2514    {CBOR_TAG_BIN_UUID,      QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
2515 #endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
2516    {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2517    {CBOR_TAG_INVALID16,     QCBOR_TYPE_NONE}
2518 };
2519 
2520 
2521 /**
2522  * @brief Process standard CBOR tags whose content is a string
2523  *
2524  * @param[in] uTag              The tag.
2525  * @param[in,out] pDecodedItem  The data item.
2526  *
2527  * @returns  This returns QCBOR_SUCCESS if the tag was procssed,
2528  *           \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2529  *           \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
2530  *
2531  * Process the CBOR tags that whose content is a byte string or a text
2532  * string and for which the string is just passed on to the caller.
2533  *
2534  * This maps the CBOR tag to the QCBOR type and checks the content
2535  * type.  Nothing more. It may not be the most important
2536  * functionality, but it part of implementing as much of RFC 8949 as
2537  * possible.
2538  */
2539 static QCBORError
QCBOR_Private_ProcessTaggedString(uint16_t uTag,QCBORItem * pDecodedItem)2540 QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
2541 {
2542    /* This only works on tags that were not mapped; no need for other yet */
2543    if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2544       return QCBOR_ERR_UNSUPPORTED;
2545    }
2546 
2547    unsigned uIndex;
2548    for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2549       if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
2550          break;
2551       }
2552    }
2553 
2554    const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
2555    if(uQCBORType == QCBOR_TYPE_NONE) {
2556       /* repurpose this error to mean not handled here */
2557       return QCBOR_ERR_UNSUPPORTED;
2558    }
2559 
2560    uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2561    if(uQCBORType & IS_BYTE_STRING_BIT) {
2562       uExpectedType = QCBOR_TYPE_BYTE_STRING;
2563    }
2564 
2565    if(pDecodedItem->uDataType != uExpectedType) {
2566       /* It's the arrays and maps that are unrecoverable because
2567        * they are not consumed here. Since this is just an error
2568        * condition, no extra code is added here to make the error
2569        * recoverable for non-arrays and maps like strings. */
2570       return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
2571    }
2572 
2573    pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
2574    return QCBOR_SUCCESS;
2575 }
2576 #endif /* QCBOR_DISABLE_TAGS */
2577 
2578 
2579 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2580 /**
2581  * @brief Figures out data type for exponent mantissa tags.
2582  *
2583  * @param[in] uTagToProcess  Either @ref CBOR_TAG_DECIMAL_FRACTION or
2584  *                           @ref CBOR_TAG_BIG_FLOAT.
2585  * @param[in] pDecodedItem   Item being decoded.
2586  *
2587  * @returns One of the 6 values between \ref QCBOR_TYPE_DECIMAL_FRACTION
2588  *          and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
2589  *
2590  * Does mapping between a CBOR tag number and a QCBOR type.  with a
2591  * little bit of logic and arithmatic.
2592  *
2593  * Used in serveral contexts. Does the work where sometimes the data
2594  * item is explicitly tagged and sometimes not.
2595  */
2596 static uint8_t
QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,const QCBORItem * pDecodedItem)2597 QCBOR_Private_ExpMantissaDataType(const uint16_t   uTagToProcess,
2598                                   const QCBORItem *pDecodedItem)
2599 {
2600    uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2601                                        QCBOR_TYPE_DECIMAL_FRACTION :
2602                                        QCBOR_TYPE_BIGFLOAT;
2603    if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2604       uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2605    }
2606    return uBase;
2607 }
2608 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2609 
2610 
2611 /**
2612  * @brief Decode tag content for select tags (decoding layer 1).
2613  *
2614  * @param[in] pMe            The decode context.
2615  * @param[out] pDecodedItem  The decoded item.
2616  *
2617  * @return Decoding error code.
2618  *
2619  * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2620  * but the whole tag was not decoded. Here, the whole tags (tag number
2621  * and tag content) that are supported by QCBOR are decoded. This is a
2622  * quick pass through for items that are not tags.
2623  */
2624 static QCBORError
QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)2625 QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2626                                       QCBORItem          *pDecodedItem)
2627 {
2628    QCBORError uReturn;
2629 
2630    uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pDecodedItem);
2631    if(uReturn != QCBOR_SUCCESS) {
2632       goto Done;
2633    }
2634 
2635 #ifndef QCBOR_DISABLE_TAGS
2636    /* When there are no tag numbers for the item, this exits first
2637     * thing and effectively does nothing.
2638     *
2639     * This loops over all the tag numbers accumulated for this item
2640     * trying to decode and interpret them. This stops at the end of
2641     * the list or at the first tag number that can't be interpreted by
2642     * this code. This is effectively a recursive processing of the
2643     * tags number list that handles nested tags.
2644     */
2645    while(1) {
2646       /* Don't bother to unmap tags via QCBORITem.uTags since this
2647        * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2648        */
2649       const uint16_t uTagToProcess = pDecodedItem->uTags[0];
2650 
2651       if(uTagToProcess == CBOR_TAG_INVALID16) {
2652          /* Hit the end of the tag list. A successful exit. */
2653          break;
2654 
2655       } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
2656          uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
2657 
2658       } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2659          uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
2660 
2661 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
2662       } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2663                 uTagToProcess == CBOR_TAG_BIGFLOAT) {
2664          uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
2665          /* --- Which is it, decimal fraction or a bigfloat? --- */
2666          pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
2667 
2668 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
2669 #ifndef QCBOR_DISABLE_UNCOMMON_TAGS
2670       } else if(uTagToProcess == CBOR_TAG_MIME ||
2671                 uTagToProcess == CBOR_TAG_BINARY_MIME) {
2672          uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
2673 #endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
2674 
2675       } else {
2676          /* See if it is a passthrough byte/text string tag; process if so */
2677          uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
2678 
2679          if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2680             /* It wasn't a passthrough byte/text string tag so it is
2681              * an unknown tag. This is the exit from the loop on the
2682              * first unknown tag.  It is a successful exit.
2683              */
2684             uReturn = QCBOR_SUCCESS;
2685             break;
2686          }
2687       }
2688 
2689       if(uReturn != QCBOR_SUCCESS) {
2690          /* Error exit from the loop */
2691          break;
2692       }
2693 
2694       /* A tag was successfully processed, shift it out of the list of
2695        * tags returned. This is the loop increment.
2696        */
2697       QCBOR_Private_ShiftTags(pDecodedItem);
2698    }
2699 #endif /* QCBOR_DISABLE_TAGS */
2700 
2701 Done:
2702    return uReturn;
2703 }
2704 
2705 
2706 /*
2707  * Public function, see header qcbor/qcbor_decode.h file
2708  */
2709 QCBORError
QCBORDecode_GetNext(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)2710 QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2711 {
2712    QCBORError uErr;
2713    uErr =  QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
2714    if(uErr != QCBOR_SUCCESS) {
2715       pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
2716       pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2717    }
2718    return uErr;
2719 }
2720 
2721 
2722 /*
2723  * Public function, see header qcbor/qcbor_decode.h file
2724  */
2725 QCBORError
QCBORDecode_PeekNext(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)2726 QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2727 {
2728    const QCBORDecodeNesting SaveNesting = pMe->nesting;
2729    const UsefulInputBuf Save = pMe->InBuf;
2730 
2731    QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2732 
2733    pMe->nesting = SaveNesting;
2734    pMe->InBuf = Save;
2735 
2736    return uErr;
2737 }
2738 
2739 
2740 /*
2741  * Public function, see header qcbor/qcbor_decode.h file
2742  */
2743 void
QCBORDecode_VPeekNext(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)2744 QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2745 {
2746    if(pMe->uLastError != QCBOR_SUCCESS) {
2747       pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
2748       pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2749       return;
2750    }
2751 
2752    pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2753 }
2754 
2755 
2756 static void
QCBORDecode_Private_CopyTags(QCBORDecodeContext * pMe,const QCBORItem * pItem)2757 QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2758 {
2759 #ifndef QCBOR_DISABLE_TAGS
2760    memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2761 #else
2762    (void)pMe;
2763    (void)pItem;
2764 #endif
2765 }
2766 
2767 /*
2768  * Public function, see header qcbor/qcbor_decode.h file
2769  */
2770 void
QCBORDecode_VGetNext(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)2771 QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2772 {
2773    if(pMe->uLastError != QCBOR_SUCCESS) {
2774       pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
2775       pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2776       return;
2777    }
2778 
2779    pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2780    QCBORDecode_Private_CopyTags(pMe, pDecodedItem);
2781 }
2782 
2783 
2784 /*
2785  * Public function, see header qcbor/qcbor_decode.h file
2786  */
2787 QCBORError
QCBORDecode_GetNextWithTags(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem,QCBORTagListOut * pTags)2788 QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2789                             QCBORItem          *pDecodedItem,
2790                             QCBORTagListOut    *pTags)
2791 {
2792 #ifndef QCBOR_DISABLE_TAGS
2793 
2794    QCBORError uReturn;
2795 
2796    uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2797    if(uReturn != QCBOR_SUCCESS) {
2798       return uReturn;
2799    }
2800 
2801    if(pTags != NULL) {
2802       pTags->uNumUsed = 0;
2803       /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
2804       for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2805          if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
2806             continue;
2807          }
2808          if(pTags->uNumUsed >= pTags->uNumAllocated) {
2809             return QCBOR_ERR_TOO_MANY_TAGS;
2810          }
2811          pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
2812          pTags->uNumUsed++;
2813       }
2814    }
2815 
2816    return QCBOR_SUCCESS;
2817 
2818 #else /* QCBOR_DISABLE_TAGS */
2819    (void)pMe;
2820    (void)pDecodedItem;
2821    (void)pTags;
2822    return QCBOR_ERR_TAGS_DISABLED;
2823 #endif /* QCBOR_DISABLE_TAGS */
2824 }
2825 
2826 
2827 /*
2828  * Public function, see header qcbor/qcbor_decode.h file
2829  */
2830 bool
QCBORDecode_IsTagged(QCBORDecodeContext * pMe,const QCBORItem * pItem,uint64_t uTag)2831 QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2832                      const QCBORItem   *pItem,
2833                      uint64_t           uTag)
2834 {
2835 #ifndef QCBOR_DISABLE_TAGS
2836    for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2837       if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
2838          break;
2839       }
2840       if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
2841          return true;
2842       }
2843    }
2844 #else /* QCBOR_TAGS_DISABLED */
2845    (void)pMe;
2846    (void)pItem;
2847    (void)uTag;
2848 #endif /* QCBOR_TAGS_DISABLED */
2849 
2850    return false;
2851 }
2852 
2853 
2854 /*
2855  * Public function, see header qcbor/qcbor_decode.h file
2856  */
2857 QCBORError
QCBORDecode_PartialFinish(QCBORDecodeContext * pMe,size_t * puConsumed)2858 QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
2859 {
2860    if(puConsumed != NULL) {
2861       *puConsumed = pMe->InBuf.cursor;
2862    }
2863 
2864    QCBORError uReturn = pMe->uLastError;
2865 
2866    if(uReturn != QCBOR_SUCCESS) {
2867       goto Done;
2868    }
2869 
2870    /* Error out if all the maps/arrays are not closed out */
2871    if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
2872       uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
2873       goto Done;
2874    }
2875 
2876    /* Error out if not all the bytes are consumed */
2877    if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
2878       uReturn = QCBOR_ERR_EXTRA_BYTES;
2879    }
2880 
2881 Done:
2882    return uReturn;
2883 }
2884 
2885 
2886 /*
2887  * Public function, see header qcbor/qcbor_decode.h file
2888  */
2889 QCBORError
QCBORDecode_Finish(QCBORDecodeContext * pMe)2890 QCBORDecode_Finish(QCBORDecodeContext *pMe)
2891 {
2892 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
2893    /* Call the destructor for the string allocator if there is one.
2894     * Always called, even if there are errors; always have to clean up.
2895     */
2896    StringAllocator_Destruct(&(pMe->StringAllocator));
2897 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
2898 
2899    return QCBORDecode_PartialFinish(pMe, NULL);
2900 }
2901 
2902 
2903 /*
2904  * Public function, see header qcbor/qcbor_decode.h file
2905  */
2906 uint64_t
QCBORDecode_GetNthTag(QCBORDecodeContext * pMe,const QCBORItem * pItem,uint32_t uIndex)2907 QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2908                       const QCBORItem    *pItem,
2909                       uint32_t            uIndex)
2910 {
2911 #ifndef QCBOR_DISABLE_TAGS
2912    if(pItem->uDataType == QCBOR_TYPE_NONE) {
2913       return CBOR_TAG_INVALID64;
2914    }
2915    if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2916       return CBOR_TAG_INVALID64;
2917    } else {
2918       return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
2919    }
2920 #else /* QCBOR_DISABLE_TAGS */
2921    (void)pMe;
2922    (void)pItem;
2923    (void)uIndex;
2924 
2925    return CBOR_TAG_INVALID64;
2926 #endif /* QCBOR_DISABLE_TAGS */
2927 }
2928 
2929 
2930 /*
2931  * Public function, see header qcbor/qcbor_decode.h file
2932  */
2933 uint64_t
QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext * pMe,uint32_t uIndex)2934 QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2935                             uint32_t                  uIndex)
2936 {
2937 #ifndef QCBOR_DISABLE_TAGS
2938 
2939    if(pMe->uLastError != QCBOR_SUCCESS) {
2940       return CBOR_TAG_INVALID64;
2941    }
2942    if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2943       return CBOR_TAG_INVALID64;
2944    } else {
2945       return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
2946    }
2947 #else /* QCBOR_DISABLE_TAGS */
2948    (void)pMe;
2949    (void)uIndex;
2950 
2951    return CBOR_TAG_INVALID64;
2952 #endif /* QCBOR_DISABLE_TAGS */
2953 }
2954 
2955 
2956 
2957 
2958 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
2959 
2960 /* ===========================================================================
2961    MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
2962 
2963    This implements a simple sting allocator for indefinite-length
2964    strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2965    implements the function type QCBORStringAllocate and allows easy
2966    use of it.
2967 
2968    This particular allocator is built-in for convenience. The caller
2969    can implement their own.  All of this following code will get
2970    dead-stripped if QCBORDecode_SetMemPool() is not called.
2971 
2972    This is a very primitive memory allocator. It does not track
2973    individual allocations, only a high-water mark. A free or
2974    reallocation must be of the last chunk allocated.
2975 
2976    The size of the pool and offset to free memory are packed into the
2977    first 8 bytes of the memory pool so we don't have to keep them in
2978    the decode context. Since the address of the pool may not be
2979    aligned, they have to be packed and unpacked as if they were
2980    serialized data of the wire or such.
2981 
2982    The sizes packed in are uint32_t to be the same on all CPU types
2983    and simplify the code.
2984    ========================================================================== */
2985 
2986 
2987 static int
MemPool_Unpack(const void * pMem,uint32_t * puPoolSize,uint32_t * puFreeOffset)2988 MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
2989 {
2990    // Use of UsefulInputBuf is overkill, but it is convenient.
2991    UsefulInputBuf UIB;
2992 
2993    // Just assume the size here. It was checked during SetUp so
2994    // the assumption is safe.
2995    UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2996    *puPoolSize     = UsefulInputBuf_GetUint32(&UIB);
2997    *puFreeOffset   = UsefulInputBuf_GetUint32(&UIB);
2998    return UsefulInputBuf_GetError(&UIB);
2999 }
3000 
3001 
3002 static int
MemPool_Pack(UsefulBuf Pool,uint32_t uFreeOffset)3003 MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
3004 {
3005    // Use of UsefulOutBuf is overkill, but convenient. The
3006    // length check performed here is useful.
3007    UsefulOutBuf UOB;
3008 
3009    UsefulOutBuf_Init(&UOB, Pool);
3010    UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
3011    UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
3012    return UsefulOutBuf_GetError(&UOB);
3013 }
3014 
3015 
3016 /*
3017  Internal function for an allocation, reallocation free and destuct.
3018 
3019  Having only one function rather than one each per mode saves space in
3020  QCBORDecodeContext.
3021 
3022  Code Reviewers: THIS FUNCTION DOES POINTER MATH
3023  */
3024 static UsefulBuf
MemPool_Function(void * pPool,void * pMem,size_t uNewSize)3025 MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
3026 {
3027    UsefulBuf ReturnValue = NULLUsefulBuf;
3028 
3029    uint32_t uPoolSize;
3030    uint32_t uFreeOffset;
3031 
3032    if(uNewSize > UINT32_MAX) {
3033       // This allocator is only good up to 4GB.  This check should
3034       // optimize out if sizeof(size_t) == sizeof(uint32_t)
3035       goto Done;
3036    }
3037    const uint32_t uNewSize32 = (uint32_t)uNewSize;
3038 
3039    if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
3040       goto Done;
3041    }
3042 
3043    if(uNewSize) {
3044       if(pMem) {
3045          // REALLOCATION MODE
3046          // Calculate pointer to the end of the memory pool.  It is
3047          // assumed that pPool + uPoolSize won't wrap around by
3048          // assuming the caller won't pass a pool buffer in that is
3049          // not in legitimate memory space.
3050          const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
3051 
3052          // Check that the pointer for reallocation is in the range of the
3053          // pool. This also makes sure that pointer math further down
3054          // doesn't wrap under or over.
3055          if(pMem >= pPool && pMem < pPoolEnd) {
3056             // Offset to start of chunk for reallocation. This won't
3057             // wrap under because of check that pMem >= pPool.  Cast
3058             // is safe because the pool is always less than UINT32_MAX
3059             // because of check in QCBORDecode_SetMemPool().
3060             const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3061 
3062             // Check to see if the allocation will fit. uPoolSize -
3063             // uMemOffset will not wrap under because of check that
3064             // pMem is in the range of the uPoolSize by check above.
3065             if(uNewSize <= uPoolSize - uMemOffset) {
3066                ReturnValue.ptr = pMem;
3067                ReturnValue.len = uNewSize;
3068 
3069                // Addition won't wrap around over because uNewSize was
3070                // checked to be sure it is less than the pool size.
3071                uFreeOffset = uMemOffset + uNewSize32;
3072             }
3073          }
3074       } else {
3075          // ALLOCATION MODE
3076          // uPoolSize - uFreeOffset will not underflow because this
3077          // pool implementation makes sure uFreeOffset is always
3078          // smaller than uPoolSize through this check here and
3079          // reallocation case.
3080          if(uNewSize <= uPoolSize - uFreeOffset) {
3081             ReturnValue.len = uNewSize;
3082             ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
3083             uFreeOffset    += (uint32_t)uNewSize;
3084          }
3085       }
3086    } else {
3087       if(pMem) {
3088          // FREE MODE
3089          // Cast is safe because of limit on pool size in
3090          // QCBORDecode_SetMemPool()
3091          uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3092       } else {
3093          // DESTRUCT MODE
3094          // Nothing to do for this allocator
3095       }
3096    }
3097 
3098    UsefulBuf Pool = {pPool, uPoolSize};
3099    MemPool_Pack(Pool, uFreeOffset);
3100 
3101 Done:
3102    return ReturnValue;
3103 }
3104 
3105 
3106 /*
3107  * Public function, see header qcbor/qcbor_decode.h file
3108  */
3109 QCBORError
QCBORDecode_SetMemPool(QCBORDecodeContext * pMe,UsefulBuf Pool,bool bAllStrings)3110 QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3111                        UsefulBuf           Pool,
3112                        bool                bAllStrings)
3113 {
3114    // The pool size and free mem offset are packed into the beginning
3115    // of the pool memory. This compile time check makes sure the
3116    // constant in the header is correct.  This check should optimize
3117    // down to nothing.
3118 #ifdef _MSC_VER
3119 #pragma warning(push)
3120 #pragma warning(disable:4127) // conditional expression is constant
3121 #endif
3122    if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
3123       return QCBOR_ERR_MEM_POOL_SIZE;
3124    }
3125 #ifdef _MSC_VER
3126 #pragma warning(pop)
3127 #endif
3128 
3129    // The pool size and free offset packed in to the beginning of pool
3130    // memory are only 32-bits. This check will optimize out on 32-bit
3131    // machines.
3132    if(Pool.len > UINT32_MAX) {
3133       return QCBOR_ERR_MEM_POOL_SIZE;
3134    }
3135 
3136    // This checks that the pool buffer given is big enough.
3137    if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
3138       return QCBOR_ERR_MEM_POOL_SIZE;
3139    }
3140 
3141    QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
3142 
3143    return QCBOR_SUCCESS;
3144 }
3145 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
3146 
3147 
3148 
3149 
3150 /**
3151  * @brief Consume an entire map or array including its contents.
3152  *
3153  * @param[in]  pMe              The decoder context.
3154  * @param[in]  pItemToConsume   The array/map whose contents are to be
3155  *                              consumed.
3156  * @param[out] puNextNestLevel  The next nesting level after the item was
3157  *                              fully consumed.
3158  *
3159  * This may be called when @c pItemToConsume is not an array or
3160  * map. In that case, this is just a pass through for @c puNextNestLevel
3161  * since there is nothing to do.
3162  */
3163 static QCBORError
QCBORDecode_Private_ConsumeItem(QCBORDecodeContext * pMe,const QCBORItem * pItemToConsume,bool * pbBreak,uint8_t * puNextNestLevel)3164 QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3165                                 const QCBORItem    *pItemToConsume,
3166                                 bool               *pbBreak,
3167                                 uint8_t            *puNextNestLevel)
3168 {
3169    QCBORError uReturn;
3170    QCBORItem  Item;
3171 
3172    /* If it is a map or array, this will tell if it is empty. */
3173    const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3174 
3175    if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
3176       /* There is only real work to do for non-empty maps and arrays */
3177 
3178       /* This works for definite- and indefinite-length maps and
3179        * arrays by using the nesting level
3180        */
3181       do {
3182          uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pbBreak, &Item);
3183          if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3184             uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
3185             goto Done;
3186          }
3187       } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
3188 
3189       *puNextNestLevel = Item.uNextNestLevel;
3190 
3191       uReturn = QCBOR_SUCCESS;
3192 
3193    } else {
3194       /* pItemToConsume is not a map or array. Just pass the nesting
3195        * level through. */
3196       *puNextNestLevel = pItemToConsume->uNextNestLevel;
3197 
3198       uReturn = QCBOR_SUCCESS;
3199    }
3200 
3201 Done:
3202     return uReturn;
3203 }
3204 
3205 
3206 /*
3207  * Public function, see header qcbor/qcbor_decode.h file
3208  */
3209 void
QCBORDecode_VGetNextConsume(QCBORDecodeContext * pMe,QCBORItem * pDecodedItem)3210 QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
3211 {
3212    QCBORDecode_VGetNext(pMe, pDecodedItem);
3213 
3214    if(pMe->uLastError == QCBOR_SUCCESS) {
3215       pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem, NULL,
3216          &pDecodedItem->uNextNestLevel);
3217    }
3218 }
3219 
3220 
3221 /*
3222  * Public function, see header qcbor/qcbor_decode.h file
3223  */
3224 QCBORError
QCBORDecode_EndCheck(QCBORDecodeContext * pMe)3225 QCBORDecode_EndCheck(QCBORDecodeContext *pMe)
3226 {
3227    size_t     uCursorOffset;
3228    QCBORError uErr;
3229 
3230    uErr = QCBORDecode_GetError(pMe);
3231    if(uErr != QCBOR_SUCCESS) {
3232       return uErr;
3233    }
3234 
3235    uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3236 
3237    if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
3238       return QCBOR_ERR_NO_MORE_ITEMS;
3239    }
3240 
3241    return QCBOR_SUCCESS;
3242 }
3243 
3244 
3245 /**
3246  * @brief Rewind cursor to start as if map or array were just entered.
3247  *
3248  * @param[in]  pMe   The decoding context
3249  *
3250  * This affects the nesting tracking and the UsefulInputBuf.
3251  */
3252 static void
QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext * pMe)3253 QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
3254 {
3255    /* Reset nesting tracking to the deepest bounded level */
3256    DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3257 
3258    DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3259 
3260    /* Reposition traversal cursor to the start of the map/array */
3261    UsefulInputBuf_Seek(&(pMe->InBuf),
3262                        DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3263 }
3264 
3265 
3266 /*
3267  * Public function, see header qcbor/qcbor_decode.h file
3268  */
3269 void
QCBORDecode_Rewind(QCBORDecodeContext * pMe)3270 QCBORDecode_Rewind(QCBORDecodeContext *pMe)
3271 {
3272    if(pMe->nesting.pCurrentBounded != NULL) {
3273       /* In a bounded map, array or bstr-wrapped CBOR */
3274 
3275       if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3276          /* In bstr-wrapped CBOR. */
3277 
3278          /* Reposition traversal cursor to start of wrapping byte string */
3279          UsefulInputBuf_Seek(&(pMe->InBuf),
3280                              pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3281          DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3282 
3283       } else {
3284          /* In a map or array */
3285          QCBORDecode_Private_RewindMapOrArray(pMe);
3286       }
3287 
3288    } else {
3289       /* Not in anything bounded */
3290 
3291       /* Reposition traversal cursor to the start of input CBOR */
3292       UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3293 
3294       /* Reset nesting tracking to beginning of input. */
3295       DecodeNesting_Init(&(pMe->nesting));
3296    }
3297 
3298    pMe->uLastError = QCBOR_SUCCESS;
3299 }
3300 
3301 
3302 
3303 
3304 
3305 typedef struct {
3306    void               *pCBContext;
3307    QCBORItemCallback   pfCallback;
3308 } MapSearchCallBack;
3309 
3310 typedef struct {
3311    size_t   uStartOffset;
3312    uint16_t uItemCount;
3313 } MapSearchInfo;
3314 
3315 
3316 /**
3317  * @brief Search a map for a set of items.
3318  *
3319  * @param[in]  pMe           The decode context to search.
3320  * @param[in,out] pItemArray The items to search for and the items found.
3321  * @param[out] pInfo         Several bits of meta-info returned by search.
3322  * @param[in] pCallBack      Callback object or @c NULL.
3323  *
3324  * @retval QCBOR_ERR_NOT_ENTERED     Trying to search without entering a map.
3325  *
3326  * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3327  *                                   were found for one of the labels being
3328  *                                   search for. This duplicate detection is
3329  *                                   only performed for items in pItemArray,
3330  *                                   not every item in the map.
3331  *
3332  * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3333  *                                   wrong for the matchd label.
3334  *
3335  * @retval Also errors returned by QCBORDecode_GetNext().
3336  *
3337  * On input, \c pItemArray contains a list of labels and data types of
3338  * items to be found.
3339  *
3340  * On output, the fully retrieved items are filled in with values and
3341  * such. The label was matched, so it never changes.
3342  *
3343  * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3344  *
3345  * This also finds the ends of maps and arrays when they are exited.
3346  */
3347 static QCBORError
QCBORDecode_Private_MapSearch(QCBORDecodeContext * pMe,QCBORItem * pItemArray,MapSearchInfo * pInfo,MapSearchCallBack * pCallBack)3348 QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3349                               QCBORItem          *pItemArray,
3350                               MapSearchInfo      *pInfo,
3351                               MapSearchCallBack  *pCallBack)
3352 {
3353    QCBORError uReturn;
3354    uint64_t   uFoundItemBitMap = 0;
3355 
3356    if(pMe->uLastError != QCBOR_SUCCESS) {
3357       uReturn = pMe->uLastError;
3358       goto Done2;
3359    }
3360 
3361    if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
3362       pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3363       /* QCBOR_TYPE_NONE as first item indicates just looking
3364          for the end of an array, so don't give error. */
3365       uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3366       goto Done2;
3367    }
3368 
3369    if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3370       // It is an empty bounded array or map
3371       if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3372          // Just trying to find the end of the map or array
3373          pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
3374          uReturn = QCBOR_SUCCESS;
3375       } else {
3376          // Nothing is ever found in an empty array or map. All items
3377          // are marked as not found below.
3378          uReturn = QCBOR_SUCCESS;
3379       }
3380       goto Done2;
3381    }
3382 
3383    QCBORDecodeNesting SaveNesting;
3384    size_t uSavePos = UsefulInputBuf_Tell(&(pMe->InBuf));
3385    DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3386 
3387    /* Reposition to search from the start of the map / array */
3388    QCBORDecode_Private_RewindMapOrArray(pMe);
3389 
3390    /*
3391     Loop over all the items in the map or array. Each item
3392     could be a map or array, but label matching is only at
3393     the main level. This handles definite- and indefinite-
3394     length maps and arrays. The only reason this is ever
3395     called on arrays is to find their end position.
3396 
3397     This will always run over all items in order to do
3398     duplicate detection.
3399 
3400     This will exit with failure if it encounters an
3401     unrecoverable error, but continue on for recoverable
3402     errors.
3403 
3404     If a recoverable error occurs on a matched item, then
3405     that error code is returned.
3406     */
3407    const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
3408    if(pInfo) {
3409       pInfo->uItemCount = 0;
3410    }
3411    uint8_t       uNextNestLevel;
3412    do {
3413       /* Remember offset of the item because sometimes it has to be returned */
3414       const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3415 
3416       /* Get the item */
3417       QCBORItem Item;
3418       /* QCBORDecode_Private_GetNextTagContent() rather than GetNext()
3419        * because a label match is performed on recoverable errors to
3420        * be able to return the the error code for the found item. */
3421       QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
3422       if(QCBORDecode_IsUnrecoverableError(uResult)) {
3423          /* The map/array can't be decoded when unrecoverable errors occur */
3424          uReturn = uResult;
3425          goto Done;
3426       }
3427       if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
3428          /* Unexpected end of map or array. */
3429          uReturn = uResult;
3430          goto Done;
3431       }
3432 
3433       /* See if item has one of the labels that are of interest */
3434       bool bMatched = false;
3435       for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3436          if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
3437             /* A label match has been found */
3438             if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3439                uReturn = QCBOR_ERR_DUPLICATE_LABEL;
3440                goto Done;
3441             }
3442             if(uResult != QCBOR_SUCCESS) {
3443                /* The label matches, but the data item is in error.
3444                 * It is OK to have recoverable errors on items that
3445                 * are not matched. */
3446                uReturn = uResult;
3447                goto Done;
3448             }
3449             if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
3450                /* The data item is not of the type(s) requested */
3451                uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3452                goto Done;
3453             }
3454 
3455             /* Successful match. Return the item. */
3456             pItemArray[nIndex] = Item;
3457             uFoundItemBitMap |= 0x01ULL << nIndex;
3458             if(pInfo) {
3459                pInfo->uStartOffset = uOffset;
3460             }
3461             bMatched = true;
3462          }
3463       }
3464 
3465 
3466       if(!bMatched && pCallBack != NULL) {
3467          /*
3468           Call the callback on unmatched labels.
3469           (It is tempting to do duplicate detection here, but that would
3470           require dynamic memory allocation because the number of labels
3471           that might be encountered is unbounded.)
3472          */
3473          uReturn = (*(pCallBack->pfCallback))(pCallBack->pCBContext, &Item);
3474          if(uReturn != QCBOR_SUCCESS) {
3475             goto Done;
3476          }
3477       }
3478 
3479       /*
3480        Consume the item whether matched or not. This
3481        does the work of traversing maps and array and
3482        everything in them. In this loop only the
3483        items at the current nesting level are examined
3484        to match the labels.
3485        */
3486       uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uNextNestLevel);
3487       if(uReturn != QCBOR_SUCCESS) {
3488          goto Done;
3489       }
3490 
3491       if(pInfo) {
3492          pInfo->uItemCount++;
3493       }
3494 
3495    } while (uNextNestLevel >= uMapNestLevel);
3496 
3497    uReturn = QCBOR_SUCCESS;
3498 
3499    const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3500 
3501    // Check here makes sure that this won't accidentally be
3502    // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
3503    // QCBOR_MAX_DECODE_INPUT_SIZE.
3504    // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3505    if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
3506       uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3507       goto Done;
3508    }
3509    /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3510    pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
3511 
3512  Done:
3513    DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3514    UsefulInputBuf_Seek(&(pMe->InBuf), uSavePos);
3515 
3516  Done2:
3517    /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
3518    for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
3519       if(!(uFoundItemBitMap & (0x01ULL << i))) {
3520          pItemArray[i].uDataType  = QCBOR_TYPE_NONE;
3521          pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
3522       }
3523    }
3524 
3525    return uReturn;
3526 }
3527 
3528 
3529 /*
3530  * Public function, see header qcbor/qcbor_decode.h file
3531  */
3532 void
QCBORDecode_GetItemInMapN(QCBORDecodeContext * pMe,int64_t nLabel,uint8_t uQcborType,QCBORItem * pItem)3533 QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3534                           int64_t             nLabel,
3535                           uint8_t             uQcborType,
3536                           QCBORItem          *pItem)
3537 {
3538    if(pMe->uLastError != QCBOR_SUCCESS) {
3539       return;
3540    }
3541 
3542    QCBORItem OneItemSeach[2];
3543    OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
3544    OneItemSeach[0].label.int64 = nLabel;
3545    OneItemSeach[0].uDataType   = uQcborType;
3546    OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE; // Indicates end of array
3547 
3548    QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
3549 
3550    if(uReturn != QCBOR_SUCCESS) {
3551       pItem->uDataType  = QCBOR_TYPE_NONE;
3552       pItem->uLabelType = QCBOR_TYPE_NONE;
3553       goto Done;
3554    }
3555 
3556    if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
3557       uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
3558    }
3559 
3560    *pItem = OneItemSeach[0];
3561    QCBORDecode_Private_CopyTags(pMe, pItem);
3562 
3563  Done:
3564    pMe->uLastError = (uint8_t)uReturn;
3565 }
3566 
3567 
3568 /*
3569  * Public function, see header qcbor/qcbor_decode.h file
3570  */
3571 void
QCBORDecode_GetItemInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,uint8_t uQcborType,QCBORItem * pItem)3572 QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3573                            const char         *szLabel,
3574                            uint8_t             uQcborType,
3575                            QCBORItem          *pItem)
3576 {
3577    if(pMe->uLastError != QCBOR_SUCCESS) {
3578       return;
3579    }
3580 
3581 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
3582    QCBORItem OneItemSeach[2];
3583    OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
3584    OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3585    OneItemSeach[0].uDataType    = uQcborType;
3586    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE; // Indicates end of array
3587 
3588    QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
3589 
3590    if(uReturn != QCBOR_SUCCESS) {
3591       pItem->uDataType  = QCBOR_TYPE_NONE;
3592       pItem->uLabelType = QCBOR_TYPE_NONE;
3593       goto Done;
3594    }
3595    if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
3596       uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
3597       goto Done;
3598    }
3599 
3600    *pItem = OneItemSeach[0];
3601    QCBORDecode_Private_CopyTags(pMe, pItem);
3602 
3603 Done:
3604 #else
3605    (void)pMe;
3606    (void)szLabel;
3607    (void)uQcborType;
3608    (void)pItem;
3609    QCBORError uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
3610 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
3611 
3612    pMe->uLastError = (uint8_t)uReturn;
3613 }
3614 
3615 
3616 
3617 /**
3618  * @brief Semi-private. Get pointer, length and item for an array or map.
3619  *
3620  * @param[in] pMe            The decode context.
3621  * @param[in] uType          CBOR major type, either array/map.
3622  * @param[out] pItem         The item for the array/map.
3623  * @param[out] pEncodedCBOR  Pointer and length of the encoded map or array.
3624  *
3625  * The next item to be decoded must be a map or array as specified by \c uType.
3626  *
3627  * \c pItem will be filled in with the label and tags of the array or map
3628  * in addition to \c pEncodedCBOR giving the pointer and length of the
3629  * encoded CBOR.
3630  *
3631  * When this is complete, the traversal cursor is at the end of the array or
3632  * map that was retrieved.
3633  */
3634 void
QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext * pMe,const uint8_t uType,QCBORItem * pItem,UsefulBufC * pEncodedCBOR)3635 QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pMe,
3636                                   const uint8_t       uType,
3637                                   QCBORItem          *pItem,
3638                                   UsefulBufC         *pEncodedCBOR)
3639 {
3640    QCBORError uErr;
3641    uint8_t    uNestLevel;
3642    size_t     uStartingCursor;
3643    size_t     uStartOfReturned;
3644    size_t     uEndOfReturned;
3645    size_t     uTempSaveCursor;
3646    bool       bInMap;
3647    QCBORItem  LabelItem;
3648    bool       EndedByBreak;
3649 
3650    uStartingCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3651    bInMap = DecodeNesting_IsCurrentTypeMap(&(pMe->nesting));
3652 
3653    /* Could call GetNext here, but don't need to because this
3654     * is only interested in arrays and maps. */
3655    uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pItem);
3656    if(uErr != QCBOR_SUCCESS) {
3657       pMe->uLastError = (uint8_t)uErr;
3658       return;
3659    }
3660 
3661    uint8_t uItemDataType = pItem->uDataType;
3662 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
3663    if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
3664       uItemDataType = QCBOR_TYPE_ARRAY;
3665    }
3666 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
3667 
3668    if(uItemDataType != uType) {
3669       pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3670       return;
3671    }
3672 
3673    if(bInMap) {
3674       /* If the item is in a map, the start of the array/map
3675        * itself, not the label, must be found. Do this by
3676        * rewinding to the starting position and fetching
3677        * just the label data item. QCBORDecode_Private_GetNextTagNumber()
3678        * doesn't do any of the array/map item counting or nesting
3679        * level tracking. Used here it will just fetech the label
3680        * data item.
3681        *
3682        * Have to save the cursor and put it back to the position
3683        * after the full item once the label as been fetched by
3684        * itself.
3685        */
3686       uTempSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3687       UsefulInputBuf_Seek(&(pMe->InBuf), uStartingCursor);
3688 
3689       /* Item has been fetched once so safe to ignore error */
3690       (void)QCBORDecode_Private_GetNextTagNumber(pMe, &LabelItem);
3691 
3692       uStartOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3693       UsefulInputBuf_Seek(&(pMe->InBuf), uTempSaveCursor);
3694    } else {
3695       uStartOfReturned = uStartingCursor;
3696    }
3697 
3698    /* Consume the entire array/map to find the end */
3699    uErr = QCBORDecode_Private_ConsumeItem(pMe, pItem, &EndedByBreak, &uNestLevel);
3700    if(uErr != QCBOR_SUCCESS) {
3701       pMe->uLastError = (uint8_t)uErr;
3702       goto Done;
3703    }
3704 
3705    /* Fill in returned values */
3706    uEndOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3707    if(EndedByBreak) {
3708       /* When ascending nesting levels, a break for the level above
3709        * was consumed. That break is not a part of what is consumed here. */
3710       uEndOfReturned--;
3711    }
3712    pEncodedCBOR->ptr = UsefulInputBuf_OffsetToPointer(&(pMe->InBuf), uStartOfReturned);
3713    pEncodedCBOR->len = uEndOfReturned - uStartOfReturned;
3714 
3715 Done:
3716    return;
3717 }
3718 
3719 
3720 /**
3721  * @brief Semi-private. Get pointer, length and item count of an array or map.
3722  *
3723  * @param[in] pMe            The decode context.
3724  * @param[in] pTarget        The label and type of the array or map to retrieve.
3725  * @param[out] pItem         The item for the array/map.
3726  * @param[out] pEncodedCBOR  Pointer and length of the encoded map or array.
3727  *
3728  * The next item to be decoded must be a map or array as specified by \c uType.
3729  *
3730  * When this is complete, the traversal cursor is unchanged.
3731  */void
QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext * pMe,QCBORItem * pTarget,QCBORItem * pItem,UsefulBufC * pEncodedCBOR)3732 QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pMe,
3733                                            QCBORItem          *pTarget,
3734                                            QCBORItem          *pItem,
3735                                            UsefulBufC         *pEncodedCBOR)
3736 {
3737    MapSearchInfo      Info;
3738    QCBORDecodeNesting SaveNesting;
3739    size_t             uSaveCursor;
3740 
3741    pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pTarget, &Info, NULL);
3742    if(pMe->uLastError != QCBOR_SUCCESS) {
3743       return;
3744    }
3745 
3746    /* Save the whole position of things so they can be restored.
3747     * so the cursor position is unchanged by this operation, like
3748     * all the other GetXxxxInMap() operations. */
3749    DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3750    uSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3751 
3752    DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3753    UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
3754    QCBORDecode_Private_GetArrayOrMap(pMe, pTarget[0].uDataType, pItem, pEncodedCBOR);
3755 
3756    UsefulInputBuf_Seek(&(pMe->InBuf), uSaveCursor);
3757    DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3758 }
3759 
3760 
3761 
3762 
3763 /**
3764  * @brief Is a QCBOR_TYPE in the type list?
3765  *
3766  * @param[in] uDataType  Type to check for.
3767  * @param[in] puTypeList  List to check.
3768  *
3769  * @retval  QCBOR_SUCCESS             If in the list.
3770  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Not in the list.
3771  */
3772 static QCBORError
QCBOR_Private_CheckTypeList(const int uDataType,const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])3773 QCBOR_Private_CheckTypeList(const int     uDataType,
3774                             const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
3775 {
3776    for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3777       if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
3778          return QCBOR_SUCCESS;
3779       }
3780    }
3781    return QCBOR_ERR_UNEXPECTED_TYPE;
3782 }
3783 
3784 
3785 /**
3786  * Match a tag/type specification against the type of the item.
3787  *
3788  * @param[in] TagSpec  Specification for matching tags.
3789  * @param[in] pItem    The item to check.
3790  *
3791  * @retval QCBOR_SUCCESS   \c uDataType is allowed by @c TagSpec
3792  * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3793  *
3794  * This checks the item data type of untagged items as well as of
3795  * tagged items against a specification to see if decoding should
3796  * proceed.
3797  *
3798  * This relies on the automatic tag decoding done by QCBOR that turns
3799  * tag numbers into particular QCBOR_TYPEs so there is no actual
3800  * comparsion of tag numbers, just of QCBOR_TYPEs.
3801  *
3802  * This checks the data item type as possibly representing the tag
3803  * number or as the tag content type.
3804  *
3805  * If QCBOR_DISABLE_TAGS is #defined,  this primarily checks the item
3806  * data type against the allowed tag content types. It will also error out
3807  * if the caller tries to require a tag because there is no way that can
3808  * ever be fulfilled.
3809  */
3810 static QCBORError
QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,const QCBORItem * pItem)3811 QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3812                                   const QCBORItem            *pItem)
3813 {
3814    const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
3815    const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3816 
3817 #ifndef QCBOR_DISABLE_TAGS
3818    /* -Wmaybe-uninitialized falsly warns here */
3819    if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3820       pItem->uTags[0] != CBOR_TAG_INVALID16) {
3821       /* There are tags that QCBOR couldn't process on this item and
3822        * the caller has told us there should not be.
3823        */
3824       return QCBOR_ERR_UNEXPECTED_TYPE;
3825    }
3826 
3827    if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3828       /* Must match the tag number and only the tag */
3829       return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3830    }
3831 
3832    QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3833    if(uReturn == QCBOR_SUCCESS) {
3834       return QCBOR_SUCCESS;
3835    }
3836 
3837    if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3838       /* Must match the content type and only the content type.
3839        * There was no match just above so it is a fail. */
3840       return QCBOR_ERR_UNEXPECTED_TYPE;
3841    }
3842 
3843    /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3844     * and it hasn't matched the content, so the end
3845     * result is whether it matches the tag. This is
3846     * the tag optional case that the CBOR standard discourages.
3847     */
3848 
3849    return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3850 
3851 #else /* QCBOR_DISABLE_TAGS */
3852    if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3853       return QCBOR_ERR_UNEXPECTED_TYPE;
3854    }
3855 
3856    return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3857 
3858 #endif /* QCBOR_DISABLE_TAGS */
3859 }
3860 
3861 
3862 /**
3863  * @brief Get an item by label to match a tag specification.
3864  *
3865  * @param[in] pMe      The decode context.
3866  * @param[in] nLabel   The label to search map for.
3867  * @param[in] TagSpec  The tag number specification to match.
3868  * @param[out] pItem   The item found.
3869  *
3870  * This finds the item with the given label in currently open
3871  * map. Then checks that its tag number and types matches the tag
3872  * specification. If not, an error is set in the decode context.
3873  */
3874 static void
QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const QCBOR_Private_TagSpec TagSpec,QCBORItem * pItem)3875 QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext         *pMe,
3876                                 const int64_t               nLabel,
3877                                 const QCBOR_Private_TagSpec TagSpec,
3878                                 QCBORItem                  *pItem)
3879 {
3880    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3881    if(pMe->uLastError != QCBOR_SUCCESS) {
3882       return;
3883    }
3884 
3885    pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
3886 }
3887 
3888 
3889 /**
3890  * @brief Get an item by label to match a tag specification.
3891  *
3892  * @param[in] pMe      The decode context.
3893  * @param[in] szLabel   The label to search map for.
3894  * @param[in] TagSpec  The tag number specification to match.
3895  * @param[out] pItem   The item found.
3896  *
3897  * This finds the item with the given label in currently open
3898  * map. Then checks that its tag number and types matches the tag
3899  * specification. If not, an error is set in the decode context.
3900  */
3901 static void
QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const QCBOR_Private_TagSpec TagSpec,QCBORItem * pItem)3902 QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext          *pMe,
3903                                  const char                  *szLabel,
3904                                  const QCBOR_Private_TagSpec  TagSpec,
3905                                  QCBORItem                   *pItem)
3906 {
3907    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3908    if(pMe->uLastError != QCBOR_SUCCESS) {
3909       return;
3910    }
3911 
3912    pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
3913 }
3914 
3915 
3916 /**
3917  * @brief Semi-private to get an string by label to match a tag specification.
3918  *
3919  * @param[in] pMe      The decode context.
3920  * @param[in] nLabel   The label to search map for.
3921  * @param[in] TagSpec  The tag number specification to match.
3922  * @param[out] pString   The string found.
3923  *
3924  * This finds the string  with the given label in currently open
3925  * map. Then checks that its tag number and types matches the tag
3926  * specification. If not, an error is set in the decode context.
3927  */
3928 void
QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const QCBOR_Private_TagSpec TagSpec,UsefulBufC * pString)3929 QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext         *pMe,
3930                                           const int64_t               nLabel,
3931                                           const QCBOR_Private_TagSpec TagSpec,
3932                                           UsefulBufC                 *pString)
3933 {
3934    QCBORItem Item;
3935    QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3936    if(pMe->uLastError == QCBOR_SUCCESS) {
3937       *pString = Item.val.string;
3938    }
3939 }
3940 
3941 
3942 /**
3943  * @brief Semi-private to get an string by label to match a tag specification.
3944  *
3945  * @param[in] pMe      The decode context.
3946  * @param[in] szLabel   The label to search map for.
3947  * @param[in] TagSpec  The tag number specification to match.
3948  * @param[out] pString   The string found.
3949  *
3950  * This finds the string  with the given label in currently open
3951  * map. Then checks that its tag number and types matches the tag
3952  * specification. If not, an error is set in the decode context.
3953  */void
QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const QCBOR_Private_TagSpec TagSpec,UsefulBufC * pString)3954 QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext         *pMe,
3955                                            const char *                szLabel,
3956                                            const QCBOR_Private_TagSpec TagSpec,
3957                                            UsefulBufC                 *pString)
3958 {
3959    QCBORItem Item;
3960    QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3961    if(pMe->uLastError == QCBOR_SUCCESS) {
3962       *pString = Item.val.string;
3963    }
3964 }
3965 
3966 
3967 /*
3968  * Public function, see header qcbor/qcbor_decode.h file
3969  */
3970 void
QCBORDecode_GetItemsInMap(QCBORDecodeContext * pMe,QCBORItem * pItemList)3971 QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
3972 {
3973    QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
3974    pMe->uLastError = (uint8_t)uErr;
3975 }
3976 
3977 /*
3978  * Public function, see header qcbor/qcbor_decode.h file
3979  */
3980 void
QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext * pMe,QCBORItem * pItemList,void * pCallbackCtx,QCBORItemCallback pfCB)3981 QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3982                                       QCBORItem          *pItemList,
3983                                       void               *pCallbackCtx,
3984                                       QCBORItemCallback   pfCB)
3985 {
3986    MapSearchCallBack CallBack;
3987    CallBack.pCBContext = pCallbackCtx;
3988    CallBack.pfCallback = pfCB;
3989 
3990    QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
3991 
3992    pMe->uLastError = (uint8_t)uErr;
3993 }
3994 
3995 
3996 /**
3997  * @brief Search for a map/array by label and enter it
3998  *
3999  * @param[in] pMe  The decode context.
4000  * @param[in] pSearch The map/array to search for.
4001  *
4002  * @c pSearch is expected to contain one item of type map or array
4003  * with the label specified. The current bounded map will be searched for
4004  * this and if found  will be entered.
4005  *
4006  * If the label is not found, or the item found is not a map or array,
4007  * the error state is set.
4008  */
4009 static void
QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext * pMe,QCBORItem pSearch[])4010 QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
4011 {
4012    // The first item in pSearch is the one that is to be
4013    // entered. It should be the only one filled in. Any other
4014    // will be ignored unless it causes an error.
4015    if(pMe->uLastError != QCBOR_SUCCESS) {
4016       return;
4017    }
4018 
4019    MapSearchInfo Info;
4020    pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &Info, NULL);
4021    if(pMe->uLastError != QCBOR_SUCCESS) {
4022       return;
4023    }
4024 
4025    if(pSearch->uDataType == QCBOR_TYPE_NONE) {
4026       pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4027       return;
4028    }
4029 
4030 
4031    /* The map or array was found. Now enter it.
4032     *
4033     * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
4034     * next item for the pre-order traversal cursor to be the map/array
4035     * found by MapSearch(). The next few lines of code force the
4036     * cursor to that.
4037     *
4038     * There is no need to retain the old cursor because
4039     * QCBORDecode_EnterBoundedMapOrArray() will set it to the
4040     * beginning of the map/array being entered.
4041     *
4042     * The cursor is forced by: 1) setting the input buffer position to
4043     * the item offset found by MapSearch(), 2) setting the map/array
4044     * counter to the total in the map/array, 3) setting the nesting
4045     * level. Setting the map/array counter to the total is not
4046     * strictly correct, but this is OK because this cursor only needs
4047     * to be used to get one item and MapSearch() has already found it
4048     * confirming it exists.
4049     */
4050    UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
4051 
4052    DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
4053 
4054    DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
4055 
4056    QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
4057 }
4058 
4059 
4060 /*
4061  * Public function, see header qcbor/qcbor_decode.h file
4062  */
4063 void
QCBORDecode_EnterMapFromMapN(QCBORDecodeContext * pMe,int64_t nLabel)4064 QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
4065 {
4066    QCBORItem OneItemSeach[2];
4067    OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
4068    OneItemSeach[0].label.int64 = nLabel;
4069    OneItemSeach[0].uDataType   = QCBOR_TYPE_MAP;
4070    OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE;
4071 
4072    /* The map to enter was found, now finish off entering it. */
4073    QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
4074 }
4075 
4076 
4077 /*
4078  * Public function, see header qcbor/qcbor_decode.h file
4079  */
4080 void
QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext * pMe,const char * szLabel)4081 QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char  *szLabel)
4082 {
4083 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
4084    QCBORItem OneItemSeach[2];
4085    OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
4086    OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4087    OneItemSeach[0].uDataType    = QCBOR_TYPE_MAP;
4088    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
4089 
4090    QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
4091 #else
4092    (void)szLabel;
4093    pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4094 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4095 }
4096 
4097 /*
4098  * Public function, see header qcbor/qcbor_decode.h file
4099  */
4100 void
QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext * pMe,int64_t nLabel)4101 QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
4102 {
4103    QCBORItem OneItemSeach[2];
4104    OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
4105    OneItemSeach[0].label.int64 = nLabel;
4106    OneItemSeach[0].uDataType   = QCBOR_TYPE_ARRAY;
4107    OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE;
4108 
4109    QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
4110 }
4111 
4112 /*
4113  * Public function, see header qcbor/qcbor_decode.h file
4114  */
4115 void
QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext * pMe,const char * szLabel)4116 QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char  *szLabel)
4117 {
4118 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
4119    QCBORItem OneItemSeach[2];
4120    OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
4121    OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4122    OneItemSeach[0].uDataType    = QCBOR_TYPE_ARRAY;
4123    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
4124 
4125    QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
4126 #else
4127    (void)szLabel;
4128    pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4129 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4130 }
4131 
4132 
4133 /**
4134  * @brief Semi-private to do the the work for EnterMap() and EnterArray().
4135  *
4136  * @param[in] pMe     The decode context
4137  * @param[in] uType   QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
4138  * @param[out] pItem  The data item for the map or array entered.
4139  *
4140  * The next item in the traversal must be a map or array.  This
4141  * consumes that item and does the book keeping to enter the map or
4142  * array.
4143  */
4144 void
QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext * pMe,const uint8_t uType,QCBORItem * pItem)4145 QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
4146                                            const uint8_t       uType,
4147                                            QCBORItem          *pItem)
4148 {
4149     QCBORError uErr;
4150 
4151    /* Must only be called on maps and arrays. */
4152    if(pMe->uLastError != QCBOR_SUCCESS) {
4153       // Already in error state; do nothing.
4154       return;
4155    }
4156 
4157    /* Get the data item that is the map or array being entered. */
4158    QCBORItem Item;
4159    uErr = QCBORDecode_GetNext(pMe, &Item);
4160    if(uErr != QCBOR_SUCCESS) {
4161       goto Done;
4162    }
4163 
4164    uint8_t uItemDataType = Item.uDataType;
4165 
4166 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
4167    if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
4168       uItemDataType = QCBOR_TYPE_ARRAY;
4169    }
4170 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4171 
4172    if(uItemDataType != uType) {
4173       uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4174       goto Done;
4175    }
4176 
4177    QCBORDecode_Private_CopyTags(pMe, &Item);
4178 
4179 
4180    const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
4181    if(bIsEmpty) {
4182       if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
4183          // Undo decrement done by QCBORDecode_GetNext() so the the
4184          // the decrement when exiting the map/array works correctly
4185          pMe->nesting.pCurrent->u.ma.uCountCursor++;
4186       }
4187       // Special case to increment nesting level for zero-length maps
4188       // and arrays entered in bounded mode.
4189       DecodeNesting_Descend(&(pMe->nesting), uType);
4190    }
4191 
4192    pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
4193 
4194    uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
4195                                                UsefulInputBuf_Tell(&(pMe->InBuf)));
4196 
4197    if(pItem != NULL) {
4198       *pItem = Item;
4199    }
4200 
4201 Done:
4202    pMe->uLastError = (uint8_t)uErr;
4203 }
4204 
4205 
4206 /**
4207  * @brief Exit a bounded map, array or bstr (semi-private).
4208  *
4209  * @param[in] pMe         Decode context.
4210  * @param[in] uEndOffset  The input buffer offset of the end of item exited.
4211  *
4212  * @returns  QCBOR_SUCCESS or an error code.
4213  *
4214  * This is the common work for exiting a level that is a bounded map,
4215  * array or bstr wrapped CBOR.
4216  *
4217  * One chunk of work is to set up the pre-order traversal so it is at
4218  * the item just after the bounded map, array or bstr that is being
4219  * exited. This is somewhat complex.
4220  *
4221  * The other work is to level-up the bounded mode to next higest
4222  * bounded mode or the top level if there isn't one.
4223  */
4224 static QCBORError
QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext * pMe,const uint32_t uEndOffset)4225 QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
4226                                      const uint32_t      uEndOffset)
4227 {
4228    QCBORError uErr;
4229 
4230    /*
4231     * First the pre-order-traversal byte offset is positioned to the
4232     * item just after the bounded mode item that was just consumed.
4233     */
4234    UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
4235 
4236    /*
4237     * Next, set the current nesting level to one above the bounded
4238     * level that was just exited.
4239     *
4240     * DecodeNesting_CheckBoundedType() is always called before this
4241     * and makes sure pCurrentBounded is valid.
4242     */
4243    DecodeNesting_LevelUpCurrent(&(pMe->nesting));
4244 
4245    /*
4246     * This does the complex work of leveling up the pre-order
4247     * traversal when the end of a map or array or another bounded
4248     * level is reached.  It may do nothing, or ascend all the way to
4249     * the top level.
4250     */
4251    uErr = QCBORDecode_Private_NestLevelAscender(pMe, NULL, false);
4252    if(uErr != QCBOR_SUCCESS) {
4253       goto Done;
4254    }
4255 
4256    /*
4257     * This makes the next highest bounded level the current bounded
4258     * level. If there is no next highest level, then no bounded mode
4259     * is in effect.
4260     */
4261    DecodeNesting_LevelUpBounded(&(pMe->nesting));
4262 
4263    pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
4264 
4265 Done:
4266    return uErr;
4267 }
4268 
4269 
4270 /**
4271  * @brief Get started exiting a map or array (semi-private)
4272  *
4273  * @param[in] pMe  The decode context
4274  * @param[in] uType  QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
4275  *
4276  * This does some work for map and array exiting (but not
4277  * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
4278  * is called to do the rest.
4279  */
4280 void
QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext * pMe,const uint8_t uType)4281 QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
4282                                           const uint8_t       uType)
4283 {
4284    if(pMe->uLastError != QCBOR_SUCCESS) {
4285       /* Already in error state; do nothing. */
4286       return;
4287    }
4288 
4289    QCBORError uErr;
4290 
4291    if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
4292       uErr = QCBOR_ERR_EXIT_MISMATCH;
4293       goto Done;
4294    }
4295 
4296    /*
4297     Have to set the offset to the end of the map/array
4298     that is being exited. If there is no cached value,
4299     from previous map search, then do a dummy search.
4300     */
4301    if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
4302       QCBORItem Dummy;
4303       Dummy.uLabelType = QCBOR_TYPE_NONE;
4304       uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL);
4305       if(uErr != QCBOR_SUCCESS) {
4306          goto Done;
4307       }
4308    }
4309 
4310    uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
4311 
4312 Done:
4313    pMe->uLastError = (uint8_t)uErr;
4314 }
4315 
4316 
4317 /**
4318  * @brief The main work of entering some byte-string wrapped CBOR.
4319  *
4320  * @param[in] pMe             The decode context.
4321  * @param[in] pItem           The byte string item.
4322  * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
4323  * @param[out] pBstr          Pointer and length of byte string entered.
4324  *
4325  * This is called once the byte string item has been decoded to do all
4326  * the book keeping work for descending a nesting level into the
4327  * nested CBOR.
4328  *
4329  * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4330  */
4331 static QCBORError
QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext * pMe,const QCBORItem * pItem,const uint8_t uTagRequirement,UsefulBufC * pBstr)4332 QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4333                                      const QCBORItem    *pItem,
4334                                      const uint8_t       uTagRequirement,
4335                                      UsefulBufC         *pBstr)
4336 {
4337    if(pBstr) {
4338       *pBstr = NULLUsefulBufC;
4339    }
4340 
4341    if(pMe->uLastError != QCBOR_SUCCESS) {
4342       /* Already in error state; do nothing. */
4343       return pMe->uLastError;
4344    }
4345 
4346    QCBORError uError;
4347 
4348    const QCBOR_Private_TagSpec TagSpec =
4349       {
4350          uTagRequirement,
4351          {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
4352          {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4353       };
4354 
4355    uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
4356    if(uError != QCBOR_SUCCESS) {
4357       goto Done;
4358    }
4359 
4360    if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
4361       /* Reverse the decrement done by GetNext() for the bstr so the
4362        * increment in QCBORDecode_NestLevelAscender() called by
4363        * ExitBoundedLevel() will work right.
4364        */
4365       DecodeNesting_ReverseDecrement(&(pMe->nesting));
4366    }
4367 
4368    if(pBstr) {
4369       *pBstr = pItem->val.string;
4370    }
4371 
4372    /* This saves the current length of the UsefulInputBuf and then
4373     * narrows the UsefulInputBuf to start and length of the wrapped
4374     * CBOR that is being entered.
4375     *
4376     * Most of these calls are simple inline accessors so this doesn't
4377     * amount to much code.
4378     */
4379 
4380    const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4381    /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4382    if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
4383       uError = QCBOR_ERR_INPUT_TOO_LARGE;
4384       goto Done;
4385    }
4386 
4387    const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4388                                                               pItem->val.string.ptr);
4389    /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4390    if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4391       /* This should never happen because pItem->val.string.ptr should
4392        * always be valid since it was just returned.
4393        */
4394       uError = QCBOR_ERR_INPUT_TOO_LARGE;
4395       goto Done;
4396    }
4397 
4398    const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4399 
4400    UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
4401    UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
4402 
4403    uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
4404                                                  (uint32_t)uPreviousLength,
4405                                                  (uint32_t)uStartOfBstr);
4406 Done:
4407    return uError;
4408 }
4409 
4410 
4411 /*
4412  * Public function, see header qcbor/qcbor_decode.h file
4413  */
4414 void
QCBORDecode_EnterBstrWrapped(QCBORDecodeContext * pMe,const uint8_t uTagRequirement,UsefulBufC * pBstr)4415 QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4416                              const uint8_t       uTagRequirement,
4417                              UsefulBufC         *pBstr)
4418 {
4419    if(pMe->uLastError != QCBOR_SUCCESS) {
4420       // Already in error state; do nothing.
4421       return;
4422    }
4423 
4424    /* Get the data item that is the byte string being entered */
4425    QCBORItem Item;
4426    pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4427    if(pMe->uLastError != QCBOR_SUCCESS) {
4428       return;
4429    }
4430 
4431    if(Item.uDataAlloc) {
4432       pMe->uLastError = QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING;
4433       return;
4434    }
4435 
4436    pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4437                                                                   &Item,
4438                                                                    uTagRequirement,
4439                                                                    pBstr);
4440 }
4441 
4442 
4443 /*
4444  * Public function, see header qcbor/qcbor_decode.h file
4445  */
4446 void
QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint8_t uTagRequirement,UsefulBufC * pBstr)4447 QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4448                                      const int64_t       nLabel,
4449                                      const uint8_t       uTagRequirement,
4450                                      UsefulBufC         *pBstr)
4451 {
4452    QCBORItem Item;
4453    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4454 
4455    pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4456                                                                   &Item,
4457                                                                    uTagRequirement,
4458                                                                    pBstr);
4459 }
4460 
4461 
4462 /*
4463  * Public function, see header qcbor/qcbor_decode.h file
4464  */
4465 void
QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint8_t uTagRequirement,UsefulBufC * pBstr)4466 QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4467                                       const char         *szLabel,
4468                                       const uint8_t       uTagRequirement,
4469                                       UsefulBufC         *pBstr)
4470 {
4471    QCBORItem Item;
4472    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4473 
4474    pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4475                                                                   &Item,
4476                                                                    uTagRequirement,
4477                                                                    pBstr);
4478 }
4479 
4480 
4481 /*
4482  * Public function, see header qcbor/qcbor_decode.h file
4483  */
4484 void
QCBORDecode_ExitBstrWrapped(QCBORDecodeContext * pMe)4485 QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
4486 {
4487    if(pMe->uLastError != QCBOR_SUCCESS) {
4488       // Already in error state; do nothing.
4489       return;
4490    }
4491 
4492    if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
4493       pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
4494       return;
4495    }
4496 
4497    const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4498 
4499    /*
4500     Reset the length of the UsefulInputBuf to what it was before
4501     the bstr wrapped CBOR was entered.
4502     */
4503    UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
4504                                DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
4505 
4506 
4507    QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
4508    pMe->uLastError = (uint8_t)uErr;
4509 }
4510 
4511 
4512 
4513 /**
4514  * @brief Process simple type true and false, a boolean
4515  *
4516  * @param[in] pMe     The decode context.
4517  * @param[in] pItem   The item with either true or false.
4518  * @param[out] pBool  The boolean value output.
4519  *
4520  * Sets the internal error if the item isn't a true or a false. Also
4521  * records any tag numbers as the tag numbers of the last item.
4522  */
4523 static void
QCBORDecode_Private_ProcessBool(QCBORDecodeContext * pMe,const QCBORItem * pItem,bool * pBool)4524 QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4525                                 const QCBORItem    *pItem,
4526                                 bool               *pBool)
4527 {
4528    if(pMe->uLastError != QCBOR_SUCCESS) {
4529       /* Already in error state, do nothing */
4530       return;
4531    }
4532 
4533    switch(pItem->uDataType) {
4534       case QCBOR_TYPE_TRUE:
4535          *pBool = true;
4536          break;
4537 
4538       case QCBOR_TYPE_FALSE:
4539          *pBool = false;
4540          break;
4541 
4542       default:
4543          pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4544          break;
4545    }
4546 }
4547 
4548 
4549 /*
4550  * Public function, see header qcbor/qcbor_decode.h file
4551  */
4552 void
QCBORDecode_GetBool(QCBORDecodeContext * pMe,bool * pValue)4553 QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
4554 {
4555    QCBORItem  Item;
4556    QCBORDecode_VGetNext(pMe, &Item);
4557    QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
4558 }
4559 
4560 
4561 /*
4562  * Public function, see header qcbor/qcbor_decode.h file
4563  */
4564 void
QCBORDecode_GetBoolInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,bool * pValue)4565 QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4566                           const int64_t       nLabel,
4567                           bool               *pValue)
4568 {
4569    QCBORItem Item;
4570    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4571    QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
4572 }
4573 
4574 
4575 /*
4576  * Public function, see header qcbor/qcbor_decode.h file
4577  */
4578 void
QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,bool * pValue)4579 QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4580                            const char         *szLabel,
4581                            bool               *pValue)
4582 {
4583    QCBORItem Item;
4584    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4585    QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
4586 }
4587 
4588 
4589 /**
4590  * @brief Process simple values.
4591  *
4592  * @param[in] pMe     The decode context.
4593  * @param[in] pItem   The item with the simple value.
4594  * @param[out] puSimple  The simple value output.
4595  *
4596  * Sets the internal error if the item isn't a true or a false. Also
4597  * records any tag numbers as the tag numbers of the last item.
4598  */
4599 static void
QCBORDecode_Private_ProcessSimple(QCBORDecodeContext * pMe,const QCBORItem * pItem,uint8_t * puSimple)4600 QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
4601                                   const QCBORItem    *pItem,
4602                                   uint8_t            *puSimple)
4603 {
4604    if(pMe->uLastError != QCBOR_SUCCESS) {
4605       return;
4606    }
4607 
4608    /* It's kind of lame to remap true...undef back to simple values, but
4609     * this function isn't used much and to not do it would require
4610     * changing GetNext() behavior in an incompatible way.
4611     */
4612    switch(pItem->uDataType) {
4613       case QCBOR_TYPE_UKNOWN_SIMPLE:
4614          *puSimple = pItem->val.uSimple;
4615          break;
4616 
4617       case QCBOR_TYPE_TRUE:
4618          *puSimple = CBOR_SIMPLEV_TRUE;
4619          break;
4620 
4621       case QCBOR_TYPE_FALSE:
4622          *puSimple = CBOR_SIMPLEV_FALSE;
4623          break;
4624 
4625       case QCBOR_TYPE_NULL:
4626          *puSimple = CBOR_SIMPLEV_NULL;
4627          break;
4628 
4629       case QCBOR_TYPE_UNDEF:
4630          *puSimple = CBOR_SIMPLEV_UNDEF;
4631          break;
4632 
4633       default:
4634          pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4635          return;
4636    }
4637 }
4638 
4639 /*
4640  * Public function, see header qcbor/qcbor_decode.h file
4641  */
4642 void
QCBORDecode_GetSimple(QCBORDecodeContext * pMe,uint8_t * puSimple)4643 QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
4644 {
4645    QCBORItem Item;
4646    QCBORDecode_VGetNext(pMe, &Item);
4647    QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
4648 }
4649 
4650 /*
4651  * Public function, see header qcbor/qcbor_decode.h file
4652  */
4653 void
QCBORDecode_GetSimpleInMapN(QCBORDecodeContext * pMe,int64_t nLabel,uint8_t * puSimpleValue)4654 QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
4655                             int64_t             nLabel,
4656                             uint8_t            *puSimpleValue)
4657 {
4658    QCBORItem Item;
4659    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4660    QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4661 }
4662 
4663 /*
4664  * Public function, see header qcbor/qcbor_decode.h file
4665  */
4666 void
QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,uint8_t * puSimpleValue)4667 QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
4668                              const char         *szLabel,
4669                              uint8_t            *puSimpleValue)
4670 {
4671    QCBORItem Item;
4672    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4673    QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4674 }
4675 
4676 
4677 
4678 /**
4679  * @brief Common processing for an epoch date.
4680  *
4681  * @param[in] pMe              The decode context.
4682  * @param[in] pItem            The item with the date.
4683  * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
4684  * @param[out] pnTime          The returned date.
4685  *
4686  * Common processing for the date tag. Mostly make sure the tag
4687  * content is correct and copy forward any further other tag numbers.
4688  */
4689 static void
QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext * pMe,QCBORItem * pItem,const uint8_t uTagRequirement,int64_t * pnTime)4690 QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4691                                      QCBORItem          *pItem,
4692                                      const uint8_t       uTagRequirement,
4693                                      int64_t            *pnTime)
4694 {
4695    if(pMe->uLastError != QCBOR_SUCCESS) {
4696       // Already in error state, do nothing
4697       return;
4698    }
4699 
4700    QCBORError uErr;
4701 
4702    const QCBOR_Private_TagSpec TagSpec =
4703    {
4704       uTagRequirement,
4705       {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4706       {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
4707    };
4708 
4709    uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
4710    if(uErr != QCBOR_SUCCESS) {
4711       goto Done;
4712    }
4713 
4714    if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
4715       uErr = QCBOR_Private_DecodeDateEpoch(pItem);
4716       if(uErr != QCBOR_SUCCESS) {
4717          goto Done;
4718       }
4719    }
4720 
4721    *pnTime = pItem->val.epochDate.nSeconds;
4722 
4723 Done:
4724    pMe->uLastError = (uint8_t)uErr;
4725 }
4726 
4727 
4728 
4729 /*
4730  * Public function, see header qcbor/qcbor_spiffy_decode.h file
4731  */
4732 void
QCBORDecode_GetEpochDate(QCBORDecodeContext * pMe,uint8_t uTagRequirement,int64_t * pnTime)4733 QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4734                          uint8_t             uTagRequirement,
4735                          int64_t            *pnTime)
4736 {
4737    QCBORItem  Item;
4738    QCBORDecode_VGetNext(pMe, &Item);
4739    QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4740 }
4741 
4742 
4743 /*
4744  * Public function, see header qcbor/qcbor_spiffy_decode.h file
4745  */
4746 void
QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext * pMe,int64_t nLabel,uint8_t uTagRequirement,int64_t * pnTime)4747 QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4748                                int64_t             nLabel,
4749                                uint8_t             uTagRequirement,
4750                                int64_t            *pnTime)
4751 {
4752    QCBORItem Item;
4753    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4754    QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4755 }
4756 
4757 
4758 /*
4759  * Public function, see header qcbor/qcbor_spiffy_decode.h file
4760  */
4761 void
QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,uint8_t uTagRequirement,int64_t * pnTime)4762 QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4763                                 const char         *szLabel,
4764                                 uint8_t             uTagRequirement,
4765                                 int64_t            *pnTime)
4766 {
4767    QCBORItem Item;
4768    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4769    QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4770 }
4771 
4772 
4773 
4774 /**
4775  * @brief Common processing for an epoch date.
4776  *
4777  * @param[in] pMe              The decode context.
4778  * @param[in] pItem            The item with the date.
4779  * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
4780  * @param[out] pnDays          The returned day count.
4781  *
4782  * Common processing for the RFC 8943 day-count tag. Mostly make sure
4783  * the tag content is correct and copy forward any further other tag
4784  * numbers.
4785  */
4786 static void
QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext * pMe,QCBORItem * pItem,uint8_t uTagRequirement,int64_t * pnDays)4787 QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4788                                      QCBORItem          *pItem,
4789                                      uint8_t             uTagRequirement,
4790                                      int64_t            *pnDays)
4791 {
4792    if(pMe->uLastError != QCBOR_SUCCESS) {
4793       /* Already in error state, do nothing */
4794       return;
4795    }
4796 
4797    QCBORError uErr;
4798 
4799    const QCBOR_Private_TagSpec TagSpec =
4800    {
4801       uTagRequirement,
4802       {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4803       {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4804    };
4805 
4806    uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
4807    if(uErr != QCBOR_SUCCESS) {
4808       goto Done;
4809    }
4810 
4811    if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
4812       uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
4813       if(uErr != QCBOR_SUCCESS) {
4814          goto Done;
4815       }
4816    }
4817 
4818    *pnDays = pItem->val.epochDays;
4819 
4820 Done:
4821    pMe->uLastError = (uint8_t)uErr;
4822 }
4823 
4824 
4825 /*
4826  * Public function, see header qcbor/qcbor_decode.h
4827  */
4828 void
QCBORDecode_GetEpochDays(QCBORDecodeContext * pMe,uint8_t uTagRequirement,int64_t * pnDays)4829 QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4830                          uint8_t             uTagRequirement,
4831                          int64_t            *pnDays)
4832 {
4833    QCBORItem  Item;
4834    QCBORDecode_VGetNext(pMe, &Item);
4835    QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4836 }
4837 
4838 
4839 /*
4840  * Public function, see header qcbor/qcbor_decode.h
4841  */
4842 void
QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext * pMe,int64_t nLabel,uint8_t uTagRequirement,int64_t * pnDays)4843 QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4844                                int64_t             nLabel,
4845                                uint8_t             uTagRequirement,
4846                                int64_t            *pnDays)
4847 {
4848    QCBORItem Item;
4849    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4850    QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4851 }
4852 
4853 
4854 /*
4855  * Public function, see header qcbor/qcbor_decode.h
4856  */
4857 void
QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,uint8_t uTagRequirement,int64_t * pnDays)4858 QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4859                                 const char         *szLabel,
4860                                 uint8_t             uTagRequirement,
4861                                 int64_t            *pnDays)
4862 {
4863    QCBORItem Item;
4864    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4865    QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4866 }
4867 
4868 
4869 
4870 /*
4871  * @brief Get a string that matches the type/tag specification.
4872  */
4873 void
QCBORDecode_Private_GetTaggedString(QCBORDecodeContext * pMe,const QCBOR_Private_TagSpec TagSpec,UsefulBufC * pBstr)4874 QCBORDecode_Private_GetTaggedString(QCBORDecodeContext         *pMe,
4875                                     const QCBOR_Private_TagSpec TagSpec,
4876                                     UsefulBufC                 *pBstr)
4877 {
4878    QCBORItem  Item;
4879 
4880    QCBORDecode_VGetNext(pMe, &Item);
4881    if(pMe->uLastError) {
4882       return;
4883    }
4884 
4885    pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
4886 
4887    if(pMe->uLastError == QCBOR_SUCCESS) {
4888       *pBstr = Item.val.string;
4889    } else {
4890       *pBstr = NULLUsefulBufC;
4891    }
4892 }
4893 
4894 
4895 
4896 
4897 /**
4898  * @brief Common processing for a big number tag.
4899  *
4900  * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
4901  * @param[in] pItem            The item with the date.
4902  * @param[out] pValue          The returned big number
4903  * @param[out] pbIsNegative  The returned sign of the big number.
4904  *
4905  * Common processing for the big number tag. Mostly make sure
4906  * the tag content is correct and copy forward any further other tag
4907  * numbers.
4908  */
4909 static QCBORError
QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,const QCBORItem * pItem,UsefulBufC * pValue,bool * pbIsNegative)4910 QCBOR_Private_ProcessBigNum(const uint8_t   uTagRequirement,
4911                             const QCBORItem *pItem,
4912                             UsefulBufC      *pValue,
4913                             bool            *pbIsNegative)
4914 {
4915    const QCBOR_Private_TagSpec TagSpec =
4916    {
4917       uTagRequirement,
4918       {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4919       {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4920    };
4921 
4922    QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
4923    if(uErr != QCBOR_SUCCESS) {
4924       return uErr;
4925    }
4926 
4927    *pValue = pItem->val.string;
4928 
4929    if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4930       *pbIsNegative = false;
4931    } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4932       *pbIsNegative = true;
4933    }
4934 
4935    return QCBOR_SUCCESS;
4936 }
4937 
4938 
4939 /*
4940  * Public function, see header qcbor/qcbor_spiffy_decode.h
4941  */
4942 void
QCBORDecode_GetBignum(QCBORDecodeContext * pMe,const uint8_t uTagRequirement,UsefulBufC * pValue,bool * pbIsNegative)4943 QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4944                       const uint8_t       uTagRequirement,
4945                       UsefulBufC         *pValue,
4946                       bool               *pbIsNegative)
4947 {
4948    QCBORItem  Item;
4949    QCBORDecode_VGetNext(pMe, &Item);
4950    if(pMe->uLastError) {
4951       return;
4952    }
4953 
4954    pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4955                                                           &Item,
4956                                                           pValue,
4957                                                           pbIsNegative);
4958 }
4959 
4960 
4961 /*
4962  * Public function, see header qcbor/qcbor_spiffy_decode.h
4963  */
4964 void
QCBORDecode_GetBignumInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint8_t uTagRequirement,UsefulBufC * pValue,bool * pbIsNegative)4965 QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4966                             const int64_t       nLabel,
4967                             const uint8_t       uTagRequirement,
4968                             UsefulBufC         *pValue,
4969                             bool               *pbIsNegative)
4970 {
4971    QCBORItem Item;
4972    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4973    if(pMe->uLastError != QCBOR_SUCCESS) {
4974       return;
4975    }
4976 
4977    pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4978                                                           &Item,
4979                                                           pValue,
4980                                                           pbIsNegative);
4981 }
4982 
4983 
4984 /*
4985  * Public function, see header qcbor/qcbor_spiffy_decode.h
4986  */
4987 void
QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint8_t uTagRequirement,UsefulBufC * pValue,bool * pbIsNegative)4988 QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4989                              const char         *szLabel,
4990                              const uint8_t       uTagRequirement,
4991                              UsefulBufC         *pValue,
4992                              bool               *pbIsNegative)
4993 {
4994    QCBORItem Item;
4995    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4996    if(pMe->uLastError != QCBOR_SUCCESS) {
4997       return;
4998    }
4999 
5000    pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
5001                                                           &Item,
5002                                                           pValue,
5003                                                           pbIsNegative);
5004 }
5005 
5006 
5007 
5008 /**
5009  * @brief Common processing for MIME tag (semi-private).
5010  *
5011  * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
5012  * @param[in] pItem            The item with the date.
5013  * @param[out] pMessage        The returned MIME message.
5014  * @param[out] pbIsTag257      If true, binary MIME, if not, text MIME.
5015  *
5016  * Common processing for the MIME tag. Mostly make sure the tag
5017  * content is correct and copy forward any further other tag
5018  * numbers. See QCBORDecode_GetMIMEMessage().
5019  */
5020 QCBORError
QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,const QCBORItem * pItem,UsefulBufC * pMessage,bool * pbIsTag257)5021 QCBORDecode_Private_GetMIME(const uint8_t     uTagRequirement,
5022                             const QCBORItem  *pItem,
5023                             UsefulBufC       *pMessage,
5024                             bool             *pbIsTag257)
5025 {
5026    const QCBOR_Private_TagSpec TagSpecText =
5027       {
5028          uTagRequirement,
5029          {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
5030          {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5031       };
5032    const QCBOR_Private_TagSpec TagSpecBinary =
5033       {
5034          uTagRequirement,
5035          {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
5036          {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5037       };
5038 
5039    QCBORError uReturn;
5040 
5041    if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
5042       *pMessage = pItem->val.string;
5043       if(pbIsTag257 != NULL) {
5044          *pbIsTag257 = false;
5045       }
5046       uReturn = QCBOR_SUCCESS;
5047    } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
5048       *pMessage = pItem->val.string;
5049       if(pbIsTag257 != NULL) {
5050          *pbIsTag257 = true;
5051       }
5052       uReturn = QCBOR_SUCCESS;
5053 
5054    } else {
5055       uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
5056    }
5057 
5058    return uReturn;
5059 }
5060 
5061 // Improvement: add methods for wrapped CBOR, a simple alternate
5062 // to EnterBstrWrapped
5063 
5064 
5065 
5066 
5067 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
5068 
5069 /**
5070  * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
5071  *
5072  * @param[in] uMantissa    The mantissa.
5073  * @param[in] nExponent    The exponent.
5074  * @param[out] puResult  The resulting integer.
5075  *
5076  * Concrete implementations of this are for exponent base 10 and 2 supporting
5077  * decimal fractions and big floats.
5078  */
5079 typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
5080 
5081 
5082 /**
5083  * @brief  Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5084  *
5085  * @param[in] uMantissa  The unsigned integer mantissa.
5086  * @param[in] nExponent  The signed integer exponent.
5087  * @param[out] puResult  Place to return the unsigned integer result.
5088  *
5089  * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
5090  * unsigned integer.
5091  *
5092  * There are many inputs for which the result will not fit in the
5093  * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
5094  * be returned.
5095  */
5096 static QCBORError
QCBOR_Private_Exponentitate10(const uint64_t uMantissa,int64_t nExponent,uint64_t * puResult)5097 QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
5098                               int64_t        nExponent,
5099                               uint64_t      *puResult)
5100 {
5101    uint64_t uResult = uMantissa;
5102 
5103    if(uResult != 0) {
5104       /* This loop will run a maximum of 19 times because
5105        * UINT64_MAX < 10 ^^ 19. More than that will cause
5106        * exit with the overflow error
5107        */
5108       for(; nExponent > 0; nExponent--) {
5109          if(uResult > UINT64_MAX / 10) {
5110             return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5111          }
5112          uResult = uResult * 10;
5113       }
5114 
5115       for(; nExponent < 0; nExponent++) {
5116          uResult = uResult / 10;
5117          if(uResult == 0) {
5118             return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5119          }
5120       }
5121    }
5122    /* else, mantissa is zero so this returns zero */
5123 
5124    *puResult = uResult;
5125 
5126    return QCBOR_SUCCESS;
5127 }
5128 
5129 
5130 /**
5131  * @brief  Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5132  *
5133  * @param[in] uMantissa  The unsigned integer mantissa.
5134  * @param[in] nExponent  The signed integer exponent.
5135  * @param[out] puResult  Place to return the unsigned integer result.
5136  *
5137  * This computes: mantissa * 2 ^^ exponent as for a big float. The
5138  * output is a 64-bit unsigned integer.
5139  *
5140  * There are many inputs for which the result will not fit in the
5141  * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
5142  * be returned.
5143  */
5144 static QCBORError
QCBOR_Private_Exponentitate2(const uint64_t uMantissa,int64_t nExponent,uint64_t * puResult)5145 QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
5146                              int64_t        nExponent,
5147                              uint64_t      *puResult)
5148 {
5149    uint64_t uResult;
5150 
5151    uResult = uMantissa;
5152 
5153    /* This loop will run a maximum of 64 times because INT64_MAX <
5154     * 2^31. More than that will cause exit with the overflow error
5155     */
5156    while(nExponent > 0) {
5157       if(uResult > UINT64_MAX >> 1) {
5158          return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5159       }
5160       uResult = uResult << 1;
5161       nExponent--;
5162    }
5163 
5164    while(nExponent < 0 ) {
5165       if(uResult == 0) {
5166          return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5167       }
5168       uResult = uResult >> 1;
5169       nExponent++;
5170    }
5171 
5172    *puResult = uResult;
5173 
5174    return QCBOR_SUCCESS;
5175 }
5176 
5177 
5178 /**
5179  * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
5180  *
5181  * @param[in] nMantissa  Signed integer mantissa.
5182  * @param[in] nExponent  Signed integer exponent.
5183  * @param[out] pnResult  Place to put the signed integer result.
5184  * @param[in] pfExp      Exponentiation function.
5185  *
5186  * @returns Error code
5187  *
5188  * \c pfExp performs exponentiation on and unsigned mantissa and
5189  * produces an unsigned result. This converts the mantissa from signed
5190  * and converts the result to signed. The exponentiation function is
5191  * either for base 2 or base 10 (and could be other if needed).
5192  */
5193 static QCBORError
QCBOR_Private_ExponentiateNN(const int64_t nMantissa,const int64_t nExponent,int64_t * pnResult,fExponentiator pfExp)5194 QCBOR_Private_ExponentiateNN(const int64_t  nMantissa,
5195                              const int64_t  nExponent,
5196                              int64_t       *pnResult,
5197                              fExponentiator pfExp)
5198 {
5199    uint64_t uResult;
5200    uint64_t uMantissa;
5201 
5202    /* Take the absolute value and put it into an unsigned. */
5203    if(nMantissa >= 0) {
5204       /* Positive case is straightforward */
5205       uMantissa = (uint64_t)nMantissa;
5206    } else if(nMantissa != INT64_MIN) {
5207       /* The common negative case. See next. */
5208       uMantissa = (uint64_t)-nMantissa;
5209    } else {
5210       /* int64_t and uint64_t are always two's complement per the
5211        * C standard (and since QCBOR uses these it only works with
5212        * two's complement, which is pretty much universal these
5213        * days). The range of a negative two's complement integer is
5214        * one more that than a positive, so the simple code above might
5215        * not work all the time because you can't simply negate the
5216        * value INT64_MIN because it can't be represented in an
5217        * int64_t. -INT64_MIN can however be represented in a
5218        * uint64_t. Some compilers seem to recognize this case for the
5219        * above code and put the correct value in uMantissa, however
5220        * they are not required to do this by the C standard. This next
5221        * line does however work for all compilers.
5222        *
5223        * This does assume two's complement where -INT64_MIN ==
5224        * INT64_MAX + 1 (which wouldn't be true for one's complement or
5225        * sign and magnitude (but we know we're using two's complement
5226        * because int64_t requires it)).
5227        *
5228        * See these, particularly the detailed commentary:
5229        * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
5230        * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
5231        */
5232       uMantissa = (uint64_t)INT64_MAX+1;
5233    }
5234 
5235    /* Call the exponentiator passed for either base 2 or base 10.
5236     * Here is where most of the overflow errors are caught. */
5237    QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
5238    if(uReturn) {
5239       return uReturn;
5240    }
5241 
5242    /* Convert back to the sign of the original mantissa */
5243    if(nMantissa >= 0) {
5244       if(uResult > INT64_MAX) {
5245          return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5246       }
5247       *pnResult = (int64_t)uResult;
5248    } else {
5249       /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
5250        * of INT64_MIN. This assumes two's compliment representation
5251        * where INT64_MIN is one increment farther from 0 than
5252        * INT64_MAX.  Trying to write -INT64_MIN doesn't work to get
5253        * this because the compiler makes it an int64_t which can't
5254        * represent -INT64_MIN. Also see above.
5255        */
5256       if(uResult > (uint64_t)INT64_MAX+1) {
5257          return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5258       }
5259       *pnResult = -(int64_t)uResult;
5260    }
5261 
5262    return QCBOR_SUCCESS;
5263 }
5264 
5265 
5266 /**
5267  * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
5268  *
5269  * @param[in] nMantissa  Signed integer mantissa.
5270  * @param[in] nExponent  Signed integer exponent.
5271  * @param[out] puResult  Place to put the signed integer result.
5272  * @param[in] pfExp      Exponentiation function.
5273  *
5274  * @returns Error code
5275  *
5276  * \c pfExp performs exponentiation on and unsigned mantissa and
5277  * produces an unsigned result. This errors out if the mantissa
5278  * is negative because the output is unsigned.
5279  */
5280 static QCBORError
QCBOR_Private_ExponentitateNU(const int64_t nMantissa,const int64_t nExponent,uint64_t * puResult,fExponentiator pfExp)5281 QCBOR_Private_ExponentitateNU(const int64_t  nMantissa,
5282                               const int64_t  nExponent,
5283                               uint64_t      *puResult,
5284                               fExponentiator pfExp)
5285 {
5286    if(nMantissa < 0) {
5287       return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5288    }
5289 
5290    /* Cast to unsigned is OK because of check for negative.
5291     * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
5292     * Exponentiation is straight forward
5293     */
5294    return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
5295 }
5296 
5297 
5298 /**
5299  * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
5300  *
5301  * @param[in] uMantissa  Unsigned integer mantissa.
5302  * @param[in] nExponent  Unsigned integer exponent.
5303  * @param[out] puResult  Place to put the unsigned integer result.
5304  * @param[in] pfExp      Exponentiation function.
5305  *
5306  * @returns Error code
5307  *
5308  * \c pfExp performs exponentiation on and unsigned mantissa and
5309  * produces an unsigned result so this is just a wrapper that does
5310  * nothing (and is likely inlined).
5311  */
5312 static QCBORError
QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,const int64_t nExponent,uint64_t * puResult,fExponentiator pfExp)5313 QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
5314                               const int64_t  nExponent,
5315                               uint64_t      *puResult,
5316                               fExponentiator pfExp)
5317 {
5318    return (*pfExp)(uMantissa, nExponent, puResult);
5319 }
5320 
5321 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
5322 
5323 
5324 
5325 
5326 /**
5327  * @brief Convert a CBOR big number to a uint64_t.
5328  *
5329  * @param[in] BigNum  Bytes of the big number to convert.
5330  * @param[in] uMax  Maximum value allowed for the result.
5331  * @param[out] pResult  Place to put the unsigned integer result.
5332  *
5333  * @returns Error code
5334  *
5335  * Many values will overflow because  a big num can represent a much
5336  * larger range than uint64_t.
5337  */
5338 static QCBORError
QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,const uint64_t uMax,uint64_t * pResult)5339 QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
5340                                       const uint64_t   uMax,
5341                                       uint64_t        *pResult)
5342 {
5343    uint64_t uResult;
5344 
5345    uResult = 0;
5346    const uint8_t *pByte = BigNum.ptr;
5347    size_t uLen = BigNum.len;
5348    while(uLen--) {
5349       if(uResult > (uMax >> 8)) {
5350          return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5351       }
5352       uResult = (uResult << 8) + *pByte++;
5353    }
5354 
5355    *pResult = uResult;
5356    return QCBOR_SUCCESS;
5357 }
5358 
5359 
5360 /**
5361  * @brief Convert a CBOR postive big number to a uint64_t.
5362  *
5363  * @param[in] BigNum  Bytes of the big number to convert.
5364  * @param[out] pResult  Place to put the unsigned integer result.
5365  *
5366  * @returns Error code
5367  *
5368  * Many values will overflow because  a big num can represent a much
5369  * larger range than uint64_t.
5370  */
5371 static QCBORError
QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,uint64_t * pResult)5372 QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
5373                                               uint64_t        *pResult)
5374 {
5375    return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
5376 }
5377 
5378 
5379 /**
5380  * @brief Convert a CBOR positive big number to an int64_t.
5381  *
5382  * @param[in] BigNum  Bytes of the big number to convert.
5383  * @param[out] pResult  Place to put the signed integer result.
5384  *
5385  * @returns Error code
5386  *
5387  * Many values will overflow because  a big num can represent a much
5388  * larger range than int64_t.
5389  */
5390 static QCBORError
QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,int64_t * pResult)5391 QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5392                                             int64_t         *pResult)
5393 {
5394    uint64_t uResult;
5395    QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5396                                                              INT64_MAX,
5397                                                              &uResult);
5398    if(uError) {
5399       return uError;
5400    }
5401    /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
5402    *pResult = (int64_t)uResult;
5403    return QCBOR_SUCCESS;
5404 }
5405 
5406 
5407 /**
5408  * @brief Convert a CBOR negative big number to an int64_t.
5409  *
5410  * @param[in] BigNum  Bytes of the big number to convert.
5411  * @param[out] pnResult  Place to put the signed integer result.
5412  *
5413  * @returns Error code
5414  *
5415  * Many values will overflow because  a big num can represent a much
5416  * larger range than int64_t.
5417  */
5418 static QCBORError
QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,int64_t * pnResult)5419 QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5420                                             int64_t         *pnResult)
5421 {
5422    uint64_t uResult;
5423    /* The negative integer furthest from zero for a C int64_t is
5424     * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5425     * negative number in CBOR is computed as -n - 1 where n is the
5426     * encoded integer, where n is what is in the variable BigNum. When
5427     * converting BigNum to a uint64_t, the maximum value is thus
5428     * INT64_MAX, so that when it -n - 1 is applied to it the result
5429     * will never be further from 0 than INT64_MIN.
5430     *
5431     *   -n - 1 <= INT64_MIN.
5432     *   -n - 1 <= -INT64_MAX - 1
5433     *    n     <= INT64_MAX.
5434     */
5435    QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5436                                                              INT64_MAX,
5437                                                              &uResult);
5438    if(uError != QCBOR_SUCCESS) {
5439       return uError;
5440    }
5441 
5442    /* Now apply -n - 1. The cast is safe because
5443     * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5444     * is the largest positive integer that an int64_t can
5445     * represent. */
5446    *pnResult =  -(int64_t)uResult - 1;
5447 
5448    return QCBOR_SUCCESS;
5449 }
5450 
5451 
5452 
5453 
5454 /**
5455  * @brief Convert integers and floats to an int64_t.
5456  *
5457  * @param[in] pItem   The item to convert.
5458  * @param[in] uConvertTypes  Bit mask list of conversion options.
5459  * @param[out] pnValue  The resulting converted value.
5460  *
5461  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
5462  *                                    in uConvertTypes.
5463  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
5464  * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
5465  *                                               or too small.
5466  */
5467 static QCBORError
QCBOR_Private_ConvertInt64(const QCBORItem * pItem,const uint32_t uConvertTypes,int64_t * pnValue)5468 QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5469                            const uint32_t   uConvertTypes,
5470                            int64_t         *pnValue)
5471 {
5472    switch(pItem->uDataType) {
5473       case QCBOR_TYPE_FLOAT:
5474       case QCBOR_TYPE_DOUBLE:
5475 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
5476          if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5477             /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5478              http://www.cplusplus.com/reference/cmath/llround/
5479              */
5480             // Not interested in FE_INEXACT
5481             feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5482             if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5483                *pnValue = llround(pItem->val.dfnum);
5484             } else {
5485                *pnValue = lroundf(pItem->val.fnum);
5486             }
5487             if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5488                // llround() shouldn't result in divide by zero, but catch
5489                // it here in case it unexpectedly does.  Don't try to
5490                // distinguish between the various exceptions because it seems
5491                // they vary by CPU, compiler and OS.
5492                return QCBOR_ERR_FLOAT_EXCEPTION;
5493             }
5494          } else {
5495             return  QCBOR_ERR_UNEXPECTED_TYPE;
5496          }
5497 #else
5498          return QCBOR_ERR_HW_FLOAT_DISABLED;
5499 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5500          break;
5501 
5502       case QCBOR_TYPE_INT64:
5503          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5504             *pnValue = pItem->val.int64;
5505          } else {
5506             return  QCBOR_ERR_UNEXPECTED_TYPE;
5507          }
5508          break;
5509 
5510       case QCBOR_TYPE_UINT64:
5511          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5512             if(pItem->val.uint64 < INT64_MAX) {
5513                *pnValue = pItem->val.int64;
5514             } else {
5515                return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5516             }
5517          } else {
5518             return  QCBOR_ERR_UNEXPECTED_TYPE;
5519          }
5520          break;
5521 
5522       default:
5523          return  QCBOR_ERR_UNEXPECTED_TYPE;
5524    }
5525    return QCBOR_SUCCESS;
5526 }
5527 
5528 
5529 /**
5530  * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5531  *
5532  * @param[in] pMe            The decode context.
5533  * @param[in] uConvertTypes  Bit mask list of conversion options.
5534  * @param[out] pnValue       Result of the conversion.
5535  * @param[in,out] pItem      Temporary space to store Item, returned item.
5536  *
5537  * See QCBORDecode_GetInt64Convert().
5538  */
5539 void
QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext * pMe,uint32_t uConvertTypes,int64_t * pnValue,QCBORItem * pItem)5540 QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5541                                     uint32_t            uConvertTypes,
5542                                     int64_t            *pnValue,
5543                                     QCBORItem          *pItem)
5544 {
5545    QCBORDecode_VGetNext(pMe, pItem);
5546    if(pMe->uLastError) {
5547       return;
5548    }
5549 
5550    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5551                                                          uConvertTypes,
5552                                                          pnValue);
5553 }
5554 
5555 /**
5556  * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5557  *
5558  * @param[in] pMe            The decode context.
5559  * @param[in] nLabel         Label to find in map.
5560  * @param[in] uConvertTypes  Bit mask list of conversion options.
5561  * @param[out] pnValue       Result of the conversion.
5562  * @param[in,out] pItem      Temporary space to store Item, returned item.
5563  *
5564  * See QCBORDecode_GetInt64ConvertInMapN().
5565  */
5566 void
QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext * pMe,int64_t nLabel,uint32_t uConvertTypes,int64_t * pnValue,QCBORItem * pItem)5567 QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5568                                           int64_t             nLabel,
5569                                           uint32_t            uConvertTypes,
5570                                           int64_t            *pnValue,
5571                                           QCBORItem          *pItem)
5572 {
5573    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
5574    if(pMe->uLastError != QCBOR_SUCCESS) {
5575       return;
5576    }
5577 
5578    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5579                                                          uConvertTypes,
5580                                                          pnValue);
5581 }
5582 
5583 /**
5584  * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5585  *
5586  * @param[in] pMe            The decode context.
5587  * @param[in] szLabel        Label to find in map.
5588  * @param[in] uConvertTypes  Bit mask list of conversion options.
5589  * @param[out] pnValue       Result of the conversion.
5590  * @param[in,out] pItem      Temporary space to store Item, returned item.
5591  *
5592  * See QCBORDecode_GetInt64ConvertInMapSZ().
5593  */
5594 void
QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,uint32_t uConvertTypes,int64_t * pnValue,QCBORItem * pItem)5595 QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5596                                            const char *         szLabel,
5597                                            uint32_t             uConvertTypes,
5598                                            int64_t             *pnValue,
5599                                            QCBORItem           *pItem)
5600 {
5601    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
5602    if(pMe->uLastError != QCBOR_SUCCESS) {
5603       return;
5604    }
5605 
5606    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5607                                                          uConvertTypes,
5608                                                          pnValue);
5609 }
5610 
5611 
5612 /**
5613  * @brief Convert many number types to an int64_t.
5614  *
5615  * @param[in] pItem   The item to convert.
5616  * @param[in] uConvertTypes  Bit mask list of conversion options.
5617  * @param[out] pnValue  The resulting converted value.
5618  *
5619  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
5620  *                                    in uConvertTypes.
5621  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
5622  * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
5623  *                                               or too small.
5624  */
5625 static QCBORError
QCBOR_Private_Int64ConvertAll(const QCBORItem * pItem,const uint32_t uConvertTypes,int64_t * pnValue)5626 QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5627                               const uint32_t   uConvertTypes,
5628                               int64_t         *pnValue)
5629 {
5630    switch(pItem->uDataType) {
5631 
5632       case QCBOR_TYPE_POSBIGNUM:
5633          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
5634             return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
5635          } else {
5636             return QCBOR_ERR_UNEXPECTED_TYPE;
5637          }
5638          break;
5639 
5640       case QCBOR_TYPE_NEGBIGNUM:
5641          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
5642             return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
5643          } else {
5644             return QCBOR_ERR_UNEXPECTED_TYPE;
5645          }
5646          break;
5647 
5648 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
5649       case QCBOR_TYPE_DECIMAL_FRACTION:
5650          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
5651             return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
5652                                   pItem->val.expAndMantissa.nExponent,
5653                                   pnValue,
5654                                  &QCBOR_Private_Exponentitate10);
5655          } else {
5656             return QCBOR_ERR_UNEXPECTED_TYPE;
5657          }
5658          break;
5659 
5660       case QCBOR_TYPE_BIGFLOAT:
5661          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
5662             return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
5663                                   pItem->val.expAndMantissa.nExponent,
5664                                   pnValue,
5665                                   QCBOR_Private_Exponentitate2);
5666          } else {
5667             return QCBOR_ERR_UNEXPECTED_TYPE;
5668          }
5669          break;
5670 
5671       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5672          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
5673             int64_t    nMantissa;
5674             QCBORError uErr;
5675             uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
5676             if(uErr) {
5677                return uErr;
5678             }
5679             return QCBOR_Private_ExponentiateNN(nMantissa,
5680                                   pItem->val.expAndMantissa.nExponent,
5681                                   pnValue,
5682                                   QCBOR_Private_Exponentitate10);
5683          } else {
5684             return QCBOR_ERR_UNEXPECTED_TYPE;
5685          }
5686          break;
5687 
5688       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5689          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
5690             int64_t    nMantissa;
5691             QCBORError uErr;
5692             uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
5693             if(uErr) {
5694                return uErr;
5695             }
5696             return QCBOR_Private_ExponentiateNN(nMantissa,
5697                                   pItem->val.expAndMantissa.nExponent,
5698                                   pnValue,
5699                                   QCBOR_Private_Exponentitate10);
5700          } else {
5701             return QCBOR_ERR_UNEXPECTED_TYPE;
5702          }
5703          break;
5704 
5705       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5706          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
5707             int64_t    nMantissa;
5708             QCBORError uErr;
5709             uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
5710             if(uErr) {
5711                return uErr;
5712             }
5713             return QCBOR_Private_ExponentiateNN(nMantissa,
5714                                   pItem->val.expAndMantissa.nExponent,
5715                                   pnValue,
5716                                   QCBOR_Private_Exponentitate2);
5717          } else {
5718             return QCBOR_ERR_UNEXPECTED_TYPE;
5719          }
5720          break;
5721 
5722       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5723          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
5724             int64_t    nMantissa;
5725             QCBORError uErr;
5726             uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
5727             if(uErr) {
5728                return uErr;
5729             }
5730             return QCBOR_Private_ExponentiateNN(nMantissa,
5731                                   pItem->val.expAndMantissa.nExponent,
5732                                   pnValue,
5733                                   QCBOR_Private_Exponentitate2);
5734          } else {
5735             return QCBOR_ERR_UNEXPECTED_TYPE;
5736          }
5737          break;
5738 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
5739 
5740 
5741       default:
5742          return QCBOR_ERR_UNEXPECTED_TYPE;   }
5743 }
5744 
5745 
5746 /*
5747  * Public function, see header qcbor/qcbor_decode.h file
5748  */
5749 void
QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext * pMe,const uint32_t uConvertTypes,int64_t * pnValue)5750 QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5751                                const uint32_t      uConvertTypes,
5752                                int64_t            *pnValue)
5753 {
5754    QCBORItem Item;
5755 
5756    QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
5757 
5758    if(pMe->uLastError == QCBOR_SUCCESS) {
5759       // The above conversion succeeded
5760       return;
5761    }
5762 
5763    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5764       // The above conversion failed in a way that code below can't correct
5765       return;
5766    }
5767 
5768    pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5769                                                             uConvertTypes,
5770                                                             pnValue);
5771 }
5772 
5773 
5774 /*
5775  * Public function, see header qcbor/qcbor_decode.h file
5776  */
5777 void
QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint32_t uConvertTypes,int64_t * pnValue)5778 QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5779                                      const int64_t       nLabel,
5780                                      const uint32_t      uConvertTypes,
5781                                      int64_t            *pnValue)
5782 {
5783    QCBORItem Item;
5784 
5785    QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
5786                                              nLabel,
5787                                              uConvertTypes,
5788                                              pnValue,
5789                                              &Item);
5790 
5791    if(pMe->uLastError == QCBOR_SUCCESS) {
5792       // The above conversion succeeded
5793       return;
5794    }
5795 
5796    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5797       // The above conversion failed in a way that code below can't correct
5798       return;
5799    }
5800 
5801    pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5802                                                             uConvertTypes,
5803                                                             pnValue);
5804 }
5805 
5806 
5807 /*
5808  * Public function, see header qcbor/qcbor_decode.h file
5809  */
5810 void
QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint32_t uConvertTypes,int64_t * pnValue)5811 QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5812                                       const char         *szLabel,
5813                                       const uint32_t      uConvertTypes,
5814                                       int64_t            *pnValue)
5815 {
5816    QCBORItem Item;
5817    QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
5818                                               szLabel,
5819                                               uConvertTypes,
5820                                               pnValue,
5821                                               &Item);
5822 
5823    if(pMe->uLastError == QCBOR_SUCCESS) {
5824       // The above conversion succeeded
5825       return;
5826    }
5827 
5828    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5829       // The above conversion failed in a way that code below can't correct
5830       return;
5831    }
5832 
5833    pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5834                                                             uConvertTypes,
5835                                                             pnValue);
5836 }
5837 
5838 
5839 /**
5840  * @brief Convert many number types to an uint64_t.
5841  *
5842  * @param[in] pItem   The item to convert.
5843  * @param[in] uConvertTypes  Bit mask list of conversion options.
5844  * @param[out] puValue  The resulting converted value.
5845  *
5846  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
5847  *                                    in uConvertTypes.
5848  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
5849  * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
5850  *                                               or too small.
5851  */
5852 static QCBORError
QCBOR_Private_ConvertUInt64(const QCBORItem * pItem,const uint32_t uConvertTypes,uint64_t * puValue)5853 QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5854                             const uint32_t   uConvertTypes,
5855                             uint64_t        *puValue)
5856 {
5857    switch(pItem->uDataType) {
5858       case QCBOR_TYPE_DOUBLE:
5859       case QCBOR_TYPE_FLOAT:
5860 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
5861          if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5862             // Can't use llround here because it will not convert values
5863             // greater than INT64_MAX and less than UINT64_MAX that
5864             // need to be converted so it is more complicated.
5865             feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5866             if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5867                if(isnan(pItem->val.dfnum)) {
5868                   return QCBOR_ERR_FLOAT_EXCEPTION;
5869                } else if(pItem->val.dfnum < 0) {
5870                   return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5871                } else {
5872                   double dRounded = round(pItem->val.dfnum);
5873                   // See discussion in DecodeDateEpoch() for
5874                   // explanation of - 0x7ff
5875                   if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5876                      return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5877                   }
5878                   *puValue = (uint64_t)dRounded;
5879                }
5880             } else {
5881                if(isnan(pItem->val.fnum)) {
5882                   return QCBOR_ERR_FLOAT_EXCEPTION;
5883                } else if(pItem->val.fnum < 0) {
5884                   return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5885                } else {
5886                   float fRounded = roundf(pItem->val.fnum);
5887                   // See discussion in DecodeDateEpoch() for
5888                   // explanation of - 0x7ff
5889                   if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5890                      return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5891                   }
5892                   *puValue = (uint64_t)fRounded;
5893                }
5894             }
5895             if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5896                // round() and roundf() shouldn't result in exceptions here, but
5897                // catch them to be robust and thorough. Don't try to
5898                // distinguish between the various exceptions because it seems
5899                // they vary by CPU, compiler and OS.
5900                return QCBOR_ERR_FLOAT_EXCEPTION;
5901             }
5902 
5903          } else {
5904             return QCBOR_ERR_UNEXPECTED_TYPE;
5905          }
5906 #else
5907          return QCBOR_ERR_HW_FLOAT_DISABLED;
5908 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5909          break;
5910 
5911       case QCBOR_TYPE_INT64:
5912          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5913             if(pItem->val.int64 >= 0) {
5914                *puValue = (uint64_t)pItem->val.int64;
5915             } else {
5916                return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5917             }
5918          } else {
5919             return QCBOR_ERR_UNEXPECTED_TYPE;
5920          }
5921          break;
5922 
5923       case QCBOR_TYPE_UINT64:
5924          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5925             *puValue =  pItem->val.uint64;
5926          } else {
5927             return QCBOR_ERR_UNEXPECTED_TYPE;
5928          }
5929          break;
5930 
5931       default:
5932          return QCBOR_ERR_UNEXPECTED_TYPE;
5933    }
5934 
5935    return QCBOR_SUCCESS;
5936 }
5937 
5938 
5939 /**
5940  * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5941  *
5942  * @param[in] pMe            The decode context.
5943  * @param[in] uConvertTypes  Bit mask list of conversion options.
5944  * @param[out] puValue       Result of the conversion.
5945  * @param[in,out] pItem      Temporary space to store Item, returned item.
5946  *
5947  * See QCBORDecode_GetUInt64Convert().
5948  */
5949 void
QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext * pMe,const uint32_t uConvertTypes,uint64_t * puValue,QCBORItem * pItem)5950 QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5951                                      const uint32_t      uConvertTypes,
5952                                      uint64_t           *puValue,
5953                                      QCBORItem          *pItem)
5954 {
5955    QCBORDecode_VGetNext(pMe, pItem);
5956    if(pMe->uLastError) {
5957       return;
5958    }
5959 
5960    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5961                                                           uConvertTypes,
5962                                                           puValue);
5963 }
5964 
5965 
5966 /**
5967  * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5968  *
5969  * @param[in] pMe            The decode context.
5970  * @param[in] nLabel         Label to find in map.
5971  * @param[in] uConvertTypes  Bit mask list of conversion options.
5972  * @param[out] puValue       Result of the conversion.
5973  * @param[in,out] pItem      Temporary space to store Item, returned item.
5974  *
5975  * See QCBORDecode_GetUInt64ConvertInMapN().
5976  */
5977 void
QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint32_t uConvertTypes,uint64_t * puValue,QCBORItem * pItem)5978 QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
5979                                            const int64_t       nLabel,
5980                                            const uint32_t      uConvertTypes,
5981                                            uint64_t            *puValue,
5982                                            QCBORItem          *pItem)
5983 {
5984    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
5985    if(pMe->uLastError != QCBOR_SUCCESS) {
5986       return;
5987    }
5988 
5989    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5990                                                           uConvertTypes,
5991                                                           puValue);
5992 }
5993 
5994 
5995 /**
5996  * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5997  *
5998  * @param[in] pMe            The decode context.
5999  * @param[in] szLabel         Label to find in map.
6000  * @param[in] uConvertTypes  Bit mask list of conversion options.
6001  * @param[out] puValue       Result of the conversion.
6002  * @param[in,out] pItem      Temporary space to store Item, returned item.
6003  *
6004  * See QCBORDecode_GetUInt64ConvertInMapSZ().
6005  */
6006 void
QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint32_t uConvertTypes,uint64_t * puValue,QCBORItem * pItem)6007 QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
6008                                             const char         *szLabel,
6009                                             const uint32_t      uConvertTypes,
6010                                             uint64_t           *puValue,
6011                                             QCBORItem          *pItem)
6012 {
6013    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
6014    if(pMe->uLastError != QCBOR_SUCCESS) {
6015       return;
6016    }
6017 
6018    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6019                                                           uConvertTypes,
6020                                                           puValue);
6021 }
6022 
6023 
6024 /**
6025  * @brief Convert many number types to an unt64_t.
6026  *
6027  * @param[in] pItem   The item to convert.
6028  * @param[in] uConvertTypes  Bit mask list of conversion options.
6029  * @param[out] puValue  The resulting converted value.
6030  *
6031  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
6032  *                                    in uConvertTypes.
6033  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
6034  * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
6035  *                                               or too small.
6036  */
6037 static QCBORError
QCBOR_Private_UInt64ConvertAll(const QCBORItem * pItem,const uint32_t uConvertTypes,uint64_t * puValue)6038 QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
6039                                const uint32_t   uConvertTypes,
6040                                uint64_t        *puValue)
6041 {
6042    switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
6043 
6044       case QCBOR_TYPE_POSBIGNUM:
6045          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
6046             return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
6047          } else {
6048             return QCBOR_ERR_UNEXPECTED_TYPE;
6049          }
6050          break;
6051 
6052       case QCBOR_TYPE_NEGBIGNUM:
6053          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
6054             return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6055          } else {
6056             return QCBOR_ERR_UNEXPECTED_TYPE;
6057          }
6058          break;
6059 
6060 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
6061 
6062       case QCBOR_TYPE_DECIMAL_FRACTION:
6063          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6064             return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
6065                                    pItem->val.expAndMantissa.nExponent,
6066                                    puValue,
6067                                    QCBOR_Private_Exponentitate10);
6068          } else {
6069             return QCBOR_ERR_UNEXPECTED_TYPE;
6070          }
6071          break;
6072 
6073       case QCBOR_TYPE_BIGFLOAT:
6074          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6075             return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
6076                                    pItem->val.expAndMantissa.nExponent,
6077                                    puValue,
6078                                    QCBOR_Private_Exponentitate2);
6079          } else {
6080             return QCBOR_ERR_UNEXPECTED_TYPE;
6081          }
6082          break;
6083 
6084       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6085          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6086             uint64_t   uMantissa;
6087             QCBORError uErr;
6088             uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
6089             if(uErr != QCBOR_SUCCESS) {
6090                return uErr;
6091             }
6092             return QCBOR_Private_ExponentitateUU(uMantissa,
6093                                                  pItem->val.expAndMantissa.nExponent,
6094                                                  puValue,
6095                                                  QCBOR_Private_Exponentitate10);
6096          } else {
6097             return QCBOR_ERR_UNEXPECTED_TYPE;
6098          }
6099          break;
6100 
6101       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6102          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6103             return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6104          } else {
6105             return QCBOR_ERR_UNEXPECTED_TYPE;
6106          }
6107          break;
6108 
6109       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6110          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6111             uint64_t   uMantissa;
6112             QCBORError uErr;
6113             uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
6114                                                                  &uMantissa);
6115             if(uErr != QCBOR_SUCCESS) {
6116                return uErr;
6117             }
6118             return QCBOR_Private_ExponentitateUU(uMantissa,
6119                                                  pItem->val.expAndMantissa.nExponent,
6120                                                  puValue,
6121                                                  QCBOR_Private_Exponentitate2);
6122          } else {
6123             return QCBOR_ERR_UNEXPECTED_TYPE;
6124          }
6125          break;
6126 
6127       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6128          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6129             return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6130          } else {
6131             return QCBOR_ERR_UNEXPECTED_TYPE;
6132          }
6133          break;
6134 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
6135       default:
6136          return QCBOR_ERR_UNEXPECTED_TYPE;
6137    }
6138 }
6139 
6140 
6141 /*
6142  * Public function, see header qcbor/qcbor_decode.h file
6143  */
6144 void
QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext * pMe,const uint32_t uConvertTypes,uint64_t * puValue)6145 QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
6146                                 const uint32_t      uConvertTypes,
6147                                 uint64_t           *puValue)
6148 {
6149    QCBORItem Item;
6150 
6151    QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
6152 
6153    if(pMe->uLastError == QCBOR_SUCCESS) {
6154       // The above conversion succeeded
6155       return;
6156    }
6157 
6158    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6159       // The above conversion failed in a way that code below can't correct
6160       return;
6161    }
6162 
6163    pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6164                                                              uConvertTypes,
6165                                                              puValue);
6166 }
6167 
6168 
6169 /*
6170  * Public function, see header qcbor/qcbor_decode.h file
6171  */
6172 void
QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint32_t uConvertTypes,uint64_t * puValue)6173 QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
6174                                       const int64_t       nLabel,
6175                                       const uint32_t      uConvertTypes,
6176                                       uint64_t           *puValue)
6177 {
6178    QCBORItem Item;
6179 
6180    QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
6181                                               nLabel,
6182                                               uConvertTypes,
6183                                               puValue,
6184                                               &Item);
6185 
6186    if(pMe->uLastError == QCBOR_SUCCESS) {
6187       // The above conversion succeeded
6188       return;
6189    }
6190 
6191    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6192       // The above conversion failed in a way that code below can't correct
6193       return;
6194    }
6195 
6196    pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6197                                                              uConvertTypes,
6198                                                              puValue);
6199 }
6200 
6201 
6202 /*
6203  * Public function, see header qcbor/qcbor_decode.h file
6204  */
6205 void
QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint32_t uConvertTypes,uint64_t * puValue)6206 QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
6207                                        const char         *szLabel,
6208                                        const uint32_t      uConvertTypes,
6209                                        uint64_t           *puValue)
6210 {
6211    QCBORItem Item;
6212    QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
6213                                                szLabel,
6214                                                uConvertTypes,
6215                                                puValue,
6216                                                &Item);
6217 
6218    if(pMe->uLastError == QCBOR_SUCCESS) {
6219       // The above conversion succeeded
6220       return;
6221    }
6222 
6223    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6224       // The above conversion failed in a way that code below can't correct
6225       return;
6226    }
6227 
6228    pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6229                                                              uConvertTypes,
6230                                                              puValue);
6231 }
6232 
6233 
6234 
6235 
6236 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
6237 /**
6238  * @brief Basic conversions to a double.
6239  *
6240  * @param[in] pItem          The item to convert
6241  * @param[in] uConvertTypes  Bit flags indicating source types for conversion
6242  * @param[out] pdValue       The value converted to a double
6243  *
6244  * This does the conversions that don't need much object code,
6245  * the conversions from int, uint and float to double.
6246  *
6247  * See QCBOR_Private_DoubleConvertAll() for the full set
6248  * of conversions.
6249  */
6250 static QCBORError
QCBOR_Private_ConvertDouble(const QCBORItem * pItem,const uint32_t uConvertTypes,double * pdValue)6251 QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
6252                             const uint32_t   uConvertTypes,
6253                             double          *pdValue)
6254 {
6255    switch(pItem->uDataType) {
6256       case QCBOR_TYPE_FLOAT:
6257 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
6258          if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6259             if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6260                // Simple cast does the job.
6261                *pdValue = (double)pItem->val.fnum;
6262             } else {
6263                return QCBOR_ERR_UNEXPECTED_TYPE;
6264             }
6265          }
6266 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
6267          return QCBOR_ERR_HW_FLOAT_DISABLED;
6268 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6269          break;
6270 
6271       case QCBOR_TYPE_DOUBLE:
6272          if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6273             if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6274                *pdValue = pItem->val.dfnum;
6275             } else {
6276                return QCBOR_ERR_UNEXPECTED_TYPE;
6277             }
6278          }
6279          break;
6280 
6281       case QCBOR_TYPE_INT64:
6282 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
6283          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
6284             // A simple cast seems to do the job with no worry of exceptions.
6285             // There will be precision loss for some values.
6286             *pdValue = (double)pItem->val.int64;
6287 
6288          } else {
6289             return QCBOR_ERR_UNEXPECTED_TYPE;
6290          }
6291 #else
6292          return QCBOR_ERR_HW_FLOAT_DISABLED;
6293 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6294          break;
6295 
6296       case QCBOR_TYPE_UINT64:
6297 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
6298          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
6299             // A simple cast seems to do the job with no worry of exceptions.
6300             // There will be precision loss for some values.
6301             *pdValue = (double)pItem->val.uint64;
6302          } else {
6303             return QCBOR_ERR_UNEXPECTED_TYPE;
6304          }
6305          break;
6306 #else
6307          return QCBOR_ERR_HW_FLOAT_DISABLED;
6308 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6309 
6310       default:
6311          return QCBOR_ERR_UNEXPECTED_TYPE;
6312    }
6313 
6314    return QCBOR_SUCCESS;
6315 }
6316 
6317 
6318 /**
6319  * @brief  Almost-public method to decode a number and convert to double (semi-private).
6320  *
6321  * @param[in] pMe            The decode context.
6322  * @param[in] uConvertTypes  Bit mask list of conversion options
6323  * @param[out] pdValue       The output of the conversion.
6324  * @param[in,out] pItem      Temporary space to store Item, returned item.
6325  *
6326  * See QCBORDecode_GetDoubleConvert().
6327  */
6328 void
QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext * pMe,const uint32_t uConvertTypes,double * pdValue,QCBORItem * pItem)6329 QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
6330                                      const uint32_t      uConvertTypes,
6331                                      double             *pdValue,
6332                                      QCBORItem          *pItem)
6333 {
6334    QCBORDecode_VGetNext(pMe, pItem);
6335    if(pMe->uLastError) {
6336       return;
6337    }
6338 
6339    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6340                                                           uConvertTypes,
6341                                                           pdValue);
6342 }
6343 
6344 
6345 /**
6346  * @brief  Almost-public method to decode a number and convert to double (semi-private).
6347  *
6348  * @param[in] pMe            The decode context.
6349  * @param[in] nLabel         Label to find in map.
6350  * @param[in] uConvertTypes  Bit mask list of conversion options
6351  * @param[out] pdValue       The output of the conversion.
6352  * @param[in,out] pItem      Temporary space to store Item, returned item.
6353  *
6354  * See QCBORDecode_GetDoubleConvertInMapN().
6355  */
6356 void
QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint32_t uConvertTypes,double * pdValue,QCBORItem * pItem)6357 QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6358                                            const int64_t       nLabel,
6359                                            const uint32_t      uConvertTypes,
6360                                            double             *pdValue,
6361                                            QCBORItem          *pItem)
6362 {
6363    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
6364    if(pMe->uLastError != QCBOR_SUCCESS) {
6365       return;
6366    }
6367 
6368    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6369                                                           uConvertTypes,
6370                                                           pdValue);
6371 }
6372 
6373 
6374 /**
6375  * @brief  Almost-public method to decode a number and convert to double (semi-private).
6376  *
6377  * @param[in] pMe            The decode context.
6378  * @param[in] szLabel        Label to find in map.
6379  * @param[in] uConvertTypes  Bit mask list of conversion options
6380  * @param[out] pdValue       The output of the conversion.
6381  * @param[in,out] pItem      Temporary space to store Item, returned item.
6382  *
6383  * See QCBORDecode_GetDoubleConvertInMapSZ().
6384  */
6385 void
QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint32_t uConvertTypes,double * pdValue,QCBORItem * pItem)6386 QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6387                                             const char         *szLabel,
6388                                             const uint32_t      uConvertTypes,
6389                                             double             *pdValue,
6390                                             QCBORItem          *pItem)
6391 {
6392    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
6393    if(pMe->uLastError != QCBOR_SUCCESS) {
6394       return;
6395    }
6396 
6397    pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6398                                                           uConvertTypes,
6399                                                           pdValue);
6400 }
6401 
6402 
6403 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
6404 /**
6405  * @brief Convert a big number to double-precision float.
6406  *
6407  * @param[in] BigNum   The big number to convert
6408  *
6409  * @returns  The double value.
6410  *
6411  * This will always succeed. It will lose precision for larger
6412  * numbers. If the big number is too large to fit (more than
6413  * 1.7976931348623157E+308) infinity will be returned. NaN is never
6414  * returned.
6415  */
6416 static double
QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)6417 QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
6418 {
6419    double dResult;
6420 
6421    dResult = 0.0;
6422    const uint8_t *pByte = BigNum.ptr;
6423    size_t uLen = BigNum.len;
6424    /* This will overflow and become the float value INFINITY if the number
6425     * is too large to fit. */
6426    while(uLen--) {
6427       dResult = (dResult * 256.0) + (double)*pByte++;
6428    }
6429 
6430    return dResult;
6431 }
6432 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6433 
6434 
6435 
6436 
6437 /**
6438  * @brief Convert many number types to a double.
6439  *
6440  * @param[in] pItem   The item to convert.
6441  * @param[in] uConvertTypes  Bit mask list of conversion options.
6442  * @param[out] pdValue  The resulting converted value.
6443  *
6444  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
6445  *                                    in uConvertTypes.
6446  * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
6447  * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
6448  *                                               or too small.
6449  */
6450 static QCBORError
QCBOR_Private_DoubleConvertAll(const QCBORItem * pItem,const uint32_t uConvertTypes,double * pdValue)6451 QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6452                                const uint32_t   uConvertTypes,
6453                                double          *pdValue)
6454 {
6455 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
6456    /*
6457     * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6458     * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6459     */
6460    switch(pItem->uDataType) {
6461 
6462 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
6463       case QCBOR_TYPE_DECIMAL_FRACTION:
6464          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6465             // Underflow gives 0, overflow gives infinity
6466             *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6467                         pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6468          } else {
6469             return QCBOR_ERR_UNEXPECTED_TYPE;
6470          }
6471          break;
6472 
6473       case QCBOR_TYPE_BIGFLOAT:
6474          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
6475             // Underflow gives 0, overflow gives infinity
6476             *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6477                               exp2((double)pItem->val.expAndMantissa.nExponent);
6478          } else {
6479             return QCBOR_ERR_UNEXPECTED_TYPE;
6480          }
6481          break;
6482 #endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
6483 
6484       case QCBOR_TYPE_POSBIGNUM:
6485          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
6486             *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
6487          } else {
6488             return QCBOR_ERR_UNEXPECTED_TYPE;
6489          }
6490          break;
6491 
6492       case QCBOR_TYPE_NEGBIGNUM:
6493          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
6494             *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
6495          } else {
6496             return QCBOR_ERR_UNEXPECTED_TYPE;
6497          }
6498          break;
6499 
6500 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
6501       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6502          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6503             double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6504             *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6505          } else {
6506             return QCBOR_ERR_UNEXPECTED_TYPE;
6507          }
6508          break;
6509 
6510       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6511         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6512          double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6513          *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6514          } else {
6515             return QCBOR_ERR_UNEXPECTED_TYPE;
6516          }
6517          break;
6518 
6519       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6520         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6521          double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6522          *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6523          } else {
6524             return QCBOR_ERR_UNEXPECTED_TYPE;
6525          }
6526          break;
6527 
6528       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6529         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6530          double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6531          *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6532          } else {
6533             return QCBOR_ERR_UNEXPECTED_TYPE;
6534          }
6535          break;
6536 #endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
6537 
6538       default:
6539          return QCBOR_ERR_UNEXPECTED_TYPE;
6540    }
6541 
6542    return QCBOR_SUCCESS;
6543 
6544 #else
6545    (void)pItem;
6546    (void)uConvertTypes;
6547    (void)pdValue;
6548    return QCBOR_ERR_HW_FLOAT_DISABLED;
6549 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6550 
6551 }
6552 
6553 
6554 /*
6555  * Public function, see header qcbor/qcbor_decode.h file
6556  */
6557 void
QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext * pMe,const uint32_t uConvertTypes,double * pdValue)6558 QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6559                                 const uint32_t      uConvertTypes,
6560                                 double             *pdValue)
6561 {
6562 
6563    QCBORItem Item;
6564 
6565    QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
6566 
6567    if(pMe->uLastError == QCBOR_SUCCESS) {
6568       // The above conversion succeeded
6569       return;
6570    }
6571 
6572    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6573       // The above conversion failed in a way that code below can't correct
6574       return;
6575    }
6576 
6577    pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6578                                                              uConvertTypes,
6579                                                              pdValue);
6580 }
6581 
6582 
6583 /*
6584  *  Public function, see header qcbor/qcbor_decode.h file
6585  */
6586 void
QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint32_t uConvertTypes,double * pdValue)6587 QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6588                                       const int64_t       nLabel,
6589                                       const uint32_t      uConvertTypes,
6590                                       double             *pdValue)
6591 {
6592    QCBORItem Item;
6593 
6594    QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6595                                               nLabel,
6596                                               uConvertTypes,
6597                                               pdValue,
6598                                               &Item);
6599 
6600    if(pMe->uLastError == QCBOR_SUCCESS) {
6601       // The above conversion succeeded
6602       return;
6603    }
6604 
6605    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6606       // The above conversion failed in a way that code below can't correct
6607       return;
6608    }
6609 
6610    pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6611                                                              uConvertTypes,
6612                                                              pdValue);
6613 }
6614 
6615 
6616 /*
6617  * Public function, see header qcbor/qcbor_decode.h file
6618  */
6619 void
QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint32_t uConvertTypes,double * pdValue)6620 QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6621                                        const char         *szLabel,
6622                                        const uint32_t      uConvertTypes,
6623                                        double             *pdValue)
6624 {
6625    QCBORItem Item;
6626    QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6627                                                szLabel,
6628                                                uConvertTypes,
6629                                                pdValue,
6630                                                &Item);
6631 
6632    if(pMe->uLastError == QCBOR_SUCCESS) {
6633       // The above conversion succeeded
6634       return;
6635    }
6636 
6637    if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6638       // The above conversion failed in a way that code below can't correct
6639       return;
6640    }
6641 
6642    pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6643                                                              uConvertTypes,
6644                                                              pdValue);
6645 }
6646 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
6647 
6648 
6649 
6650 
6651 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
6652 /**
6653  * @brief Convert an integer to a big number
6654  *
6655  * @param[in] uInt  The integer to convert.
6656  * @param[in] Buffer  The buffer to output the big number to.
6657  *
6658  * @returns The big number or NULLUsefulBufC is the buffer is to small.
6659  *
6660  * This always succeeds unless the buffer is too small.
6661  */
6662 static UsefulBufC
QCBOR_Private_ConvertIntToBigNum(uint64_t uInt,const UsefulBuf Buffer)6663 QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
6664 {
6665    while((uInt & 0xff00000000000000UL) == 0) {
6666       uInt = uInt << 8;
6667    };
6668 
6669    UsefulOutBuf UOB;
6670 
6671    UsefulOutBuf_Init(&UOB, Buffer);
6672 
6673    while(uInt) {
6674       UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
6675       uInt = uInt << 8;
6676    }
6677 
6678    return UsefulOutBuf_OutUBuf(&UOB);
6679 }
6680 
6681 
6682 /**
6683  * @brief Check and/or complete exponent and mantissa item.
6684  *
6685  * @param[in] pMe        The decoder context.
6686  * @param[in] TagSpec    Expected type(s).
6687  * @param[in,out] pItem  See below.
6688  *
6689  * This is for decimal fractions and big floats, both of which are an
6690  * exponent and mantissa.
6691  *
6692  * If the item item had a tag number indicating it was a
6693  * decimal fraction or big float, then the input @c pItem will
6694  * have been decoded as exponent and mantissa. If there was
6695  * no tag number, the caller is asking this be decoded as a
6696  * big float or decimal fraction and @c pItem just has the
6697  * first item in an exponent and mantissa.
6698  *
6699  * On output, the item is always a fully decoded decimal fraction or
6700  * big float.
6701  *
6702  * This errors out if the input type does not meet the TagSpec.
6703  */
6704 static QCBORError
QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext * pMe,const QCBOR_Private_TagSpec TagSpec,QCBORItem * pItem)6705 QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext         *pMe,
6706                                      const QCBOR_Private_TagSpec TagSpec,
6707                                      QCBORItem                  *pItem)
6708 {
6709    QCBORError uErr;
6710 
6711    /* pItem could either be a decoded exponent and mantissa or
6712     * the opening array of an undecoded exponent and mantissa. This
6713     * check will succeed on either, but doesn't say which it was.
6714     */
6715    uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
6716    if(uErr != QCBOR_SUCCESS) {
6717       goto Done;
6718    }
6719 
6720    if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
6721       /* The item is an array, which means is is an undecoded exponent
6722        * and mantissa. This call consumes the items in the array and
6723        * results in a decoded exponent and mantissa in pItem. This is
6724        * the case where there was no tag.
6725        */
6726       uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
6727       if(uErr != QCBOR_SUCCESS) {
6728          goto Done;
6729       }
6730 
6731       /* The above decode didn't determine whether it is a decimal
6732        * fraction or big num. Which of these two depends on what the
6733        * caller wants it decoded as since there is no tag, so fish the
6734        * type out of the TagSpec. */
6735       pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
6736 
6737       /* No need to check the type again. All that we need to know was
6738        * that it decoded correctly as a exponent and mantissa. The
6739        * QCBOR type is set out by what was requested.
6740        */
6741    }
6742 
6743    /* If the item was not an array and the check passed, then
6744     * it is a fully decoded big float or decimal fraction and
6745     * matches what is requested.
6746     */
6747 
6748 Done:
6749    return uErr;
6750 }
6751 
6752 
6753 /* Some notes from the work to disable tags.
6754  *
6755  * The API for big floats and decimal fractions seems good.
6756  * If there's any issue with it it's that the code size to
6757  * implement is a bit large because of the conversion
6758  * to/from int and bignum that is required. There is no API
6759  * that doesn't do the conversion so dead stripping will never
6760  * leave that code out.
6761  *
6762  * The implementation itself seems correct, but not as clean
6763  * and neat as it could be. It could probably be smaller too.
6764  *
6765  * The implementation has three main parts / functions
6766  *  - The decoding of the array of two
6767  *  - All the tag and type checking for the various API functions
6768  *  - Conversion to/from bignum and int
6769  *
6770  * The type checking seems like it wastes the most code for
6771  * what it needs to do.
6772  *
6773  * The inlining for the conversion is probably making the
6774  * overall code base larger.
6775  *
6776  * The tests cases could be organized a lot better and be
6777  * more thorough.
6778  *
6779  * Seems also like there could be more common code in the
6780  * first tier part of the public API. Some functions only
6781  * vary by a TagSpec.
6782  */
6783 
6784 /**
6785  * @brief Common processor for exponent and mantissa.
6786  *
6787  * @param[in] pMe          The decode context.
6788  * @param[in] TagSpec      The expected/allowed tags.
6789  * @param[in] pItem        The data item to process.
6790  * @param[out] pnMantissa  The returned mantissa as an int64_t.
6791  * @param[out] pnExponent  The returned exponent as an int64_t.
6792  *
6793  * This handles exponent and mantissa for base 2 and 10. This
6794  * is limited to a mantissa that is an int64_t. See also
6795  * QCBORDecode_Private_ProcessExpMantissaBig().
6796  */
6797 static void
QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext * pMe,const QCBOR_Private_TagSpec TagSpec,QCBORItem * pItem,int64_t * pnMantissa,int64_t * pnExponent)6798 QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext         *pMe,
6799                                  const QCBOR_Private_TagSpec TagSpec,
6800                                  QCBORItem                  *pItem,
6801                                  int64_t                    *pnMantissa,
6802                                  int64_t                    *pnExponent)
6803 {
6804    QCBORError uErr;
6805 
6806    if(pMe->uLastError) {
6807       return;
6808    }
6809 
6810    uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
6811    if(uErr != QCBOR_SUCCESS) {
6812       goto Done;
6813    }
6814 
6815    switch (pItem->uDataType) {
6816 
6817       case QCBOR_TYPE_DECIMAL_FRACTION:
6818       case QCBOR_TYPE_BIGFLOAT:
6819          *pnExponent = pItem->val.expAndMantissa.nExponent;
6820          *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
6821          break;
6822 
6823 #ifndef QCBOR_DISABLE_TAGS
6824       /* If tags are disabled, mantissas can never be big nums */
6825       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6826       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6827          *pnExponent = pItem->val.expAndMantissa.nExponent;
6828          uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
6829          break;
6830 
6831       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6832       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6833          *pnExponent = pItem->val.expAndMantissa.nExponent;
6834          uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
6835          break;
6836 #endif /* QCBOR_DISABLE_TAGS */
6837 
6838       default:
6839          uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6840    }
6841 
6842    Done:
6843       pMe->uLastError = (uint8_t)uErr;
6844 }
6845 
6846 
6847 /**
6848  * @brief Decode exponent and mantissa into a big number.
6849  *
6850  * @param[in] pMe                The decode context.
6851  * @param[in] TagSpec            The expected/allowed tags.
6852  * @param[in] pItem              Item to decode and convert.
6853  * @param[in] BufferForMantissa  Buffer to output mantissa into.
6854  * @param[out] pMantissa         The output mantissa.
6855  * @param[out] pbIsNegative      The sign of the output.
6856  * @param[out] pnExponent        The mantissa of the output.
6857  *
6858  * This is the common processing of a decimal fraction or a big float
6859  * into a big number. This will decode and consume all the CBOR items
6860  * that make up the decimal fraction or big float.
6861  */
6862 static void
QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext * pMe,const QCBOR_Private_TagSpec TagSpec,QCBORItem * pItem,const UsefulBuf BufferForMantissa,UsefulBufC * pMantissa,bool * pbIsNegative,int64_t * pnExponent)6863 QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext          *pMe,
6864                                           const QCBOR_Private_TagSpec  TagSpec,
6865                                           QCBORItem                   *pItem,
6866                                           const UsefulBuf              BufferForMantissa,
6867                                           UsefulBufC                  *pMantissa,
6868                                           bool                        *pbIsNegative,
6869                                           int64_t                     *pnExponent)
6870 {
6871    QCBORError uErr;
6872 
6873    if(pMe->uLastError != QCBOR_SUCCESS) {
6874       return;
6875    }
6876 
6877    uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
6878    if(uErr != QCBOR_SUCCESS) {
6879       goto Done;
6880    }
6881 
6882    uint64_t uMantissa;
6883 
6884    switch (pItem->uDataType) {
6885 
6886       case QCBOR_TYPE_DECIMAL_FRACTION:
6887       case QCBOR_TYPE_BIGFLOAT:
6888          /* See comments in ExponentiateNN() on handling INT64_MIN */
6889          if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6890             uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6891             *pbIsNegative = false;
6892          } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
6893             uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6894             *pbIsNegative = true;
6895          } else {
6896             uMantissa = (uint64_t)INT64_MAX+1;
6897             *pbIsNegative = true;
6898          }
6899          *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6900                                                        BufferForMantissa);
6901          *pnExponent = pItem->val.expAndMantissa.nExponent;
6902          break;
6903 
6904 #ifndef QCBOR_DISABLE_TAGS
6905       /* If tags are disabled, mantissas can never be big nums */
6906       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6907       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6908          *pnExponent = pItem->val.expAndMantissa.nExponent;
6909          *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6910          *pbIsNegative = false;
6911          break;
6912 
6913       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6914       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6915          *pnExponent = pItem->val.expAndMantissa.nExponent;
6916          *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6917          *pbIsNegative = true;
6918          break;
6919 #endif /* QCBOR_DISABLE_TAGS */
6920 
6921       default:
6922          uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6923    }
6924 
6925 Done:
6926    pMe->uLastError = (uint8_t)uErr;
6927 }
6928 
6929 
6930 /*
6931  * Public function, see header qcbor/qcbor_decode.h file
6932  */
6933 void
QCBORDecode_GetDecimalFraction(QCBORDecodeContext * pMe,const uint8_t uTagRequirement,int64_t * pnMantissa,int64_t * pnExponent)6934 QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6935                                const uint8_t       uTagRequirement,
6936                                int64_t             *pnMantissa,
6937                                int64_t             *pnExponent)
6938 {
6939    QCBORItem Item;
6940    QCBORDecode_VGetNext(pMe, &Item);
6941 
6942    const QCBOR_Private_TagSpec TagSpec =
6943    {
6944       uTagRequirement,
6945       {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6946          QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6947       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
6948    };
6949 
6950    QCBOR_Private_ProcessExpMantissa(pMe,
6951                                     TagSpec,
6952                                    &Item,
6953                                     pnMantissa,
6954                                     pnExponent);
6955 }
6956 
6957 
6958 /*
6959  * Public function, see header qcbor/qcbor_decode.h file
6960  */
6961 void
QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint8_t uTagRequirement,int64_t * pnMantissa,int64_t * pnExponent)6962 QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
6963                                      const int64_t       nLabel,
6964                                      const uint8_t       uTagRequirement,
6965                                      int64_t             *pnMantissa,
6966                                      int64_t             *pnExponent)
6967 {
6968    QCBORItem Item;
6969    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6970 
6971    const QCBOR_Private_TagSpec TagSpec =
6972    {
6973       uTagRequirement,
6974       {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6975          QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6976       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
6977    };
6978 
6979    QCBOR_Private_ProcessExpMantissa(pMe,
6980                                     TagSpec,
6981                                    &Item,
6982                                     pnMantissa,
6983                                     pnExponent);
6984 }
6985 
6986 
6987 /*
6988  * Public function, see header qcbor/qcbor_decode.h file
6989  */
6990 void
QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint8_t uTagRequirement,int64_t * pnMantissa,int64_t * pnExponent)6991 QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
6992                                       const char         *szLabel,
6993                                       const uint8_t       uTagRequirement,
6994                                       int64_t             *pnMantissa,
6995                                       int64_t             *pnExponent)
6996 {
6997    QCBORItem Item;
6998    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6999 
7000    const QCBOR_Private_TagSpec TagSpec =
7001    {
7002       uTagRequirement,
7003       {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7004          QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7005       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7006    };
7007 
7008    QCBOR_Private_ProcessExpMantissa(pMe,
7009                                     TagSpec,
7010                                    &Item,
7011                                     pnMantissa,
7012                                     pnExponent);
7013 }
7014 
7015 
7016 /*
7017  * Public function, see header qcbor/qcbor_decode.h file
7018  */
7019 void
QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext * pMe,const uint8_t uTagRequirement,const UsefulBuf MantissaBuffer,UsefulBufC * pMantissa,bool * pbMantissaIsNegative,int64_t * pnExponent)7020 QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
7021                                   const uint8_t       uTagRequirement,
7022                                   const UsefulBuf     MantissaBuffer,
7023                                   UsefulBufC         *pMantissa,
7024                                   bool               *pbMantissaIsNegative,
7025                                   int64_t            *pnExponent)
7026 {
7027    QCBORItem Item;
7028    QCBORDecode_VGetNext(pMe, &Item);
7029 
7030    const QCBOR_Private_TagSpec TagSpec =
7031    {
7032       uTagRequirement,
7033       {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7034          QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7035       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7036    };
7037 
7038    QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7039                                              TagSpec,
7040                                             &Item,
7041                                              MantissaBuffer,
7042                                              pMantissa,
7043                                              pbMantissaIsNegative,
7044                                              pnExponent);
7045 }
7046 
7047 
7048 /*
7049  * Public function, see header qcbor/qcbor_decode.h file
7050  */
7051 void
QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint8_t uTagRequirement,const UsefulBuf BufferForMantissa,UsefulBufC * pMantissa,bool * pbIsNegative,int64_t * pnExponent)7052 QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
7053                                         const int64_t       nLabel,
7054                                         const uint8_t       uTagRequirement,
7055                                         const UsefulBuf     BufferForMantissa,
7056                                         UsefulBufC         *pMantissa,
7057                                         bool               *pbIsNegative,
7058                                         int64_t            *pnExponent)
7059 {
7060 
7061    QCBORItem Item;
7062    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7063 
7064    const QCBOR_Private_TagSpec TagSpec =
7065    {
7066       uTagRequirement,
7067       {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7068          QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7069       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7070    };
7071 
7072    QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7073                                              TagSpec,
7074                                             &Item,
7075                                              BufferForMantissa,
7076                                              pMantissa,
7077                                              pbIsNegative,
7078                                              pnExponent);
7079 }
7080 
7081 
7082 /*
7083  * Public function, see header qcbor/qcbor_decode.h file
7084  */
7085 void
QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint8_t uTagRequirement,const UsefulBuf BufferForMantissa,UsefulBufC * pMantissa,bool * pbIsNegative,int64_t * pnExponent)7086 QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
7087                                          const char         *szLabel,
7088                                          const uint8_t       uTagRequirement,
7089                                          const UsefulBuf     BufferForMantissa,
7090                                          UsefulBufC         *pMantissa,
7091                                          bool               *pbIsNegative,
7092                                          int64_t            *pnExponent)
7093 {
7094    QCBORItem Item;
7095    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7096 
7097    const QCBOR_Private_TagSpec TagSpec =
7098    {
7099       uTagRequirement,
7100       {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7101          QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7102       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7103    };
7104 
7105    QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7106                                              TagSpec,
7107                                             &Item,
7108                                              BufferForMantissa,
7109                                              pMantissa,
7110                                              pbIsNegative,
7111                                              pnExponent);
7112 }
7113 
7114 
7115 /*
7116  * Public function, see header qcbor/qcbor_decode.h file
7117  */
7118 void
QCBORDecode_GetBigFloat(QCBORDecodeContext * pMe,const uint8_t uTagRequirement,int64_t * pnMantissa,int64_t * pnExponent)7119 QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
7120                         const uint8_t       uTagRequirement,
7121                         int64_t             *pnMantissa,
7122                         int64_t             *pnExponent)
7123 {
7124    QCBORItem Item;
7125    QCBORDecode_VGetNext(pMe, &Item);
7126 
7127    const QCBOR_Private_TagSpec TagSpec =
7128    {
7129       uTagRequirement,
7130       {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7131          QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7132       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7133    };
7134 
7135    QCBOR_Private_ProcessExpMantissa(pMe,
7136                                     TagSpec,
7137                                    &Item,
7138                                     pnMantissa,
7139                                     pnExponent);
7140 }
7141 
7142 
7143 /*
7144  * Public function, see header qcbor/qcbor_decode.h file
7145  */
7146 void
QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint8_t uTagRequirement,int64_t * pnMantissa,int64_t * pnExponent)7147 QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
7148                               const int64_t       nLabel,
7149                               const uint8_t       uTagRequirement,
7150                               int64_t            *pnMantissa,
7151                               int64_t            *pnExponent)
7152 {
7153    QCBORItem Item;
7154    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7155 
7156    const QCBOR_Private_TagSpec TagSpec =
7157    {
7158       uTagRequirement,
7159       {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7160          QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7161       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7162    };
7163 
7164    QCBOR_Private_ProcessExpMantissa(pMe,
7165                                     TagSpec,
7166                                    &Item,
7167                                     pnMantissa,
7168                                     pnExponent);
7169 }
7170 
7171 
7172 /*
7173  * Public function, see header qcbor/qcbor_decode.h file
7174  */
7175 void
QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint8_t uTagRequirement,int64_t * pnMantissa,int64_t * pnExponent)7176 QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
7177                                const char         *szLabel,
7178                                const uint8_t       uTagRequirement,
7179                                int64_t            *pnMantissa,
7180                                int64_t            *pnExponent)
7181 {
7182    QCBORItem Item;
7183    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7184 
7185    const QCBOR_Private_TagSpec TagSpec =
7186    {
7187       uTagRequirement,
7188       {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7189          QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7190       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7191    };
7192 
7193    QCBOR_Private_ProcessExpMantissa(pMe,
7194                                     TagSpec,
7195                                    &Item,
7196                                     pnMantissa,
7197                                     pnExponent);
7198 }
7199 
7200 
7201 /*
7202  * Public function, see header qcbor/qcbor_decode.h file
7203  */
7204 void
QCBORDecode_GetBigFloatBig(QCBORDecodeContext * pMe,const uint8_t uTagRequirement,const UsefulBuf MantissaBuffer,UsefulBufC * pMantissa,bool * pbMantissaIsNegative,int64_t * pnExponent)7205 QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
7206                            const uint8_t       uTagRequirement,
7207                            const UsefulBuf     MantissaBuffer,
7208                            UsefulBufC         *pMantissa,
7209                            bool               *pbMantissaIsNegative,
7210                            int64_t            *pnExponent)
7211 {
7212    QCBORItem Item;
7213    QCBORDecode_VGetNext(pMe, &Item);
7214 
7215    const QCBOR_Private_TagSpec TagSpec =
7216    {
7217       uTagRequirement,
7218       {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7219          QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7220       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7221    };
7222 
7223    QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7224                                              TagSpec,
7225                                             &Item,
7226                                              MantissaBuffer,
7227                                              pMantissa,
7228                                              pbMantissaIsNegative,
7229                                              pnExponent);
7230 }
7231 
7232 
7233 /*
7234  * Public function, see header qcbor/qcbor_decode.h file
7235  */
7236 void
QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext * pMe,const int64_t nLabel,const uint8_t uTagRequirement,const UsefulBuf BufferForMantissa,UsefulBufC * pMantissa,bool * pbIsNegative,int64_t * pnExponent)7237 QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
7238                                  const int64_t       nLabel,
7239                                  const uint8_t       uTagRequirement,
7240                                  const UsefulBuf     BufferForMantissa,
7241                                  UsefulBufC         *pMantissa,
7242                                  bool               *pbIsNegative,
7243                                  int64_t            *pnExponent)
7244 {
7245    QCBORItem Item;
7246    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7247 
7248    const QCBOR_Private_TagSpec TagSpec =
7249    {
7250       uTagRequirement,
7251       {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7252          QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7253       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7254    };
7255 
7256    QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7257                                              TagSpec,
7258                                             &Item,
7259                                              BufferForMantissa,
7260                                              pMantissa,
7261                                              pbIsNegative,
7262                                              pnExponent);
7263 }
7264 
7265 
7266 /*
7267  * Public function, see header qcbor/qcbor_decode.h file
7268  */
7269 void
QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext * pMe,const char * szLabel,const uint8_t uTagRequirement,const UsefulBuf BufferForMantissa,UsefulBufC * pMantissa,bool * pbIsNegative,int64_t * pnExponent)7270 QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
7271                                   const char         *szLabel,
7272                                   const uint8_t       uTagRequirement,
7273                                   const UsefulBuf     BufferForMantissa,
7274                                   UsefulBufC         *pMantissa,
7275                                   bool               *pbIsNegative,
7276                                   int64_t            *pnExponent)
7277 {
7278    QCBORItem Item;
7279    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7280 
7281    const QCBOR_Private_TagSpec TagSpec =
7282    {
7283       uTagRequirement,
7284       {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7285          QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7286       {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
7287    };
7288 
7289    QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7290                                              TagSpec,
7291                                             &Item,
7292                                              BufferForMantissa,
7293                                              pMantissa,
7294                                              pbIsNegative,
7295                                              pnExponent);
7296 }
7297 
7298 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
7299