blob: 8d216c74a456007993655927d570b7ef596ce2dc [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 Lundblade8b06e2e2018-12-04 12:26:51 +090045 11/9/18 llundblade Error codes are now enums.
46 11/2/18 llundblade Simplify float decoding and align with preferred
47 float encoding
48 10/31/18 llundblade Switch to one license that is almost BSD-3.
49 10/28/18 llundblade Reworked tag decoding
50 10/15/18 llundblade Indefinite length maps and arrays supported
51 10/8/18 llundblade Indefinite length strings supported
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052 02/04/17 llundbla Work on CPUs that don's require pointer alignment
53 by making use of changes in UsefulBuf
54 03/01/17 llundbla More data types; decoding improvements and fixes
55 11/13/16 llundbla Integrate most TZ changes back into github version.
56 09/30/16 gkanike Porting to TZ.
57 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080058
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070059 =====================================================================================*/
60
61#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070062#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070063
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070064
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053065/*
66 This casts away the const-ness of a pointer, usually so it can be
67 freed or realloced.
68 */
69#define UNCONST_POINTER(ptr) ((void *)(ptr))
70
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070071
72/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080073 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074 */
75
76inline static int IsMapOrArray(uint8_t uDataType)
77{
78 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
79}
80
81inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
82{
83 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
84}
85
Laurence Lundblade041ffa52018-10-07 11:43:51 +070086inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070087{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070088 return pNesting->pCurrent->uCount == UINT16_MAX;
89}
90
Laurence Lundblade3a760b02018-10-08 13:46:03 +080091inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
92{
93 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
94}
95
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070096inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
97{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070098 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700100 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800101
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
103}
104
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800105// Process a break. This will either ascend the nesting or error out
Laurence Lundblade30816f22018-11-10 13:40:22 +0700106inline static QCBORError DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700107{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800108 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700109 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800110 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700111 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800112
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800113 // breaks can only occur when the map/array is indefinite length
114 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
115 return QCBOR_ERR_BAD_BREAK;
116 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800117
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800118 // if all OK, the break reduces the level of nesting
119 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800120
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800121 return QCBOR_SUCCESS;
122}
123
124// Called on every single item except breaks including the opening of a map/array
125inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
126{
127 if(!DecodeNesting_IsNested(pNesting)) {
128 // at top level where there is no tracking
129 return;
130 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800131
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800132 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
133 // There is no count for indefinite length arrays/maps
134 return;
135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800137 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700138 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700139
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800140 // Pop up nesting levels if the counts at the levels are zero
141 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700142 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800143 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
144 pNesting->pCurrent->uCount--;
145 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146 }
147}
148
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800149// Called on every map/array
Laurence Lundblade30816f22018-11-10 13:40:22 +0700150inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700151{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700152 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800153
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800154 if(pItem->val.uCount == 0) {
155 // Nothing to do for empty definite lenth arrays. They are just are
156 // effectively the same as an item that is not a map or array
157 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530158 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800159 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800160
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800161 // Error out if arrays is too long to handle
162 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700163 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
164 goto Done;
165 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800166
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800167 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
169 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
170 goto Done;
171 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800172
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800173 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800175
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800176 // Record a few details for this nesting level
177 pNesting->pCurrent->uMajorType = pItem->uDataType;
178 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800179
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700180Done:
181 return nReturn;;
182}
183
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
185{
186 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
187}
188
189
190
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700191/*
192 This list of built-in tags. Only add tags here that are
193 clearly established and useful. Once a tag is added here
194 it can't be taken out as that would break backwards compatibility.
195 There are only 48 slots available forever.
196 */
197static const uint16_t spBuiltInTagMap[] = {
198 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR
199 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
200 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
201 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
202 CBOR_TAG_FRACTION,
203 CBOR_TAG_BIGFLOAT,
204 CBOR_TAG_COSE_ENCRYPTO,
205 CBOR_TAG_COSE_MAC0,
206 CBOR_TAG_COSE_SIGN1,
207 CBOR_TAG_ENC_AS_B64URL,
208 CBOR_TAG_ENC_AS_B64,
209 CBOR_TAG_ENC_AS_B16,
210 CBOR_TAG_CBOR,
211 CBOR_TAG_URI,
212 CBOR_TAG_B64URL,
213 CBOR_TAG_B64,
214 CBOR_TAG_REGEX,
215 CBOR_TAG_MIME,
216 CBOR_TAG_BIN_UUID,
217 CBOR_TAG_CWT,
218 CBOR_TAG_ENCRYPT,
219 CBOR_TAG_MAC,
220 CBOR_TAG_SIGN,
221 CBOR_TAG_GEO_COORD,
222 CBOR_TAG_CBOR_MAGIC
223};
224
225// This is used in a bit of cleverness in GetNext_TaggedItem() to
226// keep code size down and switch for the internal processing of
227// these types. This will break if the first four items in
228// spBuiltInTagMap don't have values 0,1,2,3. That is the
229// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3.
230#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
231#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
232#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
233#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
234
235#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
236 QCBOR_TAGFLAG_DATE_EPOCH |\
237 QCBOR_TAGFLAG_POS_BIGNUM |\
238 QCBOR_TAGFLAG_NEG_BIGNUM)
239
240#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
241#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
242#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
243
244static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
245{
246 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
247 // This is a cross-check to make sure the above array doesn't
248 // accidentally get made too big.
249 // In normal conditions the above test should optimize out
250 // as all the values are known at compile time.
251 return -1;
252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800253
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700254 if(uTag > UINT16_MAX) {
255 // This tag map works only on 16-bit tags
256 return -1;
257 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800258
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700259 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
260 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
261 return nTagBitIndex;
262 }
263 }
264 return -1; // Indicates no match
265}
266
267static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
268{
269 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
270 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
271 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
272 }
273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800274
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700275 return -1; // Indicates no match
276}
277
278/*
279 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800280
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700281 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800282 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700283 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700284static QCBORError TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700285{
286 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
287 if(nTagBitIndex >= 0) {
288 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
289 *puTagBitIndex = (uint8_t)nTagBitIndex;
290 return QCBOR_SUCCESS;
291 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800292
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700293 if(pCallerConfiguredTagMap) {
294 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
295 return QCBOR_ERR_TOO_MANY_TAGS;
296 }
297 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
298 if(nTagBitIndex >= 0) {
299 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
300
301 *puTagBitIndex = (uint8_t)nTagBitIndex;
302 return QCBOR_SUCCESS;
303 }
304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700306 return QCBOR_ERR_BAD_OPT_TAG;
307}
308
309
310
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700311
312/*
313 Public function, see header file
314 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800315void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700316{
317 memset(me, 0, sizeof(QCBORDecodeContext));
318 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
319 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
320 // if the default normal mode of 0 was set.
321 me->uDecodeMode = nDecodeMode;
322 DecodeNesting_Init(&(me->nesting));
323}
324
325
326/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700327 Public function, see header file
328 */
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530329void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700330{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700331 pCtx->pStringAllocator = (void *)pAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530332 pCtx->bStringAllocateAll = bAllocAll;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700333}
334
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700335void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
336{
337 me->pCallerConfiguredTagList = pTagList;
338}
339
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700340
341/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700342 This decodes the fundamental part of a CBOR data item, the type and number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800343
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700344 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800345
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700346 This does the network->host byte order conversion. The conversion here
347 also results in the conversion for floats in addition to that for
348 lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800349
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700350 This returns:
351 pnMajorType -- the major type for the item
352 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
353 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800354
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700355 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700356inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700357{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700358 // Stack usage: int/ptr 5 -- 40
Laurence Lundblade30816f22018-11-10 13:40:22 +0700359 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800360
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700361 // Get the initial byte that every CBOR data item has
362 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800363
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700364 // Break down the initial byte
365 const uint8_t uTmpMajorType = InitialByte >> 5;
366 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800367
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700368 // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700369 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700370 uint64_t uTmpValue;
371 switch(uAdditionalInfo) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800372
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700373 case LEN_IS_ONE_BYTE:
374 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
375 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800376
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700377 case LEN_IS_TWO_BYTES:
378 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
379 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800380
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700381 case LEN_IS_FOUR_BYTES:
382 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
383 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800384
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700385 case LEN_IS_EIGHT_BYTES:
386 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
387 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800388
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700389 case ADDINFO_RESERVED1: // reserved by CBOR spec
390 case ADDINFO_RESERVED2: // reserved by CBOR spec
391 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700392 nReturn = QCBOR_ERR_UNSUPPORTED;
393 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700394
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700396 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700397 uTmpValue = uAdditionalInfo;
398 break;
399 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800400
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700401 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
402 // There is no harm in this. This following check takes care of catching all of
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800403 // these errors.
404
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700405 if(UsefulInputBuf_GetError(pUInBuf)) {
406 nReturn = QCBOR_ERR_HIT_END;
407 goto Done;
408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800409
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700410 // All successful if we got here.
411 nReturn = QCBOR_SUCCESS;
412 *pnMajorType = uTmpMajorType;
413 *puNumber = uTmpValue;
414 *puAdditionalInfo = uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800415
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700416Done:
417 return nReturn;
418}
419
420
421/*
422 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
423 use it these days and the test vectors in the RFC are so. All integers in the CBOR
424 structure are positive and the major type indicates positive or negative.
425 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
426 and negative integers down to 2^x. Note that negative numbers can be one
427 more away from zero than positive.
428 Stdint, as far as I can tell, uses two's compliment to represent
429 negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800430
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700431 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
432 used here in any way including in the interface
433 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700434inline static QCBORError DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700435{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700436 // Stack usage: int/ptr 1 -- 8
Laurence Lundblade30816f22018-11-10 13:40:22 +0700437 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800438
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700439 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
440 if (uNumber <= INT64_MAX) {
441 pDecodedItem->val.int64 = (int64_t)uNumber;
442 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800443
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700444 } else {
445 pDecodedItem->val.uint64 = uNumber;
446 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800447
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700448 }
449 } else {
450 if(uNumber <= INT64_MAX) {
451 pDecodedItem->val.int64 = -uNumber-1;
452 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800453
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700454 } else {
455 // C can't represent a negative integer in this range
456 // so it is an error. todo -- test this condition
457 nReturn = QCBOR_ERR_INT_OVERFLOW;
458 }
459 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800460
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700461 return nReturn;
462}
463
464// Make sure #define value line up as DecodeSimple counts on this.
465#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
466#error QCBOR_TYPE_FALSE macro value wrong
467#endif
468
469#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
470#error QCBOR_TYPE_TRUE macro value wrong
471#endif
472
473#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
474#error QCBOR_TYPE_NULL macro value wrong
475#endif
476
477#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
478#error QCBOR_TYPE_UNDEF macro value wrong
479#endif
480
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700481#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
482#error QCBOR_TYPE_BREAK macro value wrong
483#endif
484
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700485#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
486#error QCBOR_TYPE_DOUBLE macro value wrong
487#endif
488
489#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
490#error QCBOR_TYPE_FLOAT macro value wrong
491#endif
492
493/*
494 Decode true, false, floats, break...
495 */
496
Laurence Lundblade30816f22018-11-10 13:40:22 +0700497inline static QCBORError DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700498{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700499 // Stack usage: 0
Laurence Lundblade30816f22018-11-10 13:40:22 +0700500 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800501
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700502 // uAdditionalInfo is 5 bits from the initial byte
503 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
504 pDecodedItem->uDataType = uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800505
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700506 switch(uAdditionalInfo) {
507 case ADDINFO_RESERVED1: // 28
508 case ADDINFO_RESERVED2: // 29
509 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700510 nReturn = QCBOR_ERR_UNSUPPORTED;
511 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800512
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700513 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700514 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
515 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700516 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700517 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700518 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
519 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700520 break;
521 case DOUBLE_PREC_FLOAT:
522 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700523 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700524 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800525
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700526 case CBOR_SIMPLEV_FALSE: // 20
527 case CBOR_SIMPLEV_TRUE: // 21
528 case CBOR_SIMPLEV_NULL: // 22
529 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700530 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800532
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700533 case CBOR_SIMPLEV_ONEBYTE: // 24
534 if(uNumber <= CBOR_SIMPLE_BREAK) {
535 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
536 nReturn = QCBOR_ERR_INVALID_CBOR;
537 goto Done;
538 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800539 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800541
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542 default: // 0-19
543 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
544 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
545 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
546 pDecodedItem->val.uSimple = (uint8_t)uNumber;
547 break;
548 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800549
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700550Done:
551 return nReturn;
552}
553
554
555
556/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530557 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700558 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700559inline static QCBORError DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700560{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700561 // Stack usage: UsefulBuf 2, int/ptr 1 40
Laurence Lundblade30816f22018-11-10 13:40:22 +0700562 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800563
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800564 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530565 if(UsefulBuf_IsNULLC(Bytes)) {
566 // Failed to get the bytes for this string item
567 nReturn = QCBOR_ERR_HIT_END;
568 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700569 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530570
571 if(pAlloc) {
572 // We are asked to use string allocator to make a copy
573 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen);
574 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700575 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530576 goto Done;
577 }
578 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
579 } else {
580 // Normal case with no string allocator
581 pDecodedItem->val.string = Bytes;
582 }
583 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800584
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530585Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700586 return nReturn;
587}
588
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700589
590/*
591 Mostly just assign the right data type for the date string.
592 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700593inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700594{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700595 // Stack Use: UsefulBuf 1 16
596 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597 return QCBOR_ERR_BAD_OPT_TAG;
598 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800599
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800600 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601 pDecodedItem->val.dateString = Temp;
602 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 return QCBOR_SUCCESS;
604}
605
606
607/*
608 Mostly just assign the right data type for the bignum.
609 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700610inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700611{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700612 // Stack Use: UsefulBuf 1 -- 16
613 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700614 return QCBOR_ERR_BAD_OPT_TAG;
615 }
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800616 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700617 pDecodedItem->val.bigNum = Temp;
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700618 pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619 return QCBOR_SUCCESS;
620}
621
622
623/*
624 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
625 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700626static int DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700628 // Stack usage: 1
Laurence Lundblade30816f22018-11-10 13:40:22 +0700629 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700633 switch (pDecodedItem->uDataType) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 case QCBOR_TYPE_INT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700636 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 case QCBOR_TYPE_UINT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700640 if(pDecodedItem->val.uint64 > INT64_MAX) {
641 nReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 goto Done;
643 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700644 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800646
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800647 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700648 {
649 const double d = pDecodedItem->val.dfnum;
650 if(d > INT64_MAX) {
651 nReturn = QCBOR_ERR_DATE_OVERFLOW;
652 goto Done;
653 }
654 pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
655 pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800656 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800657 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800658
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700659 default:
660 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700661 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700663 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800664
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665Done:
666 return nReturn;
667}
668
669
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700670
671
672// Make sure the constants align as this is assumed by the GetAnItem() implementation
673#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
674#error QCBOR_TYPE_ARRAY value not lined up with major type
675#endif
676#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
677#error QCBOR_TYPE_MAP value not lined up with major type
678#endif
679
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700681 This gets a single data item and decodes it including preceding optional tagging. This does not
682 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
683 maps are handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800684
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700685 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
686 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700687 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700688static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700689{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700690 // Stack usage: int/ptr 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700691 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800692
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700693 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
694 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
695 int uMajorType;
696 uint64_t uNumber;
697 uint8_t uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800698
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700699 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700701 // Error out here if we got into trouble on the type and number.
702 // The code after this will not work if the type and number is not good.
703 if(nReturn)
704 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800705
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530706 memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700708 // At this point the major type and the value are valid. We've got the type and the number that
709 // starts every CBOR data item.
710 switch (uMajorType) {
711 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
712 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
713 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
714 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800715
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700716 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
717 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
718 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
719 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530720 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700721 } else {
722 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
723 }
724 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800725
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700726 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
727 case CBOR_MAJOR_TYPE_MAP: // Major type 5
728 // Record the number of items in the array or map
729 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
730 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
731 goto Done;
732 }
733 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530734 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700735 } else {
736 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
737 }
738 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
739 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800740
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700741 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700742 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700743 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
744 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800745
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700746 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
747 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
748 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800749
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700750 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
751 nReturn = QCBOR_ERR_UNSUPPORTED;
752 break;
753 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755Done:
756 return nReturn;
757}
758
759
760
761/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800762 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700763 individual chunk items together into one QCBORItem using the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530764 string allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800765
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530766 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700767 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700768static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700770 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700771 QCBORError nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530772 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530773 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800774
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700775 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
776 if(nReturn) {
777 goto Done;
778 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800779
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700780 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530781 // code in this function from here down can be eliminated. Run tests, except
782 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800783
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800784 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
786 goto Done; // no need to do any work here on non-string types
787 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800789 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530790 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800791 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530794 // Can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700795 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700796 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
797 goto Done;
798 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700800 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800801 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700802 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800803
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700804 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700805 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700806 // Get item for next chunk
807 QCBORItem StringChunkItem;
808 // NULL passed to never string alloc chunk of indefinite length strings
809 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700810 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700811 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700812 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800813
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530814 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700815 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800816 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700817 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530818 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700819 break;
820 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700822 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530823 // Also catches error of other non-string types that don't belong.
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700824 if(StringChunkItem.uDataType != uStringType) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700825 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700826 break;
827 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800828
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530829 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530830 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
831 UNCONST_POINTER(FullString.ptr),
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700832 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530834 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700835 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700836 break;
837 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700839 // Copy new string chunk at the end of string so far.
840 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700841 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800842
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843Done:
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530844 if(pAlloc && nReturn && !UsefulBuf_IsNULLC(FullString)) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 // Getting item failed, clean up the allocated memory
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530846 (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700847 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800848
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700849 return nReturn;
850}
851
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700852
853/*
854 Returns an error if there was something wrong with the optional item or it couldn't
855 be handled.
856 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700857static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700859 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700860 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700861 uint64_t uTagBits = 0;
862 if(pTags) {
863 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700865
866 for(;;) {
867 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700868 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700869 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700872 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
873 // Successful exit from loop; maybe got some tags, maybe not
874 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700875 break;
876 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800877
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700878 uint8_t uTagBitIndex;
879 // Tag was mapped, tag was not mapped, error with tag list
880 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700882 case QCBOR_SUCCESS:
883 // Successfully mapped the tag
884 uTagBits |= 0x01ULL << uTagBitIndex;
885 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700887 case QCBOR_ERR_BAD_OPT_TAG:
888 // Tag is not recognized. Do nothing
889 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800890
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700891 default:
892 // Error Condition
893 goto Done;
894 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800895
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700896 if(pTags) {
897 // Caller wants all tags recorded in the provided buffer
898 if(pTags->uNumUsed >= pTags->uNumAllocated) {
899 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
900 goto Done;
901 }
902 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
903 pTags->uNumUsed++;
904 }
905 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700907 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700908 case 0:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700909 // No tags at all or none we know about. Nothing to do.
910 // This is part of the pass-through path of this function
911 // that will mostly be taken when decoding any item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700912 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700914 case QCBOR_TAGFLAG_DATE_STRING:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700915 nReturn = DecodeDateString(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800917
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 case QCBOR_TAGFLAG_DATE_EPOCH:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700919 nReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800921
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700922 case QCBOR_TAGFLAG_POS_BIGNUM:
923 case QCBOR_TAGFLAG_NEG_BIGNUM:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700924 nReturn = DecodeBigNum(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927 default:
928 // Encountering some mixed up CBOR like something that
929 // is tagged as both a string and integer date.
Laurence Lundblade30816f22018-11-10 13:40:22 +0700930 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700933Done:
934 return nReturn;
935}
936
937
938/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800939 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700940 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700941static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700942{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700943 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700944 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700945 if(nReturn)
946 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800948 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700949 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800950 goto Done;
951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800953 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
954 // In a map and caller wants maps decoded, not treated as arrays
955
956 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
957 // If in a map and the right decoding mode, get the label
958
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900959 // Get the next item which will be the real data; Item will be the label
960 QCBORItem LabelItem = *pDecodedItem;
961 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
962 if(nReturn)
963 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530965 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900966
967 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
968 // strings are always good labels
969 pDecodedItem->label.string = LabelItem.val.string;
970 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
971 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
972 // It's not a string and we only want strings, probably for easy translation to JSON
973 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
974 goto Done;
975 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
976 pDecodedItem->label.int64 = LabelItem.val.int64;
977 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
978 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
979 pDecodedItem->label.uint64 = LabelItem.val.uint64;
980 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
981 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
982 pDecodedItem->label.string = LabelItem.val.string;
983 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
984 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
985 } else {
986 // label is not an int or a string. It is an arrray
987 // or a float or such and this implementation doesn't handle that.
988 // Also, tags on labels are ignored.
989 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
990 goto Done;
991 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800992 }
993 } else {
994 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
995 // Decoding a map as an array
996 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
997 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700998 }
999 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001Done:
1002 return nReturn;
1003}
1004
1005
1006/*
1007 Public function, see header qcbor.h file
1008 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001009QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001010{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001011 // Stack ptr/int: 2, QCBORItem : 64
1012
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301013 // The public entry point for fetching and parsing the next QCBORItem.
1014 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001015 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001016
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001017 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001018 if(nReturn) {
1019 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301021
1022 // Break ending arrays/maps are always processed at the end of this function.
1023 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301024 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301025 nReturn = QCBOR_ERR_BAD_BREAK;
1026 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301027 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001028
Laurence Lundblade6de37062018-10-15 12:22:42 +05301029 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301030 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301031 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade6de37062018-10-15 12:22:42 +05301033 // Process the item just received for descent or decrement, and
1034 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001035 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001036 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001037 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001038 // Maps and arrays do count in as items in the map/array that encloses
1039 // them so a decrement needs to be done for them too, but that is done
1040 // only when all the items in them have been processed, not when they
1041 // are opened.
1042 } else {
1043 // Decrement the count of items in the enclosing map/array
1044 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301045 // triggers a decrement in the map/array above that and
1046 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001047 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001048 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301049 if(nReturn) {
1050 goto Done;
1051 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001052
Laurence Lundblade6de37062018-10-15 12:22:42 +05301053 // For indefinite length maps/arrays, looking at any and
1054 // all breaks that might terminate them. The equivalent
1055 // for definite length maps/arrays happens in
1056 // DecodeNesting_DecrementCount().
1057 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1058 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1059 // Peek forward one item to see if it is a break.
1060 QCBORItem Peek;
1061 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1062 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1063 if(nReturn) {
1064 goto Done;
1065 }
1066 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1067 // It is not a break, rewind so it can be processed normally.
1068 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1069 break;
1070 }
1071 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301072 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301073 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1074 if(nReturn) {
1075 // break occured outside of an indefinite length array/map
1076 goto Done;
1077 }
1078 }
1079 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001080
Laurence Lundblade6de37062018-10-15 12:22:42 +05301081 // Tell the caller what level is next. This tells them what maps/arrays
1082 // were closed out and makes it possible for them to reconstruct
1083 // the tree with just the information returned by GetNext
1084 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001086Done:
1087 return nReturn;
1088}
1089
1090
Laurence Lundblade30816f22018-11-10 13:40:22 +07001091QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001092{
1093 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1094}
1095
1096
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001097/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301098 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301099 next one down. If a layer has no work to do for a particular item
1100 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001101
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301102 - QCBORDecode_GetNext -- The top layer manages the beginnings and
1103 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301104 out of maps/arrays. It processes all breaks that terminate
1105 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001106
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301107 - GetNext_MapEntry -- This handles the combining of two
1108 items, the label and the data, that make up a map entry.
1109 It only does work on maps. It combines the label and data
1110 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001111
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301112 - GetNext_TaggedItem -- This handles the type 6 tagged items.
1113 It accumulates all the tags and combines them with the following
1114 non-tagged item. If the tagged item is something that is understood
1115 like a date, the decoding of that item is invoked.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001116
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301117 - GetNext_FullItem -- This assembles the sub items that make up
1118 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301119 string allocater to create contiguous space for the item. It
1120 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301122 - GetNext_Item -- This gets and decodes the most atomic
1123 item in CBOR, the thing with an initial byte containing
1124 the major type.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001125
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001126 Roughly this takes 300 bytes of stack for vars. Need to
1127 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301129 */
1130
1131
1132/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001133 Public function, see header qcbor.h file
1134 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001135int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
1136{
1137 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001138
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001139 uint8_t uTagBitIndex;
1140 // Do not care about errors in pCallerConfiguredTagMap here. They are
1141 // caught during GetNext() before this is called.
1142 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1143 return 0;
1144 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001145
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001146 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1147 return (uTagBit & pItem->uTagBits) != 0;
1148}
1149
1150
1151/*
1152 Public function, see header qcbor.h file
1153 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001154QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001155{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001156 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001158 // Error out if all the maps/arrays are not closed out
1159 if(DecodeNesting_IsNested(&(me->nesting))) {
1160 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1161 goto Done;
1162 }
1163
1164 // Error out if not all the bytes are consumed
1165 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1166 nReturn = QCBOR_ERR_EXTRA_BYTES;
1167 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001168
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001169Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301170 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001171 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001172 if(me->pStringAllocator) {
1173 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1174 if(pAllocator->fDestructor) {
1175 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1176 }
1177 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001179 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001180}
1181
1182
1183
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001184/*
1185
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001186Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001187
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001188 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001189
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001190 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001192 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001194 - 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 -08001195
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001196 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001197
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001198 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001199
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001200 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001201
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001202 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001204 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001205
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001206 */
1207
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001208
1209
Laurence Lundbladef6531662018-12-04 10:42:22 +09001210
1211/*
1212 This is a very primitive memory allocator. It does not track individual
1213 allocations, only a high-water mark. A free or reallotcation must be of
1214 the last chunk allocated.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001215
Laurence Lundbladef6531662018-12-04 10:42:22 +09001216 All of this following code will get dead-stripped if QCBORDecode_SetMemPool()
1217 is not called.
1218 */
1219
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001220typedef struct {
1221 QCBORStringAllocator StringAllocator;
Laurence Lundbladef6531662018-12-04 10:42:22 +09001222 uint8_t *pStart; // First byte that can be allocated
1223 uint8_t *pEnd; // One past the last byte that can be allocated
1224 uint8_t *pFree; // Where the next free chunk is
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001225} MemPool;
1226
1227
1228/*
Laurence Lundbladef6531662018-12-04 10:42:22 +09001229 Internal function for an allocation
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001230
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001231 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1232 */
1233static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1234{
Laurence Lundbladef6531662018-12-04 10:42:22 +09001235 MemPool *me = (MemPool *)ctx;
1236 void *pReturn = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001237
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001238 if(pMem) {
1239 // Realloc case
Laurence Lundbladef6531662018-12-04 10:42:22 +09001240 // This check will work even if uNewSize is a super-large value like UINT64_MAX
1241 if((uNewSize <= (size_t)(me->pEnd - (uint8_t *)pMem)) && ((uint8_t *)pMem >= me->pStart)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001242 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundbladef6531662018-12-04 10:42:22 +09001243 pReturn = pMem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001244 }
1245 } else {
1246 // New chunk case
Laurence Lundbladef6531662018-12-04 10:42:22 +09001247 // This check will work even if uNewSize is a super large value like UINT64_MAX
1248 if(uNewSize <= (size_t)(me->pEnd - me->pFree)) {
1249 pReturn = me->pFree;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001250 me->pFree += uNewSize;
1251 }
1252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001253
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001254 return (UsefulBuf){pReturn, uNewSize};
1255}
1256
Laurence Lundbladef6531662018-12-04 10:42:22 +09001257/*
1258 Internal function to free memory
1259 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001260static void MemPool_Free(void *ctx, void *pOldMem)
1261{
1262 MemPool *me = (MemPool *)ctx;
Laurence Lundbladef6531662018-12-04 10:42:22 +09001263 me->pFree = pOldMem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001264}
1265
Laurence Lundbladef6531662018-12-04 10:42:22 +09001266/*
1267 Public function, see header qcbor.h file
1268 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001269QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001270{
Laurence Lundbladedf2836b2018-12-19 18:13:29 -08001271 // The idea behind QCBOR_MIN_MEM_POOL_SIZE is
1272 // that the caller knows exactly what size to
1273 // allocate and that the tests can run conclusively
1274 // no matter what size MemPool is
1275 // even though it wastes some memory. MemPool
1276 // will vary depending on pointer size of the
1277 // the machine. QCBOR_MIN_MEM_POOL_SIZE is
1278 // set for pointers up to 64-bits. This
1279 // wastes about 50 bytes on a 32-bit machine.
1280 // This check makes sure things don't go
1281 // horribly wrong. It should optimize out
1282 // when there is no problem as the sizes are
1283 // known at compile time.
1284 if(sizeof(MemPool) > QCBOR_DECODE_MIN_MEM_POOL_SIZE) {
1285 return QCBOR_ERR_MEM_POOL_INTERNAL;
1286 }
Laurence Lundblade2c40ab82018-12-30 14:20:29 -08001287
Laurence Lundbladef6531662018-12-04 10:42:22 +09001288 // The first bytes of the Pool passed in are used
1289 // as the context (vtable of sorts) for the memory pool
1290 // allocator.
Laurence Lundbladedf2836b2018-12-19 18:13:29 -08001291 if(Pool.len < QCBOR_DECODE_MIN_MEM_POOL_SIZE) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001292 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001293 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001294 MemPool *pMP = (MemPool *)Pool.ptr;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001295
Laurence Lundbladef6531662018-12-04 10:42:22 +09001296 // Fill in the "vtable"
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001297 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1298 pMP->StringAllocator.fFree = MemPool_Free;
1299 pMP->StringAllocator.fDestructor = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001300
Laurence Lundbladef6531662018-12-04 10:42:22 +09001301 // Set up the pointers to the memory to be allocated
Laurence Lundbladedf2836b2018-12-19 18:13:29 -08001302 pMP->pStart = (uint8_t *)Pool.ptr + QCBOR_DECODE_MIN_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001304 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundbladef6531662018-12-04 10:42:22 +09001306 // More book keeping of context
1307 pMP->StringAllocator.pAllocaterContext = pMP;
1308 me->pStringAllocator = pMP;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001309
Laurence Lundbladef6531662018-12-04 10:42:22 +09001310 // The flag indicating when to use the allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001311 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001312
Laurence Lundblade30816f22018-11-10 13:40:22 +07001313 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001314}
1315
Laurence Lundbladef6531662018-12-04 10:42:22 +09001316
1317/*
1318 Extra little hook to make MemPool testing work right
1319 without adding any code size or overhead to non-test
1320 uses. This will get dead-stripped for non-test use.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001321
1322 This is not a public function.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001323 */
1324size_t MemPoolTestHook_GetPoolSize(void *ctx)
1325{
1326 MemPool *me = (MemPool *)ctx;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundbladef6531662018-12-04 10:42:22 +09001328 return me->pEnd - me->pStart;
1329}
1330