blob: 661264e9e720f8e36e1737a093c22eea3a31a89b [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 Lundbladec5fef682020-01-25 11:38:45 -080045 01/25/2020 llundblade Cleaner handling of too-long encoded string input.
46 01/25/2020 llundblade Refine use of integer types to quiet static analysis
47 01/08/2020 llundblade Documentation corrections & improved code formatting
Laurence Lundbladeee851742020-01-08 08:37:05 -080048 12/30/19 llundblade Add support for decimal fractions and bigfloats.
49 11/07/19 llundblade Fix long long conversion to double compiler warning
50 09/07/19 llundblade Fix bug decoding empty arrays and maps
51 07/31/19 llundblade Decode error fixes for some not-well-formed CBOR
52 07/31/19 llundblade New error code for better end of data handling
53 02/17/19 llundblade Fixed: QCBORItem.u{Data|Label}Alloc when
54 bAllStrings set
55 02/16/19 llundblade Redesign MemPool to fix memory access alignment bug
56 01/10/19 llundblade Clever type and argument decoder; 250 bytes smaller
57 11/9/18 llundblade Error codes are now enums.
58 11/2/18 llundblade Simplify float decoding and align with preferred
59 float encoding
60 10/31/18 llundblade Switch to one license that is almost BSD-3.
61 10/28/18 llundblade Reworked tag decoding
62 10/15/18 llundblade Indefinite length maps and arrays supported
63 10/8/18 llundblade Indefinite length strings supported
64 02/04/17 llundbla Work on CPUs that don's require pointer alignment
65 by making use of changes in UsefulBuf
66 03/01/17 llundbla More data types; decoding improvements and fixes
67 11/13/16 llundbla Integrate most TZ changes back into github version.
68 09/30/16 gkanike Porting to TZ.
69 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080070
Laurence Lundbladeee851742020-01-08 08:37:05 -080071 =============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070072
73#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070074#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070075
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070076
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053077/*
78 This casts away the const-ness of a pointer, usually so it can be
79 freed or realloced.
80 */
81#define UNCONST_POINTER(ptr) ((void *)(ptr))
82
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070083
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070084
Laurence Lundbladeee851742020-01-08 08:37:05 -080085/*===========================================================================
86 DecodeNesting -- Functions for tracking array/map nesting when decoding
87
88 See qcbor.h for definition of the object used here: QCBORDecodeNesting
89 ===========================================================================*/
90
91inline static int
92IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070093{
94 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
95}
96
Laurence Lundbladeee851742020-01-08 08:37:05 -080097inline static int
98DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099{
100 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
101}
102
Laurence Lundbladeee851742020-01-08 08:37:05 -0800103inline static int
104DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700105{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700106 return pNesting->pCurrent->uCount == UINT16_MAX;
107}
108
Laurence Lundbladeee851742020-01-08 08:37:05 -0800109inline static uint8_t
110DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800111{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800112 // Check in DecodeNesting_Descend and never having
113 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantee cast is safe
114 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800115}
116
Laurence Lundbladeee851742020-01-08 08:37:05 -0800117inline static int
118DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700119{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700120 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700121 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700122 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800123
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700124 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
125}
126
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800127// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800128inline static QCBORError
129DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700130{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800131 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800133 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700134 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800135
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800136 // breaks can only occur when the map/array is indefinite length
137 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
138 return QCBOR_ERR_BAD_BREAK;
139 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800140
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800141 // if all OK, the break reduces the level of nesting
142 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800143
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800144 return QCBOR_SUCCESS;
145}
146
Laurence Lundbladeee851742020-01-08 08:37:05 -0800147// Called on every single item except breaks including open of a map/array
148inline static void
149DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800150{
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700151 while(DecodeNesting_IsNested(pNesting)) {
152 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800153
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800154 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700155 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800156 pNesting->pCurrent->uCount--;
157 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700158
159 if(pNesting->pCurrent->uCount != 0) {
160 // Did not close out an array or map, so nothing further
161 break;
162 }
163
164 // Closed out an array or map so level up
165 pNesting->pCurrent--;
166
167 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168 }
169}
170
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800171// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800172inline static QCBORError
173DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700175 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800176
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800177 if(pItem->val.uCount == 0) {
178 // Nothing to do for empty definite lenth arrays. They are just are
179 // effectively the same as an item that is not a map or array
180 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530181 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800182 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800183
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800184 // Error out if arrays is too long to handle
185 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
187 goto Done;
188 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800189
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800190 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700191 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
192 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
193 goto Done;
194 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800195
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800196 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800198
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800199 // Record a few details for this nesting level
200 pNesting->pCurrent->uMajorType = pItem->uDataType;
201 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800202
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700203Done:
204 return nReturn;;
205}
206
Laurence Lundbladeee851742020-01-08 08:37:05 -0800207inline static void
208DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700209{
210 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
211}
212
213
214
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700215/*
216 This list of built-in tags. Only add tags here that are
217 clearly established and useful. Once a tag is added here
218 it can't be taken out as that would break backwards compatibility.
219 There are only 48 slots available forever.
220 */
221static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800222 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
223 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
224 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
225 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
226 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
227 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700228 CBOR_TAG_COSE_ENCRYPTO,
229 CBOR_TAG_COSE_MAC0,
230 CBOR_TAG_COSE_SIGN1,
231 CBOR_TAG_ENC_AS_B64URL,
232 CBOR_TAG_ENC_AS_B64,
233 CBOR_TAG_ENC_AS_B16,
234 CBOR_TAG_CBOR,
235 CBOR_TAG_URI,
236 CBOR_TAG_B64URL,
237 CBOR_TAG_B64,
238 CBOR_TAG_REGEX,
239 CBOR_TAG_MIME,
240 CBOR_TAG_BIN_UUID,
241 CBOR_TAG_CWT,
242 CBOR_TAG_ENCRYPT,
243 CBOR_TAG_MAC,
244 CBOR_TAG_SIGN,
245 CBOR_TAG_GEO_COORD,
246 CBOR_TAG_CBOR_MAGIC
247};
248
249// This is used in a bit of cleverness in GetNext_TaggedItem() to
250// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800251// these types. This will break if the first six items in
252// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
253// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
254#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
255#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
256#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
257#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
258#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
259#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700260
Laurence Lundblade59289e52019-12-30 13:44:37 -0800261#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
262 QCBOR_TAGFLAG_DATE_EPOCH |\
263 QCBOR_TAGFLAG_POS_BIGNUM |\
264 QCBOR_TAGFLAG_NEG_BIGNUM |\
265 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
266 QCBOR_TAGFLAG_BIGFLOAT)
267
268#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
269 QCBOR_TAGFLAG_DATE_EPOCH |\
270 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700271 QCBOR_TAGFLAG_NEG_BIGNUM)
272
273#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
274#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
275#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
276
277static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
278{
279 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800280 /*
281 This is a cross-check to make sure the above array doesn't
282 accidentally get made too big. In normal conditions the above
283 test should optimize out as all the values are known at compile
284 time.
285 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700286 return -1;
287 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800288
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700289 if(uTag > UINT16_MAX) {
290 // This tag map works only on 16-bit tags
291 return -1;
292 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800293
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700294 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
295 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
296 return nTagBitIndex;
297 }
298 }
299 return -1; // Indicates no match
300}
301
302static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
303{
304 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
305 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
306 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
307 }
308 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800309
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700310 return -1; // Indicates no match
311}
312
313/*
314 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800315
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700316 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800317 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700318 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800319static QCBORError
320TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
321 uint64_t uTag,
322 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700323{
324 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
325 if(nTagBitIndex >= 0) {
326 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
327 *puTagBitIndex = (uint8_t)nTagBitIndex;
328 return QCBOR_SUCCESS;
329 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800330
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700331 if(pCallerConfiguredTagMap) {
332 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
333 return QCBOR_ERR_TOO_MANY_TAGS;
334 }
335 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
336 if(nTagBitIndex >= 0) {
337 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
338
339 *puTagBitIndex = (uint8_t)nTagBitIndex;
340 return QCBOR_SUCCESS;
341 }
342 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800343
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700344 return QCBOR_ERR_BAD_OPT_TAG;
345}
346
347
348
Laurence Lundbladeee851742020-01-08 08:37:05 -0800349/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800350 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
351
352 The following four functions are pretty wrappers for invocation of
353 the string allocator supplied by the caller.
354
Laurence Lundbladeee851742020-01-08 08:37:05 -0800355 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800356
Laurence Lundbladeee851742020-01-08 08:37:05 -0800357static inline void
358StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800359{
360 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
361}
362
Laurence Lundbladeee851742020-01-08 08:37:05 -0800363// StringAllocator_Reallocate called with pMem NULL is
364// equal to StringAllocator_Allocate()
365static inline UsefulBuf
366StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
367 void *pMem,
368 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800369{
370 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
371}
372
Laurence Lundbladeee851742020-01-08 08:37:05 -0800373static inline UsefulBuf
374StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800375{
376 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
377}
378
Laurence Lundbladeee851742020-01-08 08:37:05 -0800379static inline void
380StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800381{
382 if(pMe->pfAllocator) {
383 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
384 }
385}
386
387
388
Laurence Lundbladeee851742020-01-08 08:37:05 -0800389/*===========================================================================
390 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700391
Laurence Lundbladeee851742020-01-08 08:37:05 -0800392 See qcbor.h for definition of the object used here: QCBORDecodeContext
393 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700394/*
395 Public function, see header file
396 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800397void QCBORDecode_Init(QCBORDecodeContext *me,
398 UsefulBufC EncodedCBOR,
399 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700400{
401 memset(me, 0, sizeof(QCBORDecodeContext));
402 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800403 // Don't bother with error check on decode mode. If a bad value is
404 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700405 me->uDecodeMode = nDecodeMode;
406 DecodeNesting_Init(&(me->nesting));
407}
408
409
410/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700411 Public function, see header file
412 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800413void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
414 QCBORStringAllocate pfAllocateFunction,
415 void *pAllocateContext,
416 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700417{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800418 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
419 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
420 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700421}
422
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800423
424/*
425 Public function, see header file
426 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800427void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
428 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700429{
430 me->pCallerConfiguredTagList = pTagList;
431}
432
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700433
434/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800435 This decodes the fundamental part of a CBOR data item, the type and
436 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800437
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700438 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800439
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440 This does the network->host byte order conversion. The conversion
441 here also results in the conversion for floats in addition to that
442 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800443
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700444 This returns:
445 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800446
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800447 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800448 tags and floats and length for strings and arrays
449
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800450 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800451 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800452
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800453 The int type is preferred to uint8_t for some variables as this
454 avoids integer promotions, can reduce code size and makes
455 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700456 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800457inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
458 int *pnMajorType,
459 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800460 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700461{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700462 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800463
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700464 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800465 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800466
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800468 const int nTmpMajorType = nInitialByte >> 5;
469 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800470
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800471 // Where the number or argument accumulates
472 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800473
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800475 // Need to get 1,2,4 or 8 additional argument bytes Map
476 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800477 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800478
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800479 // Loop getting all the bytes in the argument
480 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800482 // This shift and add gives the endian conversion
483 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
484 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800485 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800486 // The reserved and thus-far unused additional info values
487 nReturn = QCBOR_ERR_UNSUPPORTED;
488 goto Done;
489 } else {
490 // Less than 24, additional info is argument or 31, an indefinite length
491 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800492 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700493 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495 if(UsefulInputBuf_GetError(pUInBuf)) {
496 nReturn = QCBOR_ERR_HIT_END;
497 goto Done;
498 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800499
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700500 // All successful if we got here.
501 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800502 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800503 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800504 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800505
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700506Done:
507 return nReturn;
508}
509
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800510
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700511/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512 CBOR doesn't explicitly specify two's compliment for integers but all
513 CPUs use it these days and the test vectors in the RFC are so. All
514 integers in the CBOR structure are positive and the major type
515 indicates positive or negative. CBOR can express positive integers
516 up to 2^x - 1 where x is the number of bits and negative integers
517 down to 2^x. Note that negative numbers can be one more away from
518 zero than positive. Stdint, as far as I can tell, uses two's
519 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800520
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700521 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800522 used carefully here, and in particular why it isn't used in the interface.
523 Also see
524 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
525
526 Int is used for values that need less than 16-bits and would be subject
527 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529inline static QCBORError
530DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700532 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800533
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
535 if (uNumber <= INT64_MAX) {
536 pDecodedItem->val.int64 = (int64_t)uNumber;
537 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800538
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700539 } else {
540 pDecodedItem->val.uint64 = uNumber;
541 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800542
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700543 }
544 } else {
545 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800546 // CBOR's representation of negative numbers lines up with the
547 // two-compliment representation. A negative integer has one
548 // more in range than a positive integer. INT64_MIN is
549 // equal to (-INT64_MAX) - 1.
550 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700551 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800552
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553 } else {
554 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000555 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556 nReturn = QCBOR_ERR_INT_OVERFLOW;
557 }
558 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800559
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700560 return nReturn;
561}
562
563// Make sure #define value line up as DecodeSimple counts on this.
564#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
565#error QCBOR_TYPE_FALSE macro value wrong
566#endif
567
568#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
569#error QCBOR_TYPE_TRUE macro value wrong
570#endif
571
572#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
573#error QCBOR_TYPE_NULL macro value wrong
574#endif
575
576#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
577#error QCBOR_TYPE_UNDEF macro value wrong
578#endif
579
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700580#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
581#error QCBOR_TYPE_BREAK macro value wrong
582#endif
583
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
585#error QCBOR_TYPE_DOUBLE macro value wrong
586#endif
587
588#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
589#error QCBOR_TYPE_FLOAT macro value wrong
590#endif
591
592/*
593 Decode true, false, floats, break...
594 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800595inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800596DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700598 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800599
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800601 // above make sure uAdditionalInfo values line up with uDataType values.
602 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
603 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800604
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800605 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800606 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
607 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800608
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700609 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700610 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
611 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700612 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700613 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700614 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
615 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700616 break;
617 case DOUBLE_PREC_FLOAT:
618 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700619 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700620 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622 case CBOR_SIMPLEV_FALSE: // 20
623 case CBOR_SIMPLEV_TRUE: // 21
624 case CBOR_SIMPLEV_NULL: // 22
625 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700626 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800628
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 case CBOR_SIMPLEV_ONEBYTE: // 24
630 if(uNumber <= CBOR_SIMPLE_BREAK) {
631 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700632 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700633 goto Done;
634 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800635 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700636 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800637
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 default: // 0-19
639 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800640 /*
641 DecodeTypeAndNumber will make uNumber equal to
642 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
643 safe because the 2, 4 and 8 byte lengths of uNumber are in
644 the double/float cases above
645 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 pDecodedItem->val.uSimple = (uint8_t)uNumber;
647 break;
648 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800649
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650Done:
651 return nReturn;
652}
653
654
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700655/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530656 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800658inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
659 int nMajorType,
660 uint64_t uStrLen,
661 UsefulInputBuf *pUInBuf,
662 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700663{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700664 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800665
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800666 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
667 // This check makes the casts to size_t below safe.
668
669 // 4 bytes less than the largest sizeof() so this can be tested by
670 // putting a SIZE_MAX length in the CBOR test input (no one will
671 // care the limit on strings is 4 bytes shorter).
672 if(uStrLen > SIZE_MAX-4) {
673 nReturn = QCBOR_ERR_STRING_TOO_LONG;
674 goto Done;
675 }
676
677 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530678 if(UsefulBuf_IsNULLC(Bytes)) {
679 // Failed to get the bytes for this string item
680 nReturn = QCBOR_ERR_HIT_END;
681 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700682 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530683
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800684 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530685 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800686 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530687 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700688 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530689 goto Done;
690 }
691 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800692 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530693 } else {
694 // Normal case with no string allocator
695 pDecodedItem->val.string = Bytes;
696 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800697 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800698 // Cast because ternary operator causes promotion to integer
699 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
700 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800701
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530702Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700703 return nReturn;
704}
705
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700706
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708
709
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700710
711
Laurence Lundbladeee851742020-01-08 08:37:05 -0800712// Make sure the constants align as this is assumed by
713// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700714#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
715#error QCBOR_TYPE_ARRAY value not lined up with major type
716#endif
717#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
718#error QCBOR_TYPE_MAP value not lined up with major type
719#endif
720
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800722 This gets a single data item and decodes it including preceding
723 optional tagging. This does not deal with arrays and maps and nesting
724 except to decode the data item introducing them. Arrays and maps are
725 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800726
Laurence Lundbladeee851742020-01-08 08:37:05 -0800727 Errors detected here include: an array that is too long to decode,
728 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800730static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
731 QCBORItem *pDecodedItem,
732 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700733{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700734 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800735
Laurence Lundbladeee851742020-01-08 08:37:05 -0800736 /*
737 Get the major type and the number. Number could be length of more
738 bytes or the value depending on the major type nAdditionalInfo is
739 an encoding of the length of the uNumber and is needed to decode
740 floats and doubles
741 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800742 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700743 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800744 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800745
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700746 memset(pDecodedItem, 0, sizeof(QCBORItem));
747
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800749
Laurence Lundbladeee851742020-01-08 08:37:05 -0800750 // Error out here if we got into trouble on the type and number. The
751 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700752 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700753 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700754 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800755
Laurence Lundbladeee851742020-01-08 08:37:05 -0800756 // At this point the major type and the value are valid. We've got
757 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700759 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
760 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800761 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700762 nReturn = QCBOR_ERR_BAD_INT;
763 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800764 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700765 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700766 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700768 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
769 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800770 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
771 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
772 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
773 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530774 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700775 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 }
778 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800779
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700780 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
781 case CBOR_MAJOR_TYPE_MAP: // Major type 5
782 // Record the number of items in the array or map
783 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
784 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
785 goto Done;
786 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800787 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530788 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800790 // type conversion OK because of check above
791 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800793 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
795 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700796 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700798 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800799 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700800 nReturn = QCBOR_ERR_BAD_INT;
801 } else {
802 pDecodedItem->val.uTagV = uNumber;
803 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
804 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700805 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundbladeee851742020-01-08 08:37:05 -0800807 case CBOR_MAJOR_TYPE_SIMPLE:
808 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800809 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700810 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundbladeee851742020-01-08 08:37:05 -0800812 default:
813 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700814 nReturn = QCBOR_ERR_UNSUPPORTED;
815 break;
816 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700818Done:
819 return nReturn;
820}
821
822
823
824/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800825 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800826 individual chunk items together into one QCBORItem using the string
827 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800828
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530829 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700830 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800831static inline QCBORError
832GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700834 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700835 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800836 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
837 &(me->StringAllocator) :
838 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530839 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800841 nReturn = GetNext_Item(&(me->InBuf),
842 pDecodedItem,
843 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 if(nReturn) {
845 goto Done;
846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530849 // code in this function from here down can be eliminated. Run tests, except
850 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800851
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800852 // Only do indefinite length processing on strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800853 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING &&
854 pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700855 goto Done; // no need to do any work here on non-string types
856 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800857
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800858 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530859 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800860 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530863 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800864 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
866 goto Done;
867 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800868
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800870 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800872
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700873 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700874 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700875 // Get item for next chunk
876 QCBORItem StringChunkItem;
877 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800878 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700879 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700880 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800882
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530883 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700884 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800885 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700886 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530887 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700888 break;
889 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800890
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700891 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530892 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700893 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800894 if(StringChunkItem.uDataType != uStringType ||
895 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700896 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897 break;
898 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530900 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800901 // The first time throurgh FullString.ptr is NULL and this is
902 // equivalent to StringAllocator_Allocate()
903 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
904 UNCONST_POINTER(FullString.ptr),
905 FullString.len + StringChunkItem.val.string.len);
906
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700907 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530908 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700909 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910 break;
911 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800912
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700913 // Copy new string chunk at the end of string so far.
914 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700917Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800918 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
919 // Getting the item failed, clean up the allocated memory
920 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700921 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700923 return nReturn;
924}
925
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700926
927/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800928 Gets all optional tag data items preceding a data item that is not an
929 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800931static QCBORError
932GetNext_TaggedItem(QCBORDecodeContext *me,
933 QCBORItem *pDecodedItem,
934 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700935{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700936 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700937 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700938 uint64_t uTagBits = 0;
939 if(pTags) {
940 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700941 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700942
Laurence Lundblade59289e52019-12-30 13:44:37 -0800943 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700944 for(;;) {
945 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700947 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700950 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
951 // Successful exit from loop; maybe got some tags, maybe not
952 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700953 break;
954 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700956 uint8_t uTagBitIndex;
957 // Tag was mapped, tag was not mapped, error with tag list
958 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800959
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700960 case QCBOR_SUCCESS:
961 // Successfully mapped the tag
962 uTagBits |= 0x01ULL << uTagBitIndex;
963 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700965 case QCBOR_ERR_BAD_OPT_TAG:
966 // Tag is not recognized. Do nothing
967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700969 default:
970 // Error Condition
971 goto Done;
972 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800973
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700974 if(pTags) {
975 // Caller wants all tags recorded in the provided buffer
976 if(pTags->uNumUsed >= pTags->uNumAllocated) {
977 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
978 goto Done;
979 }
980 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
981 pTags->uNumUsed++;
982 }
983 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700985Done:
986 return nReturn;
987}
988
989
990/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800991 This layer takes care of map entries. It combines the label and data
992 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700993 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800994static inline QCBORError
995GetNext_MapEntry(QCBORDecodeContext *me,
996 QCBORItem *pDecodedItem,
997 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700998{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700999 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001000 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001001 if(nReturn)
1002 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001004 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001005 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001006 goto Done;
1007 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001009 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1010 // In a map and caller wants maps decoded, not treated as arrays
1011
1012 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1013 // If in a map and the right decoding mode, get the label
1014
Laurence Lundbladeee851742020-01-08 08:37:05 -08001015 // Save label in pDecodedItem and get the next which will
1016 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001017 QCBORItem LabelItem = *pDecodedItem;
1018 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1019 if(nReturn)
1020 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301022 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001023
1024 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1025 // strings are always good labels
1026 pDecodedItem->label.string = LabelItem.val.string;
1027 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1028 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001029 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001030 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1031 goto Done;
1032 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1033 pDecodedItem->label.int64 = LabelItem.val.int64;
1034 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1035 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1036 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1037 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1038 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1039 pDecodedItem->label.string = LabelItem.val.string;
1040 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1041 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1042 } else {
1043 // label is not an int or a string. It is an arrray
1044 // or a float or such and this implementation doesn't handle that.
1045 // Also, tags on labels are ignored.
1046 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1047 goto Done;
1048 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001049 }
1050 } else {
1051 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1052 // Decoding a map as an array
1053 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1054 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001055 }
1056 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001057
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001058Done:
1059 return nReturn;
1060}
1061
1062
1063/*
1064 Public function, see header qcbor.h file
1065 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001066QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1067 QCBORItem *pDecodedItem,
1068 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001069{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001070 // Stack ptr/int: 2, QCBORItem : 64
1071
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301072 // The public entry point for fetching and parsing the next QCBORItem.
1073 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001074 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001076 // Check if there are an
1077 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1078 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1079 goto Done;
1080 }
1081
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001082 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001083 if(nReturn) {
1084 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301086
1087 // Break ending arrays/maps are always processed at the end of this function.
1088 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301089 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301090 nReturn = QCBOR_ERR_BAD_BREAK;
1091 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301092 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001093
Laurence Lundblade6de37062018-10-15 12:22:42 +05301094 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301095 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301096 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundblade6de37062018-10-15 12:22:42 +05301098 // Process the item just received for descent or decrement, and
1099 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001100 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001101 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001102 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001103 // Maps and arrays do count in as items in the map/array that encloses
1104 // them so a decrement needs to be done for them too, but that is done
1105 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001106 // are opened with the exception of an empty map or array.
1107 if(pDecodedItem->val.uCount == 0) {
1108 DecodeNesting_DecrementCount(&(me->nesting));
1109 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001110 } else {
1111 // Decrement the count of items in the enclosing map/array
1112 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301113 // triggers a decrement in the map/array above that and
1114 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001115 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001116 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301117 if(nReturn) {
1118 goto Done;
1119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundblade6de37062018-10-15 12:22:42 +05301121 // For indefinite length maps/arrays, looking at any and
1122 // all breaks that might terminate them. The equivalent
1123 // for definite length maps/arrays happens in
1124 // DecodeNesting_DecrementCount().
1125 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1126 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1127 // Peek forward one item to see if it is a break.
1128 QCBORItem Peek;
1129 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1130 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1131 if(nReturn) {
1132 goto Done;
1133 }
1134 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1135 // It is not a break, rewind so it can be processed normally.
1136 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1137 break;
1138 }
1139 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301140 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301141 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1142 if(nReturn) {
1143 // break occured outside of an indefinite length array/map
1144 goto Done;
1145 }
1146 }
1147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundblade6de37062018-10-15 12:22:42 +05301149 // Tell the caller what level is next. This tells them what maps/arrays
1150 // were closed out and makes it possible for them to reconstruct
1151 // the tree with just the information returned by GetNext
1152 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001153
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001154Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001155 if(nReturn != QCBOR_SUCCESS) {
1156 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1157 memset(pDecodedItem, 0, sizeof(QCBORItem));
1158 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001159 return nReturn;
1160}
1161
1162
Laurence Lundblade59289e52019-12-30 13:44:37 -08001163/*
1164 Mostly just assign the right data type for the date string.
1165 */
1166inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1167{
1168 // Stack Use: UsefulBuf 1 16
1169 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1170 return QCBOR_ERR_BAD_OPT_TAG;
1171 }
1172
1173 const UsefulBufC Temp = pDecodedItem->val.string;
1174 pDecodedItem->val.dateString = Temp;
1175 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1176 return QCBOR_SUCCESS;
1177}
1178
1179
1180/*
1181 Mostly just assign the right data type for the bignum.
1182 */
1183inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1184{
1185 // Stack Use: UsefulBuf 1 -- 16
1186 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1187 return QCBOR_ERR_BAD_OPT_TAG;
1188 }
1189 const UsefulBufC Temp = pDecodedItem->val.string;
1190 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001191 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001192 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1193 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001194 return QCBOR_SUCCESS;
1195}
1196
1197
1198/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001199 The epoch formatted date. Turns lots of different forms of encoding
1200 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001201 */
1202static int DecodeDateEpoch(QCBORItem *pDecodedItem)
1203{
1204 // Stack usage: 1
1205 QCBORError nReturn = QCBOR_SUCCESS;
1206
1207 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1208
1209 switch (pDecodedItem->uDataType) {
1210
1211 case QCBOR_TYPE_INT64:
1212 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1213 break;
1214
1215 case QCBOR_TYPE_UINT64:
1216 if(pDecodedItem->val.uint64 > INT64_MAX) {
1217 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1218 goto Done;
1219 }
1220 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
1221 break;
1222
1223 case QCBOR_TYPE_DOUBLE:
1224 {
1225 // This comparison needs to be done as a float before
1226 // conversion to an int64_t to be able to detect doubles
1227 // that are too large to fit into an int64_t. A double
1228 // has 52 bits of preceision. An int64_t has 63. Casting
1229 // INT64_MAX to a double actually causes a round up which
1230 // is bad and wrong for the comparison because it will
1231 // allow conversion of doubles that can't fit into a
1232 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1233 // the cutoff point as if that rounds up in conversion to
1234 // double it will still be less than INT64_MAX. 0x7ff is
1235 // picked because it has 11 bits set.
1236 //
1237 // INT64_MAX seconds is on the order of 10 billion years,
1238 // and the earth is less than 5 billion years old, so for
1239 // most uses this conversion error won't occur even though
1240 // doubles can go much larger.
1241 //
1242 // Without the 0x7ff there is a ~30 minute range of time
1243 // values 10 billion years in the past and in the future
1244 // where this this code would go wrong.
1245 const double d = pDecodedItem->val.dfnum;
1246 if(d > (double)(INT64_MAX - 0x7ff)) {
1247 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1248 goto Done;
1249 }
1250 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1251 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1252 }
1253 break;
1254
1255 default:
1256 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1257 goto Done;
1258 }
1259 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1260
1261Done:
1262 return nReturn;
1263}
1264
1265
1266#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1267/*
1268 Decode decimal fractions and big floats.
1269
1270 When called pDecodedItem must be the array that is tagged as a big
1271 float or decimal fraction, the array that has the two members, the
1272 exponent and mantissa.
1273
1274 This will fetch and decode the exponent and mantissa and put the
1275 result back into pDecodedItem.
1276 */
1277inline static QCBORError
1278QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1279{
1280 QCBORError nReturn;
1281
1282 // --- Make sure it is an array; track nesting level of members ---
1283 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1284 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1285 goto Done;
1286 }
1287
1288 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001289 // definite length arrays, but not for indefnite. Instead remember
1290 // the nesting level the two integers must be at, which is one
1291 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001292 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1293
1294 // --- Is it a decimal fraction or a bigfloat? ---
1295 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1296 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1297
1298 // --- Get the exponent ---
1299 QCBORItem exponentItem;
1300 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1301 if(nReturn != QCBOR_SUCCESS) {
1302 goto Done;
1303 }
1304 if(exponentItem.uNestingLevel != nNestLevel) {
1305 // Array is empty or a map/array encountered when expecting an int
1306 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1307 goto Done;
1308 }
1309 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1310 // Data arriving as an unsigned int < INT64_MAX has been converted
1311 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1312 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1313 // will be too large for this to handle and thus an error that will
1314 // get handled in the next else.
1315 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1316 } else {
1317 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1318 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1319 goto Done;
1320 }
1321
1322 // --- Get the mantissa ---
1323 QCBORItem mantissaItem;
1324 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1325 if(nReturn != QCBOR_SUCCESS) {
1326 goto Done;
1327 }
1328 if(mantissaItem.uNestingLevel != nNestLevel) {
1329 // Mantissa missing or map/array encountered when expecting number
1330 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1331 goto Done;
1332 }
1333 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1334 // Data arriving as an unsigned int < INT64_MAX has been converted
1335 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1336 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1337 // will be too large for this to handle and thus an error that
1338 // will get handled in an else below.
1339 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1340 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1341 // Got a good big num mantissa
1342 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1343 // Depends on numbering of QCBOR_TYPE_XXX
1344 pDecodedItem->uDataType += 1 + mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM;
1345 } else {
1346 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1347 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1348 goto Done;
1349 }
1350
1351 // --- Check that array only has the two numbers ---
1352 if(mantissaItem.uNextNestLevel == nNestLevel) {
1353 // Extra items in the decimal fraction / big num
1354 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1355 goto Done;
1356 }
1357
1358Done:
1359
1360 return nReturn;
1361}
1362#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1363
1364
1365/*
1366 Public function, see header qcbor.h file
1367 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001368QCBORError
1369QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1370 QCBORItem *pDecodedItem,
1371 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001372{
1373 QCBORError nReturn;
1374
1375 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1376 if(nReturn != QCBOR_SUCCESS) {
1377 goto Done;
1378 }
1379
1380#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1381#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1382#else
1383#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1384#endif
1385
1386 // Only pay attention to tags this code knows how to decode.
1387 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1388 case 0:
1389 // No tags at all or none we know about. Nothing to do.
1390 // This is the pass-through path of this function
1391 // that will mostly be taken when decoding any item.
1392 break;
1393
1394 case QCBOR_TAGFLAG_DATE_STRING:
1395 nReturn = DecodeDateString(pDecodedItem);
1396 break;
1397
1398 case QCBOR_TAGFLAG_DATE_EPOCH:
1399 nReturn = DecodeDateEpoch(pDecodedItem);
1400 break;
1401
1402 case QCBOR_TAGFLAG_POS_BIGNUM:
1403 case QCBOR_TAGFLAG_NEG_BIGNUM:
1404 nReturn = DecodeBigNum(pDecodedItem);
1405 break;
1406
1407#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1408 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1409 case QCBOR_TAGFLAG_BIGFLOAT:
1410 // For aggregate tagged types, what goes into pTags is only collected
1411 // from the surrounding data item, not the contents, so pTags is not
1412 // passed on here.
1413
1414 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1415 break;
1416#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1417
1418 default:
1419 // Encountering some mixed-up CBOR like something that
1420 // is tagged as both a string and integer date.
1421 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1422 }
1423
1424Done:
1425 if(nReturn != QCBOR_SUCCESS) {
1426 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1427 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1428 }
1429 return nReturn;
1430}
1431
1432
1433/*
1434 Public function, see header qcbor.h file
1435 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001436QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001437{
1438 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1439}
1440
1441
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001442/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301443 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301444 next one down. If a layer has no work to do for a particular item
1445 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001446
Laurence Lundblade59289e52019-12-30 13:44:37 -08001447 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1448 tagged data items, turning them into the local C representation.
1449 For the most simple it is just associating a QCBOR_TYPE with the data. For
1450 the complex ones that an aggregate of data items, there is some further
1451 decoding and a little bit of recursion.
1452
1453 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301454 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301455 out of maps/arrays. It processes all breaks that terminate
1456 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001457
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301458 - GetNext_MapEntry -- This handles the combining of two
1459 items, the label and the data, that make up a map entry.
1460 It only does work on maps. It combines the label and data
1461 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001462
Laurence Lundblade59289e52019-12-30 13:44:37 -08001463 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1464 tags into bit flags associated with the data item. No actual decoding
1465 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001466
Laurence Lundblade59289e52019-12-30 13:44:37 -08001467 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301468 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301469 string allocater to create contiguous space for the item. It
1470 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001471
Laurence Lundblade59289e52019-12-30 13:44:37 -08001472 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1473 atomic data item has a "major type", an integer "argument" and optionally
1474 some content. For text and byte strings, the content is the bytes
1475 that make up the string. These are the smallest data items that are
1476 considered to be well-formed. The content may also be other data items in
1477 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001478
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001479 Roughly this takes 300 bytes of stack for vars. Need to
1480 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001481
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301482 */
1483
1484
1485/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001486 Public function, see header qcbor.h file
1487 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001488int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1489 const QCBORItem *pItem,
1490 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001491{
1492 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001493
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001494 uint8_t uTagBitIndex;
1495 // Do not care about errors in pCallerConfiguredTagMap here. They are
1496 // caught during GetNext() before this is called.
1497 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1498 return 0;
1499 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001500
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001501 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1502 return (uTagBit & pItem->uTagBits) != 0;
1503}
1504
1505
1506/*
1507 Public function, see header qcbor.h file
1508 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001509QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001510{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001511 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001512
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001513 // Error out if all the maps/arrays are not closed out
1514 if(DecodeNesting_IsNested(&(me->nesting))) {
1515 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1516 goto Done;
1517 }
1518
1519 // Error out if not all the bytes are consumed
1520 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1521 nReturn = QCBOR_ERR_EXTRA_BYTES;
1522 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001523
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001524Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301525 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001526 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001527 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001528
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001529 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001530}
1531
1532
1533
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001534/*
1535
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001536Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001537
Laurence Lundbladeee851742020-01-08 08:37:05 -08001538 - Hit end of input before it was expected while decoding type and
1539 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001541 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001542
Laurence Lundbladeee851742020-01-08 08:37:05 -08001543 - Hit end of input while decoding a text or byte string
1544 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundbladeee851742020-01-08 08:37:05 -08001546 - Encountered conflicting tags -- e.g., an item is tagged both a date
1547 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001548
Laurence Lundbladeee851742020-01-08 08:37:05 -08001549 - Encontered an array or mapp that has too many items
1550 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001551
Laurence Lundbladeee851742020-01-08 08:37:05 -08001552 - Encountered array/map nesting that is too deep
1553 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001554
Laurence Lundbladeee851742020-01-08 08:37:05 -08001555 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1556 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001557
Laurence Lundbladeee851742020-01-08 08:37:05 -08001558 - The type of a map label is not a string or int
1559 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001560
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001561 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001562
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001563 */
1564
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001565
1566
Laurence Lundbladef6531662018-12-04 10:42:22 +09001567
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001568/* ===========================================================================
1569 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001570
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001571 This implements a simple sting allocator for indefinite length
1572 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1573 implements the function type QCBORStringAllocate and allows easy
1574 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001575
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001576 This particular allocator is built-in for convenience. The caller
1577 can implement their own. All of this following code will get
1578 dead-stripped if QCBORDecode_SetMemPool() is not called.
1579
1580 This is a very primitive memory allocator. It does not track
1581 individual allocations, only a high-water mark. A free or
1582 reallocation must be of the last chunk allocated.
1583
1584 The size of the pool and offset to free memory are packed into the
1585 first 8 bytes of the memory pool so we don't have to keep them in
1586 the decode context. Since the address of the pool may not be
1587 aligned, they have to be packed and unpacked as if they were
1588 serialized data of the wire or such.
1589
1590 The sizes packed in are uint32_t to be the same on all CPU types
1591 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001592 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001593
1594
Laurence Lundbladeee851742020-01-08 08:37:05 -08001595static inline int
1596MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001597{
1598 // Use of UsefulInputBuf is overkill, but it is convenient.
1599 UsefulInputBuf UIB;
1600
Laurence Lundbladeee851742020-01-08 08:37:05 -08001601 // Just assume the size here. It was checked during SetUp so
1602 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001603 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1604 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1605 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1606 return UsefulInputBuf_GetError(&UIB);
1607}
1608
1609
Laurence Lundbladeee851742020-01-08 08:37:05 -08001610static inline int
1611MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001612{
1613 // Use of UsefulOutBuf is overkill, but convenient. The
1614 // length check performed here is useful.
1615 UsefulOutBuf UOB;
1616
1617 UsefulOutBuf_Init(&UOB, Pool);
1618 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1619 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1620 return UsefulOutBuf_GetError(&UOB);
1621}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001622
1623
1624/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001625 Internal function for an allocation, reallocation free and destuct.
1626
1627 Having only one function rather than one each per mode saves space in
1628 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001629
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001630 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1631 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001632static UsefulBuf
1633MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001634{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001635 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001636
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001637 uint32_t uPoolSize;
1638 uint32_t uFreeOffset;
1639
1640 if(uNewSize > UINT32_MAX) {
1641 // This allocator is only good up to 4GB. This check should
1642 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1643 goto Done;
1644 }
1645 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1646
1647 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1648 goto Done;
1649 }
1650
1651 if(uNewSize) {
1652 if(pMem) {
1653 // REALLOCATION MODE
1654 // Calculate pointer to the end of the memory pool. It is
1655 // assumed that pPool + uPoolSize won't wrap around by
1656 // assuming the caller won't pass a pool buffer in that is
1657 // not in legitimate memory space.
1658 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1659
1660 // Check that the pointer for reallocation is in the range of the
1661 // pool. This also makes sure that pointer math further down
1662 // doesn't wrap under or over.
1663 if(pMem >= pPool && pMem < pPoolEnd) {
1664 // Offset to start of chunk for reallocation. This won't
1665 // wrap under because of check that pMem >= pPool. Cast
1666 // is safe because the pool is always less than UINT32_MAX
1667 // because of check in QCBORDecode_SetMemPool().
1668 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1669
1670 // Check to see if the allocation will fit. uPoolSize -
1671 // uMemOffset will not wrap under because of check that
1672 // pMem is in the range of the uPoolSize by check above.
1673 if(uNewSize <= uPoolSize - uMemOffset) {
1674 ReturnValue.ptr = pMem;
1675 ReturnValue.len = uNewSize;
1676
1677 // Addition won't wrap around over because uNewSize was
1678 // checked to be sure it is less than the pool size.
1679 uFreeOffset = uMemOffset + uNewSize32;
1680 }
1681 }
1682 } else {
1683 // ALLOCATION MODE
1684 // uPoolSize - uFreeOffset will not underflow because this
1685 // pool implementation makes sure uFreeOffset is always
1686 // smaller than uPoolSize through this check here and
1687 // reallocation case.
1688 if(uNewSize <= uPoolSize - uFreeOffset) {
1689 ReturnValue.len = uNewSize;
1690 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
1691 uFreeOffset += uNewSize;
1692 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001693 }
1694 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001695 if(pMem) {
1696 // FREE MODE
1697 // Cast is safe because of limit on pool size in
1698 // QCBORDecode_SetMemPool()
1699 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1700 } else {
1701 // DESTRUCT MODE
1702 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001703 }
1704 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001705
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001706 UsefulBuf Pool = {pPool, uPoolSize};
1707 MemPool_Pack(Pool, uFreeOffset);
1708
1709Done:
1710 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001711}
1712
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001713
Laurence Lundbladef6531662018-12-04 10:42:22 +09001714/*
1715 Public function, see header qcbor.h file
1716 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001717QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1718 UsefulBuf Pool,
1719 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001720{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001721 // The pool size and free mem offset are packed into the beginning
1722 // of the pool memory. This compile time check make sure the
1723 // constant in the header is correct. This check should optimize
1724 // down to nothing.
1725 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001726 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001727 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001728
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001729 // The pool size and free offset packed in to the beginning of pool
1730 // memory are only 32-bits. This check will optimize out on 32-bit
1731 // machines.
1732 if(Pool.len > UINT32_MAX) {
1733 return QCBOR_ERR_BUFFER_TOO_LARGE;
1734 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001735
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001736 // This checks that the pool buffer given is big enough.
1737 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1738 return QCBOR_ERR_BUFFER_TOO_SMALL;
1739 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001740
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001741 pMe->StringAllocator.pfAllocator = MemPool_Function;
1742 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1743 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001744
Laurence Lundblade30816f22018-11-10 13:40:22 +07001745 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001746}