blob: 532da1ea9db843f0c2aac75f9653451202c7254f [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundbladeee851742020-01-08 08:37:05 -080033/*==============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070034 FILE: qcbor_decode.c
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080035
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036 DESCRIPTION: This file contains the implementation of QCBOR.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070040 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080042
Laurence Lundbladeee851742020-01-08 08:37:05 -080043 when who what, where, why
44 -------- ---- ---------------------------------------------------
Laurence Lundblade06350ea2020-01-27 19:32:40 -080045 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
Laurence Lundbladec5fef682020-01-25 11:38:45 -080046 01/25/2020 llundblade Cleaner handling of too-long encoded string input.
47 01/25/2020 llundblade Refine use of integer types to quiet static analysis
48 01/08/2020 llundblade Documentation corrections & improved code formatting
Laurence Lundbladeee851742020-01-08 08:37:05 -080049 12/30/19 llundblade Add support for decimal fractions and bigfloats.
50 11/07/19 llundblade Fix long long conversion to double compiler warning
51 09/07/19 llundblade Fix bug decoding empty arrays and maps
52 07/31/19 llundblade Decode error fixes for some not-well-formed CBOR
53 07/31/19 llundblade New error code for better end of data handling
54 02/17/19 llundblade Fixed: QCBORItem.u{Data|Label}Alloc when
55 bAllStrings set
56 02/16/19 llundblade Redesign MemPool to fix memory access alignment bug
57 01/10/19 llundblade Clever type and argument decoder; 250 bytes smaller
58 11/9/18 llundblade Error codes are now enums.
59 11/2/18 llundblade Simplify float decoding and align with preferred
60 float encoding
61 10/31/18 llundblade Switch to one license that is almost BSD-3.
62 10/28/18 llundblade Reworked tag decoding
63 10/15/18 llundblade Indefinite length maps and arrays supported
64 10/8/18 llundblade Indefinite length strings supported
65 02/04/17 llundbla Work on CPUs that don's require pointer alignment
66 by making use of changes in UsefulBuf
67 03/01/17 llundbla More data types; decoding improvements and fixes
68 11/13/16 llundbla Integrate most TZ changes back into github version.
69 09/30/16 gkanike Porting to TZ.
70 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080071
Laurence Lundbladeee851742020-01-08 08:37:05 -080072 =============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070073
74#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070075#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070076
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053078/*
79 This casts away the const-ness of a pointer, usually so it can be
80 freed or realloced.
81 */
82#define UNCONST_POINTER(ptr) ((void *)(ptr))
83
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070084
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070085
Laurence Lundbladeee851742020-01-08 08:37:05 -080086/*===========================================================================
87 DecodeNesting -- Functions for tracking array/map nesting when decoding
88
89 See qcbor.h for definition of the object used here: QCBORDecodeNesting
90 ===========================================================================*/
91
92inline static int
93IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094{
95 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
96}
97
Laurence Lundbladeee851742020-01-08 08:37:05 -080098inline static int
99DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100{
101 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
102}
103
Laurence Lundbladeee851742020-01-08 08:37:05 -0800104inline static int
105DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700106{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700107 return pNesting->pCurrent->uCount == UINT16_MAX;
108}
109
Laurence Lundbladeee851742020-01-08 08:37:05 -0800110inline static uint8_t
111DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800112{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800113 // Check in DecodeNesting_Descend and never having
114 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantee cast is safe
115 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800116}
117
Laurence Lundbladeee851742020-01-08 08:37:05 -0800118inline static int
119DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700120{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700121 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700122 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700123 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800124
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
126}
127
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800128// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800129inline static QCBORError
130DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700131{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800132 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700133 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800134 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800137 // breaks can only occur when the map/array is indefinite length
138 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
139 return QCBOR_ERR_BAD_BREAK;
140 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800141
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800142 // if all OK, the break reduces the level of nesting
143 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800144
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800145 return QCBOR_SUCCESS;
146}
147
Laurence Lundbladeee851742020-01-08 08:37:05 -0800148// Called on every single item except breaks including open of a map/array
149inline static void
150DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800151{
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700152 while(DecodeNesting_IsNested(pNesting)) {
153 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800154
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800155 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700156 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800157 pNesting->pCurrent->uCount--;
158 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700159
160 if(pNesting->pCurrent->uCount != 0) {
161 // Did not close out an array or map, so nothing further
162 break;
163 }
164
165 // Closed out an array or map so level up
166 pNesting->pCurrent--;
167
168 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700169 }
170}
171
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800173inline static QCBORError
174DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700176 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800177
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178 if(pItem->val.uCount == 0) {
179 // Nothing to do for empty definite lenth arrays. They are just are
180 // effectively the same as an item that is not a map or array
181 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530182 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800184
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800185 // Error out if arrays is too long to handle
186 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700187 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
188 goto Done;
189 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800190
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800191 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700192 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
193 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
194 goto Done;
195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800196
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800197 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700198 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800199
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800200 // Record a few details for this nesting level
201 pNesting->pCurrent->uMajorType = pItem->uDataType;
202 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800203
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700204Done:
205 return nReturn;;
206}
207
Laurence Lundbladeee851742020-01-08 08:37:05 -0800208inline static void
209DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700210{
211 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
212}
213
214
215
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700216/*
217 This list of built-in tags. Only add tags here that are
218 clearly established and useful. Once a tag is added here
219 it can't be taken out as that would break backwards compatibility.
220 There are only 48 slots available forever.
221 */
222static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800223 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
224 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
225 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
226 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
227 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
228 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700229 CBOR_TAG_COSE_ENCRYPTO,
230 CBOR_TAG_COSE_MAC0,
231 CBOR_TAG_COSE_SIGN1,
232 CBOR_TAG_ENC_AS_B64URL,
233 CBOR_TAG_ENC_AS_B64,
234 CBOR_TAG_ENC_AS_B16,
235 CBOR_TAG_CBOR,
236 CBOR_TAG_URI,
237 CBOR_TAG_B64URL,
238 CBOR_TAG_B64,
239 CBOR_TAG_REGEX,
240 CBOR_TAG_MIME,
241 CBOR_TAG_BIN_UUID,
242 CBOR_TAG_CWT,
243 CBOR_TAG_ENCRYPT,
244 CBOR_TAG_MAC,
245 CBOR_TAG_SIGN,
246 CBOR_TAG_GEO_COORD,
247 CBOR_TAG_CBOR_MAGIC
248};
249
250// This is used in a bit of cleverness in GetNext_TaggedItem() to
251// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800252// these types. This will break if the first six items in
253// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
254// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
255#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
256#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
257#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
258#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
259#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
260#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700261
Laurence Lundblade59289e52019-12-30 13:44:37 -0800262#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
263 QCBOR_TAGFLAG_DATE_EPOCH |\
264 QCBOR_TAGFLAG_POS_BIGNUM |\
265 QCBOR_TAGFLAG_NEG_BIGNUM |\
266 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
267 QCBOR_TAGFLAG_BIGFLOAT)
268
269#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
270 QCBOR_TAGFLAG_DATE_EPOCH |\
271 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700272 QCBOR_TAGFLAG_NEG_BIGNUM)
273
274#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
275#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
276#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
277
278static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
279{
280 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800281 /*
282 This is a cross-check to make sure the above array doesn't
283 accidentally get made too big. In normal conditions the above
284 test should optimize out as all the values are known at compile
285 time.
286 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700287 return -1;
288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700290 if(uTag > UINT16_MAX) {
291 // This tag map works only on 16-bit tags
292 return -1;
293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800294
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700295 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
296 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
297 return nTagBitIndex;
298 }
299 }
300 return -1; // Indicates no match
301}
302
303static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
304{
305 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
306 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
307 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
308 }
309 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800310
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700311 return -1; // Indicates no match
312}
313
314/*
315 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800316
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700317 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800318 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700319 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800320static QCBORError
321TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
322 uint64_t uTag,
323 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700324{
325 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
326 if(nTagBitIndex >= 0) {
327 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
328 *puTagBitIndex = (uint8_t)nTagBitIndex;
329 return QCBOR_SUCCESS;
330 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800331
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700332 if(pCallerConfiguredTagMap) {
333 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
334 return QCBOR_ERR_TOO_MANY_TAGS;
335 }
336 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
337 if(nTagBitIndex >= 0) {
338 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
339
340 *puTagBitIndex = (uint8_t)nTagBitIndex;
341 return QCBOR_SUCCESS;
342 }
343 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800344
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700345 return QCBOR_ERR_BAD_OPT_TAG;
346}
347
348
349
Laurence Lundbladeee851742020-01-08 08:37:05 -0800350/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800351 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
352
353 The following four functions are pretty wrappers for invocation of
354 the string allocator supplied by the caller.
355
Laurence Lundbladeee851742020-01-08 08:37:05 -0800356 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800357
Laurence Lundbladeee851742020-01-08 08:37:05 -0800358static inline void
359StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800360{
361 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
362}
363
Laurence Lundbladeee851742020-01-08 08:37:05 -0800364// StringAllocator_Reallocate called with pMem NULL is
365// equal to StringAllocator_Allocate()
366static inline UsefulBuf
367StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
368 void *pMem,
369 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800370{
371 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
372}
373
Laurence Lundbladeee851742020-01-08 08:37:05 -0800374static inline UsefulBuf
375StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800376{
377 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
378}
379
Laurence Lundbladeee851742020-01-08 08:37:05 -0800380static inline void
381StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800382{
383 if(pMe->pfAllocator) {
384 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
385 }
386}
387
388
389
Laurence Lundbladeee851742020-01-08 08:37:05 -0800390/*===========================================================================
391 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700392
Laurence Lundbladeee851742020-01-08 08:37:05 -0800393 See qcbor.h for definition of the object used here: QCBORDecodeContext
394 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395/*
396 Public function, see header file
397 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800398void QCBORDecode_Init(QCBORDecodeContext *me,
399 UsefulBufC EncodedCBOR,
400 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700401{
402 memset(me, 0, sizeof(QCBORDecodeContext));
403 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800404 // Don't bother with error check on decode mode. If a bad value is
405 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700406 me->uDecodeMode = nDecodeMode;
407 DecodeNesting_Init(&(me->nesting));
408}
409
410
411/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700412 Public function, see header file
413 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800414void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
415 QCBORStringAllocate pfAllocateFunction,
416 void *pAllocateContext,
417 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700418{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800419 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
420 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
421 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700422}
423
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800424
425/*
426 Public function, see header file
427 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800428void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
429 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700430{
431 me->pCallerConfiguredTagList = pTagList;
432}
433
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700434
435/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800436 This decodes the fundamental part of a CBOR data item, the type and
437 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800438
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700439 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800440
Laurence Lundbladeee851742020-01-08 08:37:05 -0800441 This does the network->host byte order conversion. The conversion
442 here also results in the conversion for floats in addition to that
443 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800444
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700445 This returns:
446 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800447
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800448 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800449 tags and floats and length for strings and arrays
450
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800451 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800452 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800453
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800454 The int type is preferred to uint8_t for some variables as this
455 avoids integer promotions, can reduce code size and makes
456 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700457 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800458inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
459 int *pnMajorType,
460 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800461 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700462{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700463 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800464
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700465 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800466 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800467
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700468 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800469 const int nTmpMajorType = nInitialByte >> 5;
470 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800471
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800472 // Where the number or argument accumulates
473 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800474
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800475 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800476 // Need to get 1,2,4 or 8 additional argument bytes Map
477 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800478 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800479
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800480 // Loop getting all the bytes in the argument
481 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800482 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800483 // This shift and add gives the endian conversion
484 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
485 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800486 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800487 // The reserved and thus-far unused additional info values
488 nReturn = QCBOR_ERR_UNSUPPORTED;
489 goto Done;
490 } else {
491 // Less than 24, additional info is argument or 31, an indefinite length
492 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800493 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700494 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800495
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700496 if(UsefulInputBuf_GetError(pUInBuf)) {
497 nReturn = QCBOR_ERR_HIT_END;
498 goto Done;
499 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700501 // All successful if we got here.
502 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800503 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800504 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800505 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700507Done:
508 return nReturn;
509}
510
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800511
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700512/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513 CBOR doesn't explicitly specify two's compliment for integers but all
514 CPUs use it these days and the test vectors in the RFC are so. All
515 integers in the CBOR structure are positive and the major type
516 indicates positive or negative. CBOR can express positive integers
517 up to 2^x - 1 where x is the number of bits and negative integers
518 down to 2^x. Note that negative numbers can be one more away from
519 zero than positive. Stdint, as far as I can tell, uses two's
520 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800521
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700522 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800523 used carefully here, and in particular why it isn't used in the interface.
524 Also see
525 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
526
527 Int is used for values that need less than 16-bits and would be subject
528 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700529 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800530inline static QCBORError
531DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700533 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800534
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
536 if (uNumber <= INT64_MAX) {
537 pDecodedItem->val.int64 = (int64_t)uNumber;
538 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800539
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 } else {
541 pDecodedItem->val.uint64 = uNumber;
542 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800543
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544 }
545 } else {
546 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800547 // CBOR's representation of negative numbers lines up with the
548 // two-compliment representation. A negative integer has one
549 // more in range than a positive integer. INT64_MIN is
550 // equal to (-INT64_MAX) - 1.
551 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800553
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700554 } else {
555 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000556 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557 nReturn = QCBOR_ERR_INT_OVERFLOW;
558 }
559 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800560
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561 return nReturn;
562}
563
564// Make sure #define value line up as DecodeSimple counts on this.
565#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
566#error QCBOR_TYPE_FALSE macro value wrong
567#endif
568
569#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
570#error QCBOR_TYPE_TRUE macro value wrong
571#endif
572
573#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
574#error QCBOR_TYPE_NULL macro value wrong
575#endif
576
577#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
578#error QCBOR_TYPE_UNDEF macro value wrong
579#endif
580
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
582#error QCBOR_TYPE_BREAK macro value wrong
583#endif
584
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
586#error QCBOR_TYPE_DOUBLE macro value wrong
587#endif
588
589#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
590#error QCBOR_TYPE_FLOAT macro value wrong
591#endif
592
593/*
594 Decode true, false, floats, break...
595 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800597DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700599 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800600
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800602 // above make sure uAdditionalInfo values line up with uDataType values.
603 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
604 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800605
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800607 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
608 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700610 case HALF_PREC_FLOAT:
Laurence Lundblade9682a532020-06-06 18:33:04 -0700611#ifndef QCBOR_CONFIG_DISABLE_ENCODE_IEEE754
612 // The caast to uint16_t is safe because the encoded value
613 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700614 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
615 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700616#else
617 nReturn = QCBOR_ERR_UNSUPPORTED;
618#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700619 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700620 case SINGLE_PREC_FLOAT:
Laurence Lundblade9682a532020-06-06 18:33:04 -0700621#ifndef QCBOR_CONFIG_DISABLE_ENCODE_IEEE754
622 // The caast to uint32_t is safe because the encoded value
623 // was 16 bits. It was widened to 64 bits to be passed in here.
624 pDecodedItem->val.dfnum = IEEE754_FloatToDouble((uint32_t)uNumber);
625#else
626 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
627 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
628#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700629 break;
630 case DOUBLE_PREC_FLOAT:
631 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700632 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700633 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 case CBOR_SIMPLEV_FALSE: // 20
636 case CBOR_SIMPLEV_TRUE: // 21
637 case CBOR_SIMPLEV_NULL: // 22
638 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700639 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800641
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 case CBOR_SIMPLEV_ONEBYTE: // 24
643 if(uNumber <= CBOR_SIMPLE_BREAK) {
644 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700645 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 goto Done;
647 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800648 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 default: // 0-19
652 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800653 /*
654 DecodeTypeAndNumber will make uNumber equal to
655 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
656 safe because the 2, 4 and 8 byte lengths of uNumber are in
657 the double/float cases above
658 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700659 pDecodedItem->val.uSimple = (uint8_t)uNumber;
660 break;
661 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800662
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663Done:
664 return nReturn;
665}
666
667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530669 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700670 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800671inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
672 int nMajorType,
673 uint64_t uStrLen,
674 UsefulInputBuf *pUInBuf,
675 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700676{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700677 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800678
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800679 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
680 // This check makes the casts to size_t below safe.
681
682 // 4 bytes less than the largest sizeof() so this can be tested by
683 // putting a SIZE_MAX length in the CBOR test input (no one will
684 // care the limit on strings is 4 bytes shorter).
685 if(uStrLen > SIZE_MAX-4) {
686 nReturn = QCBOR_ERR_STRING_TOO_LONG;
687 goto Done;
688 }
689
690 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530691 if(UsefulBuf_IsNULLC(Bytes)) {
692 // Failed to get the bytes for this string item
693 nReturn = QCBOR_ERR_HIT_END;
694 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700695 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530696
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800697 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530698 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530700 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700701 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530702 goto Done;
703 }
704 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800705 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530706 } else {
707 // Normal case with no string allocator
708 pDecodedItem->val.string = Bytes;
709 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800710 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 // Cast because ternary operator causes promotion to integer
712 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
713 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530715Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700716 return nReturn;
717}
718
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700719
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721
722
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700723
724
Laurence Lundbladeee851742020-01-08 08:37:05 -0800725// Make sure the constants align as this is assumed by
726// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700727#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
728#error QCBOR_TYPE_ARRAY value not lined up with major type
729#endif
730#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
731#error QCBOR_TYPE_MAP value not lined up with major type
732#endif
733
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800735 This gets a single data item and decodes it including preceding
736 optional tagging. This does not deal with arrays and maps and nesting
737 except to decode the data item introducing them. Arrays and maps are
738 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800739
Laurence Lundbladeee851742020-01-08 08:37:05 -0800740 Errors detected here include: an array that is too long to decode,
741 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800743static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
744 QCBORItem *pDecodedItem,
745 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700746{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700747 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800748
Laurence Lundbladeee851742020-01-08 08:37:05 -0800749 /*
750 Get the major type and the number. Number could be length of more
751 bytes or the value depending on the major type nAdditionalInfo is
752 an encoding of the length of the uNumber and is needed to decode
753 floats and doubles
754 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800755 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700756 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800757 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800758
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700759 memset(pDecodedItem, 0, sizeof(QCBORItem));
760
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800761 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800762
Laurence Lundbladeee851742020-01-08 08:37:05 -0800763 // Error out here if we got into trouble on the type and number. The
764 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700765 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700766 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700767 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundbladeee851742020-01-08 08:37:05 -0800769 // At this point the major type and the value are valid. We've got
770 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800771 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700772 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
773 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800774 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700775 nReturn = QCBOR_ERR_BAD_INT;
776 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800777 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700778 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800780
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
782 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800783 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
784 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
785 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
786 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530787 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800789 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700790 }
791 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700793 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
794 case CBOR_MAJOR_TYPE_MAP: // Major type 5
795 // Record the number of items in the array or map
796 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
797 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
798 goto Done;
799 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530801 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700802 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800803 // type conversion OK because of check above
804 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700805 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800806 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800807 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
808 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700809 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700811 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800812 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700813 nReturn = QCBOR_ERR_BAD_INT;
814 } else {
815 pDecodedItem->val.uTagV = uNumber;
816 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
817 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700818 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800819
Laurence Lundbladeee851742020-01-08 08:37:05 -0800820 case CBOR_MAJOR_TYPE_SIMPLE:
821 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800822 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700823 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800824
Laurence Lundbladeee851742020-01-08 08:37:05 -0800825 default:
826 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700827 nReturn = QCBOR_ERR_UNSUPPORTED;
828 break;
829 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800830
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700831Done:
832 return nReturn;
833}
834
835
836
837/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800838 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800839 individual chunk items together into one QCBORItem using the string
840 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530842 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800844static inline QCBORError
845GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700846{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700847 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700848 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800849 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
850 &(me->StringAllocator) :
851 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530852 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800853
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800854 nReturn = GetNext_Item(&(me->InBuf),
855 pDecodedItem,
856 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700857 if(nReturn) {
858 goto Done;
859 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800860
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530862 // code in this function from here down can be eliminated. Run tests, except
863 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800864
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800865 // Only do indefinite length processing on strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800866 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING &&
867 pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700868 goto Done; // no need to do any work here on non-string types
869 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800871 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530872 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800873 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700874 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530876 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800877 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
879 goto Done;
880 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800883 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700886 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700888 // Get item for next chunk
889 QCBORItem StringChunkItem;
890 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800891 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700893 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800895
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530896 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700897 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800898 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530900 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901 break;
902 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700904 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530905 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700906 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800907 if(StringChunkItem.uDataType != uStringType ||
908 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700909 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910 break;
911 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800912
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530913 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800914 // The first time throurgh FullString.ptr is NULL and this is
915 // equivalent to StringAllocator_Allocate()
916 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
917 UNCONST_POINTER(FullString.ptr),
918 FullString.len + StringChunkItem.val.string.len);
919
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530921 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700922 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700923 break;
924 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800925
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700926 // Copy new string chunk at the end of string so far.
927 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800931 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
932 // Getting the item failed, clean up the allocated memory
933 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700934 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800935
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700936 return nReturn;
937}
938
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700939
940/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800941 Gets all optional tag data items preceding a data item that is not an
942 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700943 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800944static QCBORError
945GetNext_TaggedItem(QCBORDecodeContext *me,
946 QCBORItem *pDecodedItem,
947 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700949 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700950 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700951 uint64_t uTagBits = 0;
952 if(pTags) {
953 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700955
Laurence Lundblade59289e52019-12-30 13:44:37 -0800956 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700957 for(;;) {
958 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700959 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700960 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700961 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800962
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700963 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
964 // Successful exit from loop; maybe got some tags, maybe not
965 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700966 break;
967 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700969 uint8_t uTagBitIndex;
970 // Tag was mapped, tag was not mapped, error with tag list
971 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700973 case QCBOR_SUCCESS:
974 // Successfully mapped the tag
975 uTagBits |= 0x01ULL << uTagBitIndex;
976 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700978 case QCBOR_ERR_BAD_OPT_TAG:
979 // Tag is not recognized. Do nothing
980 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800981
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700982 default:
983 // Error Condition
984 goto Done;
985 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800986
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700987 if(pTags) {
988 // Caller wants all tags recorded in the provided buffer
989 if(pTags->uNumUsed >= pTags->uNumAllocated) {
990 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
991 goto Done;
992 }
993 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
994 pTags->uNumUsed++;
995 }
996 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800997
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700998Done:
999 return nReturn;
1000}
1001
1002
1003/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004 This layer takes care of map entries. It combines the label and data
1005 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001006 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001007static inline QCBORError
1008GetNext_MapEntry(QCBORDecodeContext *me,
1009 QCBORItem *pDecodedItem,
1010 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001011{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001012 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001013 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001014 if(nReturn)
1015 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001016
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001017 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001018 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001019 goto Done;
1020 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001022 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1023 // In a map and caller wants maps decoded, not treated as arrays
1024
1025 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1026 // If in a map and the right decoding mode, get the label
1027
Laurence Lundbladeee851742020-01-08 08:37:05 -08001028 // Save label in pDecodedItem and get the next which will
1029 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001030 QCBORItem LabelItem = *pDecodedItem;
1031 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1032 if(nReturn)
1033 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301035 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001036
1037 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1038 // strings are always good labels
1039 pDecodedItem->label.string = LabelItem.val.string;
1040 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1041 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001042 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001043 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1044 goto Done;
1045 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1046 pDecodedItem->label.int64 = LabelItem.val.int64;
1047 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1048 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1049 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1050 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1051 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1052 pDecodedItem->label.string = LabelItem.val.string;
1053 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1054 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1055 } else {
1056 // label is not an int or a string. It is an arrray
1057 // or a float or such and this implementation doesn't handle that.
1058 // Also, tags on labels are ignored.
1059 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1060 goto Done;
1061 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001062 }
1063 } else {
1064 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1065 // Decoding a map as an array
1066 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1067 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001068 }
1069 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001070
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071Done:
1072 return nReturn;
1073}
1074
1075
1076/*
1077 Public function, see header qcbor.h file
1078 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001079QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1080 QCBORItem *pDecodedItem,
1081 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001082{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001083 // Stack ptr/int: 2, QCBORItem : 64
1084
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301085 // The public entry point for fetching and parsing the next QCBORItem.
1086 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001087 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001089 // Check if there are an
1090 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1091 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1092 goto Done;
1093 }
1094
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001095 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001096 if(nReturn) {
1097 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001098 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301099
1100 // Break ending arrays/maps are always processed at the end of this function.
1101 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301102 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301103 nReturn = QCBOR_ERR_BAD_BREAK;
1104 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301105 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001106
Laurence Lundblade6de37062018-10-15 12:22:42 +05301107 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301108 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301109 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001110
Laurence Lundblade6de37062018-10-15 12:22:42 +05301111 // Process the item just received for descent or decrement, and
1112 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001113 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001114 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001115 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001116 // Maps and arrays do count in as items in the map/array that encloses
1117 // them so a decrement needs to be done for them too, but that is done
1118 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001119 // are opened with the exception of an empty map or array.
1120 if(pDecodedItem->val.uCount == 0) {
1121 DecodeNesting_DecrementCount(&(me->nesting));
1122 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001123 } else {
1124 // Decrement the count of items in the enclosing map/array
1125 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301126 // triggers a decrement in the map/array above that and
1127 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001128 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001129 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301130 if(nReturn) {
1131 goto Done;
1132 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001133
Laurence Lundblade6de37062018-10-15 12:22:42 +05301134 // For indefinite length maps/arrays, looking at any and
1135 // all breaks that might terminate them. The equivalent
1136 // for definite length maps/arrays happens in
1137 // DecodeNesting_DecrementCount().
1138 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1139 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1140 // Peek forward one item to see if it is a break.
1141 QCBORItem Peek;
1142 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1143 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1144 if(nReturn) {
1145 goto Done;
1146 }
1147 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1148 // It is not a break, rewind so it can be processed normally.
1149 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1150 break;
1151 }
1152 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301153 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301154 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1155 if(nReturn) {
1156 // break occured outside of an indefinite length array/map
1157 goto Done;
1158 }
1159 }
1160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001161
Laurence Lundblade6de37062018-10-15 12:22:42 +05301162 // Tell the caller what level is next. This tells them what maps/arrays
1163 // were closed out and makes it possible for them to reconstruct
1164 // the tree with just the information returned by GetNext
1165 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001166
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001167Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001168 if(nReturn != QCBOR_SUCCESS) {
1169 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1170 memset(pDecodedItem, 0, sizeof(QCBORItem));
1171 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001172 return nReturn;
1173}
1174
1175
Laurence Lundblade59289e52019-12-30 13:44:37 -08001176/*
1177 Mostly just assign the right data type for the date string.
1178 */
1179inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1180{
1181 // Stack Use: UsefulBuf 1 16
1182 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1183 return QCBOR_ERR_BAD_OPT_TAG;
1184 }
1185
1186 const UsefulBufC Temp = pDecodedItem->val.string;
1187 pDecodedItem->val.dateString = Temp;
1188 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1189 return QCBOR_SUCCESS;
1190}
1191
1192
1193/*
1194 Mostly just assign the right data type for the bignum.
1195 */
1196inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1197{
1198 // Stack Use: UsefulBuf 1 -- 16
1199 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1200 return QCBOR_ERR_BAD_OPT_TAG;
1201 }
1202 const UsefulBufC Temp = pDecodedItem->val.string;
1203 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001204 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001205 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1206 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001207 return QCBOR_SUCCESS;
1208}
1209
1210
1211/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001212 The epoch formatted date. Turns lots of different forms of encoding
1213 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001214 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001215static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001216{
1217 // Stack usage: 1
1218 QCBORError nReturn = QCBOR_SUCCESS;
1219
1220 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1221
1222 switch (pDecodedItem->uDataType) {
1223
1224 case QCBOR_TYPE_INT64:
1225 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1226 break;
1227
1228 case QCBOR_TYPE_UINT64:
1229 if(pDecodedItem->val.uint64 > INT64_MAX) {
1230 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1231 goto Done;
1232 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001233 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001234 break;
1235
Laurence Lundblade9682a532020-06-06 18:33:04 -07001236 // TODO: test this with float and half input
Laurence Lundblade59289e52019-12-30 13:44:37 -08001237 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001238 case QCBOR_TYPE_FLOAT:
1239#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001240 {
1241 // This comparison needs to be done as a float before
1242 // conversion to an int64_t to be able to detect doubles
1243 // that are too large to fit into an int64_t. A double
1244 // has 52 bits of preceision. An int64_t has 63. Casting
1245 // INT64_MAX to a double actually causes a round up which
1246 // is bad and wrong for the comparison because it will
1247 // allow conversion of doubles that can't fit into a
1248 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
Laurence Lundblade9682a532020-06-06 18:33:04 -07001249 // the cutoff point because if that value rounds up in conversion to
Laurence Lundblade59289e52019-12-30 13:44:37 -08001250 // double it will still be less than INT64_MAX. 0x7ff is
1251 // picked because it has 11 bits set.
1252 //
1253 // INT64_MAX seconds is on the order of 10 billion years,
1254 // and the earth is less than 5 billion years old, so for
1255 // most uses this conversion error won't occur even though
1256 // doubles can go much larger.
1257 //
1258 // Without the 0x7ff there is a ~30 minute range of time
1259 // values 10 billion years in the past and in the future
Laurence Lundblade9682a532020-06-06 18:33:04 -07001260 // where this this code would go wrong and some compilers
1261 // will generate warnings or errors.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001262 const double d = pDecodedItem->val.dfnum;
1263 if(d > (double)(INT64_MAX - 0x7ff)) {
1264 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1265 goto Done;
1266 }
1267 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1268 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1269 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001270#else
1271 /* Disabling float support causes a floating point
1272 data to error in the default below. The above code
1273 requires floating point conversion to integers and
1274 comparison which requires either floating point HW
1275 or a SW library. */
1276
1277 nReturn = QCBOR_ERR_FLOAT_DATE_UNSUPPORTED;
1278#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001279 break;
1280
Laurence Lundblade9682a532020-06-06 18:33:04 -07001281
Laurence Lundblade59289e52019-12-30 13:44:37 -08001282 default:
1283 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1284 goto Done;
1285 }
1286 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1287
1288Done:
1289 return nReturn;
1290}
1291
1292
1293#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1294/*
1295 Decode decimal fractions and big floats.
1296
1297 When called pDecodedItem must be the array that is tagged as a big
1298 float or decimal fraction, the array that has the two members, the
1299 exponent and mantissa.
1300
1301 This will fetch and decode the exponent and mantissa and put the
1302 result back into pDecodedItem.
1303 */
1304inline static QCBORError
1305QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1306{
1307 QCBORError nReturn;
1308
1309 // --- Make sure it is an array; track nesting level of members ---
1310 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1311 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1312 goto Done;
1313 }
1314
1315 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001316 // definite length arrays, but not for indefnite. Instead remember
1317 // the nesting level the two integers must be at, which is one
1318 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001319 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1320
1321 // --- Is it a decimal fraction or a bigfloat? ---
1322 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1323 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1324
1325 // --- Get the exponent ---
1326 QCBORItem exponentItem;
1327 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1328 if(nReturn != QCBOR_SUCCESS) {
1329 goto Done;
1330 }
1331 if(exponentItem.uNestingLevel != nNestLevel) {
1332 // Array is empty or a map/array encountered when expecting an int
1333 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1334 goto Done;
1335 }
1336 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1337 // Data arriving as an unsigned int < INT64_MAX has been converted
1338 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1339 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1340 // will be too large for this to handle and thus an error that will
1341 // get handled in the next else.
1342 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1343 } else {
1344 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1345 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1346 goto Done;
1347 }
1348
1349 // --- Get the mantissa ---
1350 QCBORItem mantissaItem;
1351 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1352 if(nReturn != QCBOR_SUCCESS) {
1353 goto Done;
1354 }
1355 if(mantissaItem.uNestingLevel != nNestLevel) {
1356 // Mantissa missing or map/array encountered when expecting number
1357 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1358 goto Done;
1359 }
1360 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1361 // Data arriving as an unsigned int < INT64_MAX has been converted
1362 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1363 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1364 // will be too large for this to handle and thus an error that
1365 // will get handled in an else below.
1366 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1367 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1368 // Got a good big num mantissa
1369 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1370 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001371 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1372 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1373 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001374 } else {
1375 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1376 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1377 goto Done;
1378 }
1379
1380 // --- Check that array only has the two numbers ---
1381 if(mantissaItem.uNextNestLevel == nNestLevel) {
1382 // Extra items in the decimal fraction / big num
1383 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1384 goto Done;
1385 }
1386
1387Done:
1388
1389 return nReturn;
1390}
1391#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1392
1393
1394/*
1395 Public function, see header qcbor.h file
1396 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001397QCBORError
1398QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1399 QCBORItem *pDecodedItem,
1400 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001401{
1402 QCBORError nReturn;
1403
1404 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1405 if(nReturn != QCBOR_SUCCESS) {
1406 goto Done;
1407 }
1408
1409#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1410#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1411#else
1412#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1413#endif
1414
1415 // Only pay attention to tags this code knows how to decode.
1416 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1417 case 0:
1418 // No tags at all or none we know about. Nothing to do.
1419 // This is the pass-through path of this function
1420 // that will mostly be taken when decoding any item.
1421 break;
1422
1423 case QCBOR_TAGFLAG_DATE_STRING:
1424 nReturn = DecodeDateString(pDecodedItem);
1425 break;
1426
1427 case QCBOR_TAGFLAG_DATE_EPOCH:
1428 nReturn = DecodeDateEpoch(pDecodedItem);
1429 break;
1430
1431 case QCBOR_TAGFLAG_POS_BIGNUM:
1432 case QCBOR_TAGFLAG_NEG_BIGNUM:
1433 nReturn = DecodeBigNum(pDecodedItem);
1434 break;
1435
1436#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1437 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1438 case QCBOR_TAGFLAG_BIGFLOAT:
1439 // For aggregate tagged types, what goes into pTags is only collected
1440 // from the surrounding data item, not the contents, so pTags is not
1441 // passed on here.
1442
1443 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1444 break;
1445#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1446
1447 default:
1448 // Encountering some mixed-up CBOR like something that
1449 // is tagged as both a string and integer date.
1450 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1451 }
1452
1453Done:
1454 if(nReturn != QCBOR_SUCCESS) {
1455 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1456 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1457 }
1458 return nReturn;
1459}
1460
1461
1462/*
1463 Public function, see header qcbor.h file
1464 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001465QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001466{
1467 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1468}
1469
1470
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001471/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301472 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301473 next one down. If a layer has no work to do for a particular item
1474 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001475
Laurence Lundblade59289e52019-12-30 13:44:37 -08001476 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1477 tagged data items, turning them into the local C representation.
1478 For the most simple it is just associating a QCBOR_TYPE with the data. For
1479 the complex ones that an aggregate of data items, there is some further
1480 decoding and a little bit of recursion.
1481
1482 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301483 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301484 out of maps/arrays. It processes all breaks that terminate
1485 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001486
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301487 - GetNext_MapEntry -- This handles the combining of two
1488 items, the label and the data, that make up a map entry.
1489 It only does work on maps. It combines the label and data
1490 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001491
Laurence Lundblade59289e52019-12-30 13:44:37 -08001492 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1493 tags into bit flags associated with the data item. No actual decoding
1494 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001495
Laurence Lundblade59289e52019-12-30 13:44:37 -08001496 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301497 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301498 string allocater to create contiguous space for the item. It
1499 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001500
Laurence Lundblade59289e52019-12-30 13:44:37 -08001501 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1502 atomic data item has a "major type", an integer "argument" and optionally
1503 some content. For text and byte strings, the content is the bytes
1504 that make up the string. These are the smallest data items that are
1505 considered to be well-formed. The content may also be other data items in
1506 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001507
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001508 Roughly this takes 300 bytes of stack for vars. Need to
1509 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001510
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301511 */
1512
1513
1514/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001515 Public function, see header qcbor.h file
1516 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001517int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1518 const QCBORItem *pItem,
1519 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001520{
1521 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001522
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001523 uint8_t uTagBitIndex;
1524 // Do not care about errors in pCallerConfiguredTagMap here. They are
1525 // caught during GetNext() before this is called.
1526 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1527 return 0;
1528 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001529
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001530 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1531 return (uTagBit & pItem->uTagBits) != 0;
1532}
1533
1534
1535/*
1536 Public function, see header qcbor.h file
1537 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001538QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001539{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001540 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001541
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001542 // Error out if all the maps/arrays are not closed out
1543 if(DecodeNesting_IsNested(&(me->nesting))) {
1544 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1545 goto Done;
1546 }
1547
1548 // Error out if not all the bytes are consumed
1549 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1550 nReturn = QCBOR_ERR_EXTRA_BYTES;
1551 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001552
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001553Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301554 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001555 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001556 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001557
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001558 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001559}
1560
1561
1562
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001563/*
1564
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001565Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001566
Laurence Lundbladeee851742020-01-08 08:37:05 -08001567 - Hit end of input before it was expected while decoding type and
1568 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001569
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001570 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001571
Laurence Lundbladeee851742020-01-08 08:37:05 -08001572 - Hit end of input while decoding a text or byte string
1573 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001574
Laurence Lundbladeee851742020-01-08 08:37:05 -08001575 - Encountered conflicting tags -- e.g., an item is tagged both a date
1576 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001577
Laurence Lundbladeee851742020-01-08 08:37:05 -08001578 - Encontered an array or mapp that has too many items
1579 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001580
Laurence Lundbladeee851742020-01-08 08:37:05 -08001581 - Encountered array/map nesting that is too deep
1582 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001583
Laurence Lundbladeee851742020-01-08 08:37:05 -08001584 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1585 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001586
Laurence Lundbladeee851742020-01-08 08:37:05 -08001587 - The type of a map label is not a string or int
1588 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001589
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001590 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001592 */
1593
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001594
1595
Laurence Lundbladef6531662018-12-04 10:42:22 +09001596
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001597/* ===========================================================================
1598 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001599
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001600 This implements a simple sting allocator for indefinite length
1601 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1602 implements the function type QCBORStringAllocate and allows easy
1603 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001604
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001605 This particular allocator is built-in for convenience. The caller
1606 can implement their own. All of this following code will get
1607 dead-stripped if QCBORDecode_SetMemPool() is not called.
1608
1609 This is a very primitive memory allocator. It does not track
1610 individual allocations, only a high-water mark. A free or
1611 reallocation must be of the last chunk allocated.
1612
1613 The size of the pool and offset to free memory are packed into the
1614 first 8 bytes of the memory pool so we don't have to keep them in
1615 the decode context. Since the address of the pool may not be
1616 aligned, they have to be packed and unpacked as if they were
1617 serialized data of the wire or such.
1618
1619 The sizes packed in are uint32_t to be the same on all CPU types
1620 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001621 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001622
1623
Laurence Lundbladeee851742020-01-08 08:37:05 -08001624static inline int
1625MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001626{
1627 // Use of UsefulInputBuf is overkill, but it is convenient.
1628 UsefulInputBuf UIB;
1629
Laurence Lundbladeee851742020-01-08 08:37:05 -08001630 // Just assume the size here. It was checked during SetUp so
1631 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001632 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1633 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1634 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1635 return UsefulInputBuf_GetError(&UIB);
1636}
1637
1638
Laurence Lundbladeee851742020-01-08 08:37:05 -08001639static inline int
1640MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001641{
1642 // Use of UsefulOutBuf is overkill, but convenient. The
1643 // length check performed here is useful.
1644 UsefulOutBuf UOB;
1645
1646 UsefulOutBuf_Init(&UOB, Pool);
1647 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1648 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1649 return UsefulOutBuf_GetError(&UOB);
1650}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001651
1652
1653/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001654 Internal function for an allocation, reallocation free and destuct.
1655
1656 Having only one function rather than one each per mode saves space in
1657 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001658
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001659 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1660 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001661static UsefulBuf
1662MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001663{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001664 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001665
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001666 uint32_t uPoolSize;
1667 uint32_t uFreeOffset;
1668
1669 if(uNewSize > UINT32_MAX) {
1670 // This allocator is only good up to 4GB. This check should
1671 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1672 goto Done;
1673 }
1674 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1675
1676 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1677 goto Done;
1678 }
1679
1680 if(uNewSize) {
1681 if(pMem) {
1682 // REALLOCATION MODE
1683 // Calculate pointer to the end of the memory pool. It is
1684 // assumed that pPool + uPoolSize won't wrap around by
1685 // assuming the caller won't pass a pool buffer in that is
1686 // not in legitimate memory space.
1687 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1688
1689 // Check that the pointer for reallocation is in the range of the
1690 // pool. This also makes sure that pointer math further down
1691 // doesn't wrap under or over.
1692 if(pMem >= pPool && pMem < pPoolEnd) {
1693 // Offset to start of chunk for reallocation. This won't
1694 // wrap under because of check that pMem >= pPool. Cast
1695 // is safe because the pool is always less than UINT32_MAX
1696 // because of check in QCBORDecode_SetMemPool().
1697 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1698
1699 // Check to see if the allocation will fit. uPoolSize -
1700 // uMemOffset will not wrap under because of check that
1701 // pMem is in the range of the uPoolSize by check above.
1702 if(uNewSize <= uPoolSize - uMemOffset) {
1703 ReturnValue.ptr = pMem;
1704 ReturnValue.len = uNewSize;
1705
1706 // Addition won't wrap around over because uNewSize was
1707 // checked to be sure it is less than the pool size.
1708 uFreeOffset = uMemOffset + uNewSize32;
1709 }
1710 }
1711 } else {
1712 // ALLOCATION MODE
1713 // uPoolSize - uFreeOffset will not underflow because this
1714 // pool implementation makes sure uFreeOffset is always
1715 // smaller than uPoolSize through this check here and
1716 // reallocation case.
1717 if(uNewSize <= uPoolSize - uFreeOffset) {
1718 ReturnValue.len = uNewSize;
1719 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001720 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001721 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001722 }
1723 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001724 if(pMem) {
1725 // FREE MODE
1726 // Cast is safe because of limit on pool size in
1727 // QCBORDecode_SetMemPool()
1728 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1729 } else {
1730 // DESTRUCT MODE
1731 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001732 }
1733 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001734
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001735 UsefulBuf Pool = {pPool, uPoolSize};
1736 MemPool_Pack(Pool, uFreeOffset);
1737
1738Done:
1739 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001740}
1741
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001742
Laurence Lundbladef6531662018-12-04 10:42:22 +09001743/*
1744 Public function, see header qcbor.h file
1745 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001746QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1747 UsefulBuf Pool,
1748 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001749{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001750 // The pool size and free mem offset are packed into the beginning
1751 // of the pool memory. This compile time check make sure the
1752 // constant in the header is correct. This check should optimize
1753 // down to nothing.
1754 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001755 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001756 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001757
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001758 // The pool size and free offset packed in to the beginning of pool
1759 // memory are only 32-bits. This check will optimize out on 32-bit
1760 // machines.
1761 if(Pool.len > UINT32_MAX) {
1762 return QCBOR_ERR_BUFFER_TOO_LARGE;
1763 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001764
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001765 // This checks that the pool buffer given is big enough.
1766 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1767 return QCBOR_ERR_BUFFER_TOO_SMALL;
1768 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001769
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001770 pMe->StringAllocator.pfAllocator = MemPool_Function;
1771 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1772 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001773
Laurence Lundblade30816f22018-11-10 13:40:22 +07001774 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001775}