blob: 6df81fcfd642dc4cc1cb422dc589178bb91c1767 [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.
3 Copyright (c) 2018, Laurence Lundblade.
4 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 Lundblade624405d2018-09-18 20:10:47 -070031 ==============================================================================*/
32
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070033/*===================================================================================
34 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 Lundbladeb69cad72018-09-13 11:09:01 -070043 when who what, where, why
44 -------- ---- ---------------------------------------------------
Laurence Lundblade4c0cf842019-01-12 03:25:44 -080045 01/10/19 llundblade Clever type and argument decoder is 250 bytes smaller
Laurence Lundblade8b06e2e2018-12-04 12:26:51 +090046 11/9/18 llundblade Error codes are now enums.
47 11/2/18 llundblade Simplify float decoding and align with preferred
48 float encoding
49 10/31/18 llundblade Switch to one license that is almost BSD-3.
50 10/28/18 llundblade Reworked tag decoding
51 10/15/18 llundblade Indefinite length maps and arrays supported
52 10/8/18 llundblade Indefinite length strings supported
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053 02/04/17 llundbla Work on CPUs that don's require pointer alignment
54 by making use of changes in UsefulBuf
55 03/01/17 llundbla More data types; decoding improvements and fixes
56 11/13/16 llundbla Integrate most TZ changes back into github version.
57 09/30/16 gkanike Porting to TZ.
58 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080059
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070060 =====================================================================================*/
61
62#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070063#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070064
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070065
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053066/*
67 This casts away the const-ness of a pointer, usually so it can be
68 freed or realloced.
69 */
70#define UNCONST_POINTER(ptr) ((void *)(ptr))
71
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070072
73/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080074 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070075 */
76
77inline static int IsMapOrArray(uint8_t uDataType)
78{
79 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
80}
81
82inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
83{
84 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
85}
86
Laurence Lundblade041ffa52018-10-07 11:43:51 +070087inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070088{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070089 return pNesting->pCurrent->uCount == UINT16_MAX;
90}
91
Laurence Lundblade3a760b02018-10-08 13:46:03 +080092inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
93{
94 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
95}
96
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
98{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070099 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700101 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800102
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700103 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
104}
105
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800106// Process a break. This will either ascend the nesting or error out
Laurence Lundblade30816f22018-11-10 13:40:22 +0700107inline static QCBORError DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700108{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800109 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700110 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800111 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800113
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800114 // breaks can only occur when the map/array is indefinite length
115 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
116 return QCBOR_ERR_BAD_BREAK;
117 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800119 // if all OK, the break reduces the level of nesting
120 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800121
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800122 return QCBOR_SUCCESS;
123}
124
125// Called on every single item except breaks including the opening of a map/array
126inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
127{
128 if(!DecodeNesting_IsNested(pNesting)) {
129 // at top level where there is no tracking
130 return;
131 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800132
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800133 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
134 // There is no count for indefinite length arrays/maps
135 return;
136 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800137
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800138 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700139 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700140
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800141 // Pop up nesting levels if the counts at the levels are zero
142 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700143 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800144 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
145 pNesting->pCurrent->uCount--;
146 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700147 }
148}
149
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800150// Called on every map/array
Laurence Lundblade30816f22018-11-10 13:40:22 +0700151inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700153 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800154
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800155 if(pItem->val.uCount == 0) {
156 // Nothing to do for empty definite lenth arrays. They are just are
157 // effectively the same as an item that is not a map or array
158 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530159 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800161
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800162 // Error out if arrays is too long to handle
163 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
165 goto Done;
166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800167
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800168 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700169 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
170 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
171 goto Done;
172 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800173
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800174 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800176
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800177 // Record a few details for this nesting level
178 pNesting->pCurrent->uMajorType = pItem->uDataType;
179 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800180
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700181Done:
182 return nReturn;;
183}
184
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700185inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
186{
187 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
188}
189
190
191
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700192/*
193 This list of built-in tags. Only add tags here that are
194 clearly established and useful. Once a tag is added here
195 it can't be taken out as that would break backwards compatibility.
196 There are only 48 slots available forever.
197 */
198static const uint16_t spBuiltInTagMap[] = {
199 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR
200 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
201 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
202 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
203 CBOR_TAG_FRACTION,
204 CBOR_TAG_BIGFLOAT,
205 CBOR_TAG_COSE_ENCRYPTO,
206 CBOR_TAG_COSE_MAC0,
207 CBOR_TAG_COSE_SIGN1,
208 CBOR_TAG_ENC_AS_B64URL,
209 CBOR_TAG_ENC_AS_B64,
210 CBOR_TAG_ENC_AS_B16,
211 CBOR_TAG_CBOR,
212 CBOR_TAG_URI,
213 CBOR_TAG_B64URL,
214 CBOR_TAG_B64,
215 CBOR_TAG_REGEX,
216 CBOR_TAG_MIME,
217 CBOR_TAG_BIN_UUID,
218 CBOR_TAG_CWT,
219 CBOR_TAG_ENCRYPT,
220 CBOR_TAG_MAC,
221 CBOR_TAG_SIGN,
222 CBOR_TAG_GEO_COORD,
223 CBOR_TAG_CBOR_MAGIC
224};
225
226// This is used in a bit of cleverness in GetNext_TaggedItem() to
227// keep code size down and switch for the internal processing of
228// these types. This will break if the first four items in
229// spBuiltInTagMap don't have values 0,1,2,3. That is the
230// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3.
231#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
232#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
233#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
234#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
235
236#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
237 QCBOR_TAGFLAG_DATE_EPOCH |\
238 QCBOR_TAGFLAG_POS_BIGNUM |\
239 QCBOR_TAGFLAG_NEG_BIGNUM)
240
241#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
242#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
243#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
244
245static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
246{
247 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
248 // This is a cross-check to make sure the above array doesn't
249 // accidentally get made too big.
250 // In normal conditions the above test should optimize out
251 // as all the values are known at compile time.
252 return -1;
253 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800254
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700255 if(uTag > UINT16_MAX) {
256 // This tag map works only on 16-bit tags
257 return -1;
258 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800259
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700260 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
261 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
262 return nTagBitIndex;
263 }
264 }
265 return -1; // Indicates no match
266}
267
268static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
269{
270 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
271 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
272 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
273 }
274 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800275
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700276 return -1; // Indicates no match
277}
278
279/*
280 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800281
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700282 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700284 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700285static QCBORError TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700286{
287 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
288 if(nTagBitIndex >= 0) {
289 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
290 *puTagBitIndex = (uint8_t)nTagBitIndex;
291 return QCBOR_SUCCESS;
292 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800293
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700294 if(pCallerConfiguredTagMap) {
295 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
296 return QCBOR_ERR_TOO_MANY_TAGS;
297 }
298 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
299 if(nTagBitIndex >= 0) {
300 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
301
302 *puTagBitIndex = (uint8_t)nTagBitIndex;
303 return QCBOR_SUCCESS;
304 }
305 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800306
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700307 return QCBOR_ERR_BAD_OPT_TAG;
308}
309
310
311
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700312
313/*
314 Public function, see header file
315 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800316void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700317{
318 memset(me, 0, sizeof(QCBORDecodeContext));
319 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
320 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
321 // if the default normal mode of 0 was set.
322 me->uDecodeMode = nDecodeMode;
323 DecodeNesting_Init(&(me->nesting));
324}
325
326
327/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700328 Public function, see header file
329 */
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530330void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700331{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700332 pCtx->pStringAllocator = (void *)pAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530333 pCtx->bStringAllocateAll = bAllocAll;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700334}
335
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700336void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
337{
338 me->pCallerConfiguredTagList = pTagList;
339}
340
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700341
342/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700343 This decodes the fundamental part of a CBOR data item, the type and number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800344
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700345 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800346
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700347 This does the network->host byte order conversion. The conversion here
348 also results in the conversion for floats in addition to that for
349 lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800350
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700351 This returns:
352 pnMajorType -- the major type for the item
353 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
354 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800355
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700356 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800357inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
358 int *pnMajorType,
359 uint64_t *puArgument,
360 uint8_t *puAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700361{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700362 QCBORError nReturn;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800363
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700364 // Get the initial byte that every CBOR data item has
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800365 const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf);
366
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700367 // Break down the initial byte
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800368 const uint8_t uTmpMajorType = uInitialByte >> 5;
369 const uint8_t uAdditionalInfo = uInitialByte & 0x1f;
370
371 // Where the number or argument accumulates
372 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800373
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800374 if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
375 // Need to get 1,2,4 or 8 additional argument bytes
376 // Map LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
377 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800378
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800379 // Loop getting all the bytes in the argument
380 uArgument = 0;
381 for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
382 // This shift and add gives the endian conversion
383 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
384 }
385 } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) {
386 // The reserved and thus-far unused additional info values
387 nReturn = QCBOR_ERR_UNSUPPORTED;
388 goto Done;
389 } else {
390 // Less than 24, additional info is argument or 31, an indefinite length
391 // No more bytes to get
392 uArgument = uAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700393 }
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800394
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395 if(UsefulInputBuf_GetError(pUInBuf)) {
396 nReturn = QCBOR_ERR_HIT_END;
397 goto Done;
398 }
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800399
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700400 // All successful if we got here.
401 nReturn = QCBOR_SUCCESS;
402 *pnMajorType = uTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800403 *puArgument = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700404 *puAdditionalInfo = uAdditionalInfo;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800405
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700406Done:
407 return nReturn;
408}
409
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700410/*
411 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
412 use it these days and the test vectors in the RFC are so. All integers in the CBOR
413 structure are positive and the major type indicates positive or negative.
414 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
415 and negative integers down to 2^x. Note that negative numbers can be one
416 more away from zero than positive.
417 Stdint, as far as I can tell, uses two's compliment to represent
418 negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800419
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700420 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
421 used here in any way including in the interface
422 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700423inline static QCBORError DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700424{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700425 // Stack usage: int/ptr 1 -- 8
Laurence Lundblade30816f22018-11-10 13:40:22 +0700426 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800427
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700428 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
429 if (uNumber <= INT64_MAX) {
430 pDecodedItem->val.int64 = (int64_t)uNumber;
431 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800432
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700433 } else {
434 pDecodedItem->val.uint64 = uNumber;
435 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800436
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700437 }
438 } else {
439 if(uNumber <= INT64_MAX) {
440 pDecodedItem->val.int64 = -uNumber-1;
441 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800442
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700443 } else {
444 // C can't represent a negative integer in this range
445 // so it is an error. todo -- test this condition
446 nReturn = QCBOR_ERR_INT_OVERFLOW;
447 }
448 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800449
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700450 return nReturn;
451}
452
453// Make sure #define value line up as DecodeSimple counts on this.
454#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
455#error QCBOR_TYPE_FALSE macro value wrong
456#endif
457
458#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
459#error QCBOR_TYPE_TRUE macro value wrong
460#endif
461
462#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
463#error QCBOR_TYPE_NULL macro value wrong
464#endif
465
466#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
467#error QCBOR_TYPE_UNDEF macro value wrong
468#endif
469
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700470#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
471#error QCBOR_TYPE_BREAK macro value wrong
472#endif
473
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700474#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
475#error QCBOR_TYPE_DOUBLE macro value wrong
476#endif
477
478#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
479#error QCBOR_TYPE_FLOAT macro value wrong
480#endif
481
482/*
483 Decode true, false, floats, break...
484 */
485
Laurence Lundblade30816f22018-11-10 13:40:22 +0700486inline static QCBORError DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700487{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700488 // Stack usage: 0
Laurence Lundblade30816f22018-11-10 13:40:22 +0700489 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800490
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700491 // uAdditionalInfo is 5 bits from the initial byte
492 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
493 pDecodedItem->uDataType = uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495 switch(uAdditionalInfo) {
496 case ADDINFO_RESERVED1: // 28
497 case ADDINFO_RESERVED2: // 29
498 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700499 nReturn = QCBOR_ERR_UNSUPPORTED;
500 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800501
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700502 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700503 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
504 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700505 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700506 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700507 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
508 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700509 break;
510 case DOUBLE_PREC_FLOAT:
511 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700512 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700513 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800514
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700515 case CBOR_SIMPLEV_FALSE: // 20
516 case CBOR_SIMPLEV_TRUE: // 21
517 case CBOR_SIMPLEV_NULL: // 22
518 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700519 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800521
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700522 case CBOR_SIMPLEV_ONEBYTE: // 24
523 if(uNumber <= CBOR_SIMPLE_BREAK) {
524 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
525 nReturn = QCBOR_ERR_INVALID_CBOR;
526 goto Done;
527 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800528 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700529 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531 default: // 0-19
532 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
533 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
534 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
535 pDecodedItem->val.uSimple = (uint8_t)uNumber;
536 break;
537 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800538
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700539Done:
540 return nReturn;
541}
542
543
544
545/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530546 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700548inline static QCBORError DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700549{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700550 // Stack usage: UsefulBuf 2, int/ptr 1 40
Laurence Lundblade30816f22018-11-10 13:40:22 +0700551 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800552
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800553 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530554 if(UsefulBuf_IsNULLC(Bytes)) {
555 // Failed to get the bytes for this string item
556 nReturn = QCBOR_ERR_HIT_END;
557 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700558 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530559
560 if(pAlloc) {
561 // We are asked to use string allocator to make a copy
562 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen);
563 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700564 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530565 goto Done;
566 }
567 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
568 } else {
569 // Normal case with no string allocator
570 pDecodedItem->val.string = Bytes;
571 }
572 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800573
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530574Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700575 return nReturn;
576}
577
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578
579/*
580 Mostly just assign the right data type for the date string.
581 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700582inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700583{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700584 // Stack Use: UsefulBuf 1 16
585 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586 return QCBOR_ERR_BAD_OPT_TAG;
587 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800588
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800589 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700590 pDecodedItem->val.dateString = Temp;
591 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592 return QCBOR_SUCCESS;
593}
594
595
596/*
597 Mostly just assign the right data type for the bignum.
598 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700599inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601 // Stack Use: UsefulBuf 1 -- 16
602 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 return QCBOR_ERR_BAD_OPT_TAG;
604 }
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800605 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700606 pDecodedItem->val.bigNum = Temp;
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700607 pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700608 return QCBOR_SUCCESS;
609}
610
611
612/*
613 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
614 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700615static int DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700617 // Stack usage: 1
Laurence Lundblade30816f22018-11-10 13:40:22 +0700618 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700622 switch (pDecodedItem->uDataType) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800623
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700624 case QCBOR_TYPE_INT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700625 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800627
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 case QCBOR_TYPE_UINT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700629 if(pDecodedItem->val.uint64 > INT64_MAX) {
630 nReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 goto Done;
632 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700633 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800635
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800636 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700637 {
638 const double d = pDecodedItem->val.dfnum;
639 if(d > INT64_MAX) {
640 nReturn = QCBOR_ERR_DATE_OVERFLOW;
641 goto Done;
642 }
643 pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
644 pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800645 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800646 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800647
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700648 default:
649 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700650 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700652 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654Done:
655 return nReturn;
656}
657
658
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700659
660
661// Make sure the constants align as this is assumed by the GetAnItem() implementation
662#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
663#error QCBOR_TYPE_ARRAY value not lined up with major type
664#endif
665#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
666#error QCBOR_TYPE_MAP value not lined up with major type
667#endif
668
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700670 This gets a single data item and decodes it including preceding optional tagging. This does not
671 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
672 maps are handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800673
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700674 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
675 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700677static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700678{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700679 // Stack usage: int/ptr 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700680 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700682 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
683 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
684 int uMajorType;
685 uint64_t uNumber;
686 uint8_t uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800687
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700688 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800689
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700690 // Error out here if we got into trouble on the type and number.
691 // The code after this will not work if the type and number is not good.
692 if(nReturn)
693 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800694
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530695 memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700697 // At this point the major type and the value are valid. We've got the type and the number that
698 // starts every CBOR data item.
699 switch (uMajorType) {
700 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
701 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
702 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
703 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700705 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
706 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
707 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
708 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530709 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700710 } else {
711 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
712 }
713 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700715 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
716 case CBOR_MAJOR_TYPE_MAP: // Major type 5
717 // Record the number of items in the array or map
718 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
719 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
720 goto Done;
721 }
722 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530723 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700724 } else {
725 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
726 }
727 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
728 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800729
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700730 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700731 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700732 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
733 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800734
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700735 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
736 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
737 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800738
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700739 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
740 nReturn = QCBOR_ERR_UNSUPPORTED;
741 break;
742 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800743
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700744Done:
745 return nReturn;
746}
747
748
749
750/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800751 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700752 individual chunk items together into one QCBORItem using the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530753 string allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530755 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700756 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700757static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700758{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700759 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700760 QCBORError nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530761 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530762 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800763
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
765 if(nReturn) {
766 goto Done;
767 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530770 // code in this function from here down can be eliminated. Run tests, except
771 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800772
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800773 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700774 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
775 goto Done; // no need to do any work here on non-string types
776 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800777
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800778 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530779 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800780 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800782
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530783 // Can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700784 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
786 goto Done;
787 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800790 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700791 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700793 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700795 // Get item for next chunk
796 QCBORItem StringChunkItem;
797 // NULL passed to never string alloc chunk of indefinite length strings
798 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700800 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530803 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700804 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800805 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700806 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530807 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700808 break;
809 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700811 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530812 // Also catches error of other non-string types that don't belong.
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700813 if(StringChunkItem.uDataType != uStringType) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700814 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700815 break;
816 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530818 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530819 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
820 UNCONST_POINTER(FullString.ptr),
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700821 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700822 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530823 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700824 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700825 break;
826 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800827
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700828 // Copy new string chunk at the end of string so far.
829 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700830 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700832Done:
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530833 if(pAlloc && nReturn && !UsefulBuf_IsNULLC(FullString)) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834 // Getting item failed, clean up the allocated memory
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530835 (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700836 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800837
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700838 return nReturn;
839}
840
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700841
842/*
843 Returns an error if there was something wrong with the optional item or it couldn't
844 be handled.
845 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700846static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700848 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700849 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700850 uint64_t uTagBits = 0;
851 if(pTags) {
852 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700854
855 for(;;) {
856 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700858 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700859 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800860
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700861 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
862 // Successful exit from loop; maybe got some tags, maybe not
863 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700864 break;
865 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800866
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700867 uint8_t uTagBitIndex;
868 // Tag was mapped, tag was not mapped, error with tag list
869 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700871 case QCBOR_SUCCESS:
872 // Successfully mapped the tag
873 uTagBits |= 0x01ULL << uTagBitIndex;
874 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700876 case QCBOR_ERR_BAD_OPT_TAG:
877 // Tag is not recognized. Do nothing
878 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800879
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700880 default:
881 // Error Condition
882 goto Done;
883 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800884
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700885 if(pTags) {
886 // Caller wants all tags recorded in the provided buffer
887 if(pTags->uNumUsed >= pTags->uNumAllocated) {
888 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
889 goto Done;
890 }
891 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
892 pTags->uNumUsed++;
893 }
894 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800895
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700896 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897 case 0:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700898 // No tags at all or none we know about. Nothing to do.
899 // This is part of the pass-through path of this function
900 // that will mostly be taken when decoding any item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700901 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800902
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700903 case QCBOR_TAGFLAG_DATE_STRING:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700904 nReturn = DecodeDateString(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700905 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907 case QCBOR_TAGFLAG_DATE_EPOCH:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700908 nReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700909 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800910
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700911 case QCBOR_TAGFLAG_POS_BIGNUM:
912 case QCBOR_TAGFLAG_NEG_BIGNUM:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700913 nReturn = DecodeBigNum(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700914 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916 default:
917 // Encountering some mixed up CBOR like something that
918 // is tagged as both a string and integer date.
Laurence Lundblade30816f22018-11-10 13:40:22 +0700919 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800921
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700922Done:
923 return nReturn;
924}
925
926
927/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800928 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700929 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700930static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700932 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700933 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 if(nReturn)
935 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800937 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700938 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800939 goto Done;
940 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800942 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
943 // In a map and caller wants maps decoded, not treated as arrays
944
945 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
946 // If in a map and the right decoding mode, get the label
947
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900948 // Get the next item which will be the real data; Item will be the label
949 QCBORItem LabelItem = *pDecodedItem;
950 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
951 if(nReturn)
952 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530954 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900955
956 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
957 // strings are always good labels
958 pDecodedItem->label.string = LabelItem.val.string;
959 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
960 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
961 // It's not a string and we only want strings, probably for easy translation to JSON
962 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
963 goto Done;
964 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
965 pDecodedItem->label.int64 = LabelItem.val.int64;
966 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
967 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
968 pDecodedItem->label.uint64 = LabelItem.val.uint64;
969 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
970 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
971 pDecodedItem->label.string = LabelItem.val.string;
972 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
973 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
974 } else {
975 // label is not an int or a string. It is an arrray
976 // or a float or such and this implementation doesn't handle that.
977 // Also, tags on labels are ignored.
978 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
979 goto Done;
980 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800981 }
982 } else {
983 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
984 // Decoding a map as an array
985 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
986 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700987 }
988 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800989
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990Done:
991 return nReturn;
992}
993
994
995/*
996 Public function, see header qcbor.h file
997 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700998QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001000 // Stack ptr/int: 2, QCBORItem : 64
1001
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301002 // The public entry point for fetching and parsing the next QCBORItem.
1003 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001004 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001005
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001006 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001007 if(nReturn) {
1008 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301010
1011 // Break ending arrays/maps are always processed at the end of this function.
1012 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301013 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301014 nReturn = QCBOR_ERR_BAD_BREAK;
1015 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301016 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade6de37062018-10-15 12:22:42 +05301018 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301019 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301020 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundblade6de37062018-10-15 12:22:42 +05301022 // Process the item just received for descent or decrement, and
1023 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001024 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001025 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001026 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001027 // Maps and arrays do count in as items in the map/array that encloses
1028 // them so a decrement needs to be done for them too, but that is done
1029 // only when all the items in them have been processed, not when they
1030 // are opened.
1031 } else {
1032 // Decrement the count of items in the enclosing map/array
1033 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301034 // triggers a decrement in the map/array above that and
1035 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001036 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001037 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301038 if(nReturn) {
1039 goto Done;
1040 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundblade6de37062018-10-15 12:22:42 +05301042 // For indefinite length maps/arrays, looking at any and
1043 // all breaks that might terminate them. The equivalent
1044 // for definite length maps/arrays happens in
1045 // DecodeNesting_DecrementCount().
1046 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1047 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1048 // Peek forward one item to see if it is a break.
1049 QCBORItem Peek;
1050 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1051 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1052 if(nReturn) {
1053 goto Done;
1054 }
1055 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1056 // It is not a break, rewind so it can be processed normally.
1057 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1058 break;
1059 }
1060 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301061 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301062 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1063 if(nReturn) {
1064 // break occured outside of an indefinite length array/map
1065 goto Done;
1066 }
1067 }
1068 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001069
Laurence Lundblade6de37062018-10-15 12:22:42 +05301070 // Tell the caller what level is next. This tells them what maps/arrays
1071 // were closed out and makes it possible for them to reconstruct
1072 // the tree with just the information returned by GetNext
1073 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001075Done:
1076 return nReturn;
1077}
1078
1079
Laurence Lundblade30816f22018-11-10 13:40:22 +07001080QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001081{
1082 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1083}
1084
1085
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001086/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301087 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301088 next one down. If a layer has no work to do for a particular item
1089 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301091 - QCBORDecode_GetNext -- The top layer manages the beginnings and
1092 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301093 out of maps/arrays. It processes all breaks that terminate
1094 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001095
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301096 - GetNext_MapEntry -- This handles the combining of two
1097 items, the label and the data, that make up a map entry.
1098 It only does work on maps. It combines the label and data
1099 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001100
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301101 - GetNext_TaggedItem -- This handles the type 6 tagged items.
1102 It accumulates all the tags and combines them with the following
1103 non-tagged item. If the tagged item is something that is understood
1104 like a date, the decoding of that item is invoked.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301106 - GetNext_FullItem -- This assembles the sub items that make up
1107 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301108 string allocater to create contiguous space for the item. It
1109 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001110
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301111 - GetNext_Item -- This gets and decodes the most atomic
1112 item in CBOR, the thing with an initial byte containing
1113 the major type.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001115 Roughly this takes 300 bytes of stack for vars. Need to
1116 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001117
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301118 */
1119
1120
1121/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001122 Public function, see header qcbor.h file
1123 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001124int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
1125{
1126 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001128 uint8_t uTagBitIndex;
1129 // Do not care about errors in pCallerConfiguredTagMap here. They are
1130 // caught during GetNext() before this is called.
1131 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1132 return 0;
1133 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001135 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1136 return (uTagBit & pItem->uTagBits) != 0;
1137}
1138
1139
1140/*
1141 Public function, see header qcbor.h file
1142 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001143QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001144{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001145 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001146
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001147 // Error out if all the maps/arrays are not closed out
1148 if(DecodeNesting_IsNested(&(me->nesting))) {
1149 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1150 goto Done;
1151 }
1152
1153 // Error out if not all the bytes are consumed
1154 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1155 nReturn = QCBOR_ERR_EXTRA_BYTES;
1156 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001158Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301159 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001160 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001161 if(me->pStringAllocator) {
1162 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1163 if(pAllocator->fDestructor) {
1164 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1165 }
1166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001168 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001169}
1170
1171
1172
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001173/*
1174
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001175Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001176
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001177 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001180
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001181 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001182
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001183 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001184
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001185 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001186
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001187 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001189 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001190
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001191 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001193 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001194
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001195 */
1196
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001197
1198
Laurence Lundbladef6531662018-12-04 10:42:22 +09001199
1200/*
1201 This is a very primitive memory allocator. It does not track individual
1202 allocations, only a high-water mark. A free or reallotcation must be of
1203 the last chunk allocated.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001204
Laurence Lundbladef6531662018-12-04 10:42:22 +09001205 All of this following code will get dead-stripped if QCBORDecode_SetMemPool()
1206 is not called.
1207 */
1208
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001209typedef struct {
1210 QCBORStringAllocator StringAllocator;
Laurence Lundbladef6531662018-12-04 10:42:22 +09001211 uint8_t *pStart; // First byte that can be allocated
1212 uint8_t *pEnd; // One past the last byte that can be allocated
1213 uint8_t *pFree; // Where the next free chunk is
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001214} MemPool;
1215
1216
1217/*
Laurence Lundbladef6531662018-12-04 10:42:22 +09001218 Internal function for an allocation
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001219
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001220 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1221 */
1222static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1223{
Laurence Lundbladef6531662018-12-04 10:42:22 +09001224 MemPool *me = (MemPool *)ctx;
1225 void *pReturn = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001226
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001227 if(pMem) {
1228 // Realloc case
Laurence Lundbladef6531662018-12-04 10:42:22 +09001229 // This check will work even if uNewSize is a super-large value like UINT64_MAX
1230 if((uNewSize <= (size_t)(me->pEnd - (uint8_t *)pMem)) && ((uint8_t *)pMem >= me->pStart)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001231 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundbladef6531662018-12-04 10:42:22 +09001232 pReturn = pMem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001233 }
1234 } else {
1235 // New chunk case
Laurence Lundbladef6531662018-12-04 10:42:22 +09001236 // This check will work even if uNewSize is a super large value like UINT64_MAX
1237 if(uNewSize <= (size_t)(me->pEnd - me->pFree)) {
1238 pReturn = me->pFree;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001239 me->pFree += uNewSize;
1240 }
1241 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001243 return (UsefulBuf){pReturn, uNewSize};
1244}
1245
Laurence Lundbladef6531662018-12-04 10:42:22 +09001246/*
1247 Internal function to free memory
1248 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001249static void MemPool_Free(void *ctx, void *pOldMem)
1250{
1251 MemPool *me = (MemPool *)ctx;
Laurence Lundbladef6531662018-12-04 10:42:22 +09001252 me->pFree = pOldMem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001253}
1254
Laurence Lundbladef6531662018-12-04 10:42:22 +09001255/*
1256 Public function, see header qcbor.h file
1257 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001258QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001259{
Laurence Lundbladedf2836b2018-12-19 18:13:29 -08001260 // The idea behind QCBOR_MIN_MEM_POOL_SIZE is
1261 // that the caller knows exactly what size to
1262 // allocate and that the tests can run conclusively
1263 // no matter what size MemPool is
1264 // even though it wastes some memory. MemPool
1265 // will vary depending on pointer size of the
1266 // the machine. QCBOR_MIN_MEM_POOL_SIZE is
1267 // set for pointers up to 64-bits. This
1268 // wastes about 50 bytes on a 32-bit machine.
1269 // This check makes sure things don't go
1270 // horribly wrong. It should optimize out
1271 // when there is no problem as the sizes are
1272 // known at compile time.
1273 if(sizeof(MemPool) > QCBOR_DECODE_MIN_MEM_POOL_SIZE) {
1274 return QCBOR_ERR_MEM_POOL_INTERNAL;
1275 }
Laurence Lundblade2c40ab82018-12-30 14:20:29 -08001276
Laurence Lundbladef6531662018-12-04 10:42:22 +09001277 // The first bytes of the Pool passed in are used
1278 // as the context (vtable of sorts) for the memory pool
1279 // allocator.
Laurence Lundbladedf2836b2018-12-19 18:13:29 -08001280 if(Pool.len < QCBOR_DECODE_MIN_MEM_POOL_SIZE) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001281 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001282 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001283 MemPool *pMP = (MemPool *)Pool.ptr;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001284
Laurence Lundbladef6531662018-12-04 10:42:22 +09001285 // Fill in the "vtable"
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001286 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1287 pMP->StringAllocator.fFree = MemPool_Free;
1288 pMP->StringAllocator.fDestructor = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001289
Laurence Lundbladef6531662018-12-04 10:42:22 +09001290 // Set up the pointers to the memory to be allocated
Laurence Lundbladedf2836b2018-12-19 18:13:29 -08001291 pMP->pStart = (uint8_t *)Pool.ptr + QCBOR_DECODE_MIN_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001292 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001293 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundbladef6531662018-12-04 10:42:22 +09001295 // More book keeping of context
1296 pMP->StringAllocator.pAllocaterContext = pMP;
1297 me->pStringAllocator = pMP;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001298
Laurence Lundbladef6531662018-12-04 10:42:22 +09001299 // The flag indicating when to use the allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001300 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001301
Laurence Lundblade30816f22018-11-10 13:40:22 +07001302 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303}
1304
Laurence Lundbladef6531662018-12-04 10:42:22 +09001305
1306/*
1307 Extra little hook to make MemPool testing work right
1308 without adding any code size or overhead to non-test
1309 uses. This will get dead-stripped for non-test use.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001310
1311 This is not a public function.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001312 */
1313size_t MemPoolTestHook_GetPoolSize(void *ctx)
1314{
1315 MemPool *me = (MemPool *)ctx;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001316
Laurence Lundbladef6531662018-12-04 10:42:22 +09001317 return me->pEnd - me->pStart;
1318}
1319