blob: 4d8027c264c0fe89bd97bf94eceef2e2583a6015 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladef0ea5f32019-01-11 20:10:26 -08003 Copyright (c) 2018-2019, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence 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 Lundblade9916b1b2019-09-07 22:33:25 -070045 09/07/19 llundblade Fix bug decoding empty arrays and maps
Laurence Lundbladebb1062e2019-08-12 23:28:54 -070046 07/31/19 llundblade Decode error fixes for some not-well-formed CBOR
47 07/31/19 llundblade New error code for better end of data handling
Laurence Lundblade1d7eb632019-02-17 17:23:38 -080048 02/17/19 llundblade Fixed: QCBORItem.u{Data|Label}Alloc when bAllStrings set
49 02/16/19 llundblade Redesign MemPool to fix memory access alignment bug
Laurence Lundblade4c0cf842019-01-12 03:25:44 -080050 01/10/19 llundblade Clever type and argument decoder is 250 bytes smaller
Laurence Lundblade8b06e2e2018-12-04 12:26:51 +090051 11/9/18 llundblade Error codes are now enums.
52 11/2/18 llundblade Simplify float decoding and align with preferred
53 float encoding
54 10/31/18 llundblade Switch to one license that is almost BSD-3.
55 10/28/18 llundblade Reworked tag decoding
56 10/15/18 llundblade Indefinite length maps and arrays supported
57 10/8/18 llundblade Indefinite length strings supported
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070058 02/04/17 llundbla Work on CPUs that don's require pointer alignment
59 by making use of changes in UsefulBuf
60 03/01/17 llundbla More data types; decoding improvements and fixes
61 11/13/16 llundbla Integrate most TZ changes back into github version.
62 09/30/16 gkanike Porting to TZ.
63 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080064
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070065 =====================================================================================*/
66
67#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070068#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070069
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070070
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053071/*
72 This casts away the const-ness of a pointer, usually so it can be
73 freed or realloced.
74 */
75#define UNCONST_POINTER(ptr) ((void *)(ptr))
76
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077
78/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080079 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070080 */
81
82inline static int IsMapOrArray(uint8_t uDataType)
83{
84 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
85}
86
87inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
88{
89 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
90}
91
Laurence Lundblade041ffa52018-10-07 11:43:51 +070092inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070093{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070094 return pNesting->pCurrent->uCount == UINT16_MAX;
95}
96
Laurence Lundblade3a760b02018-10-08 13:46:03 +080097inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
98{
99 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
100}
101
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
103{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700104 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700105 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700106 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800107
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
109}
110
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800111// Process a break. This will either ascend the nesting or error out
Laurence Lundblade30816f22018-11-10 13:40:22 +0700112inline static QCBORError DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700113{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800114 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800116 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700117 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800119 // breaks can only occur when the map/array is indefinite length
120 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
121 return QCBOR_ERR_BAD_BREAK;
122 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800123
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800124 // if all OK, the break reduces the level of nesting
125 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800126
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800127 return QCBOR_SUCCESS;
128}
129
130// Called on every single item except breaks including the opening of a map/array
131inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
132{
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700133 while(DecodeNesting_IsNested(pNesting)) {
134 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800135
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800136 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700137 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800138 pNesting->pCurrent->uCount--;
139 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700140
141 if(pNesting->pCurrent->uCount != 0) {
142 // Did not close out an array or map, so nothing further
143 break;
144 }
145
146 // Closed out an array or map so level up
147 pNesting->pCurrent--;
148
149 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150 }
151}
152
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700153
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800154// Called on every map/array
Laurence Lundblade30816f22018-11-10 13:40:22 +0700155inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700157 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800158
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800159 if(pItem->val.uCount == 0) {
160 // Nothing to do for empty definite lenth arrays. They are just are
161 // effectively the same as an item that is not a map or array
162 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530163 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800165
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800166 // Error out if arrays is too long to handle
167 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
169 goto Done;
170 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800171
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700173 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
174 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
175 goto Done;
176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800177
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700179 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800180
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800181 // Record a few details for this nesting level
182 pNesting->pCurrent->uMajorType = pItem->uDataType;
183 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800184
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700185Done:
186 return nReturn;;
187}
188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
190{
191 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
192}
193
194
195
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700196/*
197 This list of built-in tags. Only add tags here that are
198 clearly established and useful. Once a tag is added here
199 it can't be taken out as that would break backwards compatibility.
200 There are only 48 slots available forever.
201 */
202static const uint16_t spBuiltInTagMap[] = {
203 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR
204 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
205 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
206 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
207 CBOR_TAG_FRACTION,
208 CBOR_TAG_BIGFLOAT,
209 CBOR_TAG_COSE_ENCRYPTO,
210 CBOR_TAG_COSE_MAC0,
211 CBOR_TAG_COSE_SIGN1,
212 CBOR_TAG_ENC_AS_B64URL,
213 CBOR_TAG_ENC_AS_B64,
214 CBOR_TAG_ENC_AS_B16,
215 CBOR_TAG_CBOR,
216 CBOR_TAG_URI,
217 CBOR_TAG_B64URL,
218 CBOR_TAG_B64,
219 CBOR_TAG_REGEX,
220 CBOR_TAG_MIME,
221 CBOR_TAG_BIN_UUID,
222 CBOR_TAG_CWT,
223 CBOR_TAG_ENCRYPT,
224 CBOR_TAG_MAC,
225 CBOR_TAG_SIGN,
226 CBOR_TAG_GEO_COORD,
227 CBOR_TAG_CBOR_MAGIC
228};
229
230// This is used in a bit of cleverness in GetNext_TaggedItem() to
231// keep code size down and switch for the internal processing of
232// these types. This will break if the first four items in
233// spBuiltInTagMap don't have values 0,1,2,3. That is the
234// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3.
235#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
236#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
237#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
238#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
239
240#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
241 QCBOR_TAGFLAG_DATE_EPOCH |\
242 QCBOR_TAGFLAG_POS_BIGNUM |\
243 QCBOR_TAGFLAG_NEG_BIGNUM)
244
245#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
246#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
247#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
248
249static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
250{
251 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
252 // This is a cross-check to make sure the above array doesn't
253 // accidentally get made too big.
254 // In normal conditions the above test should optimize out
255 // as all the values are known at compile time.
256 return -1;
257 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800258
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700259 if(uTag > UINT16_MAX) {
260 // This tag map works only on 16-bit tags
261 return -1;
262 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800263
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700264 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
265 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
266 return nTagBitIndex;
267 }
268 }
269 return -1; // Indicates no match
270}
271
272static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
273{
274 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
275 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
276 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
277 }
278 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800279
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700280 return -1; // Indicates no match
281}
282
283/*
284 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800285
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700286 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800287 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700288 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700289static QCBORError TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700290{
291 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
292 if(nTagBitIndex >= 0) {
293 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
294 *puTagBitIndex = (uint8_t)nTagBitIndex;
295 return QCBOR_SUCCESS;
296 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800297
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700298 if(pCallerConfiguredTagMap) {
299 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
300 return QCBOR_ERR_TOO_MANY_TAGS;
301 }
302 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
303 if(nTagBitIndex >= 0) {
304 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
305
306 *puTagBitIndex = (uint8_t)nTagBitIndex;
307 return QCBOR_SUCCESS;
308 }
309 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800310
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700311 return QCBOR_ERR_BAD_OPT_TAG;
312}
313
314
315
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800316/* ===========================================================================
317 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
318
319 The following four functions are pretty wrappers for invocation of
320 the string allocator supplied by the caller.
321
322 ==============================================================================*/
323
324static inline void StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
325{
326 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
327}
328
329// StringAllocator_Reallocate called with pMem NULL is equal to StringAllocator_Allocate()
330static inline UsefulBuf StringAllocator_Reallocate(const QCORInternalAllocator *pMe, void *pMem, size_t uSize)
331{
332 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
333}
334
335static inline UsefulBuf StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
336{
337 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
338}
339
340static inline void StringAllocator_Destruct(const QCORInternalAllocator *pMe)
341{
342 if(pMe->pfAllocator) {
343 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
344 }
345}
346
347
348
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700349
350/*
351 Public function, see header file
352 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800353void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700354{
355 memset(me, 0, sizeof(QCBORDecodeContext));
356 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
357 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
358 // if the default normal mode of 0 was set.
359 me->uDecodeMode = nDecodeMode;
360 DecodeNesting_Init(&(me->nesting));
361}
362
363
364/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700365 Public function, see header file
366 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800367void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
368 QCBORStringAllocate pfAllocateFunction,
369 void *pAllocateContext,
370 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700371{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800372 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
373 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
374 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700375}
376
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800377
378/*
379 Public function, see header file
380 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700381void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
382{
383 me->pCallerConfiguredTagList = pTagList;
384}
385
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700386
387/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700388 This decodes the fundamental part of a CBOR data item, the type and number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800389
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700390 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800391
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700392 This does the network->host byte order conversion. The conversion here
393 also results in the conversion for floats in addition to that for
394 lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800395
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700396 This returns:
397 pnMajorType -- the major type for the item
398 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
399 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800400
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700401 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800402inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
403 int *pnMajorType,
404 uint64_t *puArgument,
405 uint8_t *puAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700406{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700407 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800408
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700409 // Get the initial byte that every CBOR data item has
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800410 const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800411
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700412 // Break down the initial byte
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800413 const uint8_t uTmpMajorType = uInitialByte >> 5;
414 const uint8_t uAdditionalInfo = uInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800415
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800416 // Where the number or argument accumulates
417 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800418
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800419 if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
420 // Need to get 1,2,4 or 8 additional argument bytes
421 // Map LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
422 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800423
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800424 // Loop getting all the bytes in the argument
425 uArgument = 0;
426 for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
427 // This shift and add gives the endian conversion
428 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
429 }
430 } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) {
431 // The reserved and thus-far unused additional info values
432 nReturn = QCBOR_ERR_UNSUPPORTED;
433 goto Done;
434 } else {
435 // Less than 24, additional info is argument or 31, an indefinite length
436 // No more bytes to get
437 uArgument = uAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700438 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800439
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700440 if(UsefulInputBuf_GetError(pUInBuf)) {
441 nReturn = QCBOR_ERR_HIT_END;
442 goto Done;
443 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800444
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700445 // All successful if we got here.
446 nReturn = QCBOR_SUCCESS;
447 *pnMajorType = uTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800448 *puArgument = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700449 *puAdditionalInfo = uAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800450
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700451Done:
452 return nReturn;
453}
454
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700455/*
456 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
457 use it these days and the test vectors in the RFC are so. All integers in the CBOR
458 structure are positive and the major type indicates positive or negative.
459 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
460 and negative integers down to 2^x. Note that negative numbers can be one
461 more away from zero than positive.
462 Stdint, as far as I can tell, uses two's compliment to represent
463 negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800464
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700465 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
466 used here in any way including in the interface
467 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700468inline static QCBORError DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700469{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700470 // Stack usage: int/ptr 1 -- 8
Laurence Lundblade30816f22018-11-10 13:40:22 +0700471 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700473 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
474 if (uNumber <= INT64_MAX) {
475 pDecodedItem->val.int64 = (int64_t)uNumber;
476 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700478 } else {
479 pDecodedItem->val.uint64 = uNumber;
480 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800481
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482 }
483 } else {
484 if(uNumber <= INT64_MAX) {
485 pDecodedItem->val.int64 = -uNumber-1;
486 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800487
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700488 } else {
489 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000490 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700491 nReturn = QCBOR_ERR_INT_OVERFLOW;
492 }
493 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495 return nReturn;
496}
497
498// Make sure #define value line up as DecodeSimple counts on this.
499#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
500#error QCBOR_TYPE_FALSE macro value wrong
501#endif
502
503#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
504#error QCBOR_TYPE_TRUE macro value wrong
505#endif
506
507#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
508#error QCBOR_TYPE_NULL macro value wrong
509#endif
510
511#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
512#error QCBOR_TYPE_UNDEF macro value wrong
513#endif
514
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700515#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
516#error QCBOR_TYPE_BREAK macro value wrong
517#endif
518
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700519#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
520#error QCBOR_TYPE_DOUBLE macro value wrong
521#endif
522
523#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
524#error QCBOR_TYPE_FLOAT macro value wrong
525#endif
526
527/*
528 Decode true, false, floats, break...
529 */
530
Laurence Lundblade30816f22018-11-10 13:40:22 +0700531inline static QCBORError DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700533 // Stack usage: 0
Laurence Lundblade30816f22018-11-10 13:40:22 +0700534 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800535
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700536 // uAdditionalInfo is 5 bits from the initial byte
537 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
538 pDecodedItem->uDataType = uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800539
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 switch(uAdditionalInfo) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700541 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as it is caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800542
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700543 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700544 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
545 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700546 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700547 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700548 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
549 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700550 break;
551 case DOUBLE_PREC_FLOAT:
552 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700553 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700554 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800555
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556 case CBOR_SIMPLEV_FALSE: // 20
557 case CBOR_SIMPLEV_TRUE: // 21
558 case CBOR_SIMPLEV_NULL: // 22
559 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800562
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700563 case CBOR_SIMPLEV_ONEBYTE: // 24
564 if(uNumber <= CBOR_SIMPLE_BREAK) {
565 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700566 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567 goto Done;
568 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800569 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800571
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700572 default: // 0-19
573 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
574 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
575 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
576 pDecodedItem->val.uSimple = (uint8_t)uNumber;
577 break;
578 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800579
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700580Done:
581 return nReturn;
582}
583
584
585
586/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530587 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700588 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
590 int nMajorType,
591 uint64_t uStrLen,
592 UsefulInputBuf *pUInBuf,
593 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700594{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700595 // Stack usage: UsefulBuf 2, int/ptr 1 40
Laurence Lundblade30816f22018-11-10 13:40:22 +0700596 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800597
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800598 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530599 if(UsefulBuf_IsNULLC(Bytes)) {
600 // Failed to get the bytes for this string item
601 nReturn = QCBOR_ERR_HIT_END;
602 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700603 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530604
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530606 // We are asked to use string allocator to make a copy
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800607 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530608 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700609 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530610 goto Done;
611 }
612 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800613 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530614 } else {
615 // Normal case with no string allocator
616 pDecodedItem->val.string = Bytes;
617 }
618 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530620Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700621 return nReturn;
622}
623
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700624
625/*
626 Mostly just assign the right data type for the date string.
627 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700628inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700630 // Stack Use: UsefulBuf 1 16
631 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632 return QCBOR_ERR_BAD_OPT_TAG;
633 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800635 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700636 pDecodedItem->val.dateString = Temp;
637 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 return QCBOR_SUCCESS;
639}
640
641
642/*
643 Mostly just assign the right data type for the bignum.
644 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700645inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700647 // Stack Use: UsefulBuf 1 -- 16
648 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 return QCBOR_ERR_BAD_OPT_TAG;
650 }
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800651 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700652 pDecodedItem->val.bigNum = Temp;
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700653 pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654 return QCBOR_SUCCESS;
655}
656
657
658/*
659 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
660 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700661static int DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700663 // Stack usage: 1
Laurence Lundblade30816f22018-11-10 13:40:22 +0700664 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800667
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700668 switch (pDecodedItem->uDataType) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800669
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700670 case QCBOR_TYPE_INT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700671 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800673
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674 case QCBOR_TYPE_UINT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700675 if(pDecodedItem->val.uint64 > INT64_MAX) {
676 nReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677 goto Done;
678 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700679 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800682 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700683 {
684 const double d = pDecodedItem->val.dfnum;
685 if(d > INT64_MAX) {
686 nReturn = QCBOR_ERR_DATE_OVERFLOW;
687 goto Done;
688 }
689 pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
690 pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800691 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800692 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800693
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 default:
695 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700696 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700698 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700Done:
701 return nReturn;
702}
703
704
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700705
706
707// Make sure the constants align as this is assumed by the GetAnItem() implementation
708#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
709#error QCBOR_TYPE_ARRAY value not lined up with major type
710#endif
711#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
712#error QCBOR_TYPE_MAP value not lined up with major type
713#endif
714
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700716 This gets a single data item and decodes it including preceding optional tagging. This does not
717 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
718 maps are handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800719
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700720 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
721 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800723static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
724 QCBORItem *pDecodedItem,
725 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700726{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700727 // Stack usage: int/ptr 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700728 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800729
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700730 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
731 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
732 int uMajorType;
733 uint64_t uNumber;
734 uint8_t uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800735
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700736 memset(pDecodedItem, 0, sizeof(QCBORItem));
737
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700738 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800739
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700740 // Error out here if we got into trouble on the type and number.
741 // The code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700742 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700743 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700744 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800745
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700746 // At this point the major type and the value are valid. We've got the type and the number that
747 // starts every CBOR data item.
748 switch (uMajorType) {
749 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
750 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700751 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
752 nReturn = QCBOR_ERR_BAD_INT;
753 } else {
754 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
755 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700756 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800757
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700758 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
759 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
760 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
761 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530762 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700763 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800764 nReturn = DecodeBytes(pAllocator, uMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700765 }
766 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700768 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
769 case CBOR_MAJOR_TYPE_MAP: // Major type 5
770 // Record the number of items in the array or map
771 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
772 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
773 goto Done;
774 }
775 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530776 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 } else {
778 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
779 }
780 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
781 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800782
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700783 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700784 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
785 nReturn = QCBOR_ERR_BAD_INT;
786 } else {
787 pDecodedItem->val.uTagV = uNumber;
788 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
789 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700790 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
793 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
794 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800795
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700796 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
797 nReturn = QCBOR_ERR_UNSUPPORTED;
798 break;
799 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801Done:
802 return nReturn;
803}
804
805
806
807/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800808 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700809 individual chunk items together into one QCBORItem using the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530810 string allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530812 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700813 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700814static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700815{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700816 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700817 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800818 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
819 &(me->StringAllocator) :
820 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530821 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800823 nReturn = GetNext_Item(&(me->InBuf),
824 pDecodedItem,
825 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700826 if(nReturn) {
827 goto Done;
828 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800829
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700830 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530831 // code in this function from here down can be eliminated. Run tests, except
832 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800834 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700835 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
836 goto Done; // no need to do any work here on non-string types
837 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800839 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530840 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800841 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800843
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530844 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800845 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700846 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
847 goto Done;
848 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800849
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700850 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800851 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800853
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700854 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700855 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700856 // Get item for next chunk
857 QCBORItem StringChunkItem;
858 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800859 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700861 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700862 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800863
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530864 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700865 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800866 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700867 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530868 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 break;
870 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700872 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530873 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700874 // Also catches indefinite length strings inside indefinite length strings
875 if(StringChunkItem.uDataType != uStringType || StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700876 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700877 break;
878 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800879
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530880 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800881 // The first time throurgh FullString.ptr is NULL and this is
882 // equivalent to StringAllocator_Allocate()
883 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
884 UNCONST_POINTER(FullString.ptr),
885 FullString.len + StringChunkItem.val.string.len);
886
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530888 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700889 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890 break;
891 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800892
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700893 // Copy new string chunk at the end of string so far.
894 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700895 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800898 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
899 // Getting the item failed, clean up the allocated memory
900 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800902
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903 return nReturn;
904}
905
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700906
907/*
908 Returns an error if there was something wrong with the optional item or it couldn't
909 be handled.
910 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700911static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700912{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700913 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700914 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700915 uint64_t uTagBits = 0;
916 if(pTags) {
917 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700918 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700919
920 for(;;) {
921 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700922 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700923 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800925
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700926 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
927 // Successful exit from loop; maybe got some tags, maybe not
928 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700929 break;
930 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800931
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700932 uint8_t uTagBitIndex;
933 // Tag was mapped, tag was not mapped, error with tag list
934 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800935
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700936 case QCBOR_SUCCESS:
937 // Successfully mapped the tag
938 uTagBits |= 0x01ULL << uTagBitIndex;
939 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700941 case QCBOR_ERR_BAD_OPT_TAG:
942 // Tag is not recognized. Do nothing
943 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700945 default:
946 // Error Condition
947 goto Done;
948 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700950 if(pTags) {
951 // Caller wants all tags recorded in the provided buffer
952 if(pTags->uNumUsed >= pTags->uNumAllocated) {
953 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
954 goto Done;
955 }
956 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
957 pTags->uNumUsed++;
958 }
959 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700961 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700962 case 0:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700963 // No tags at all or none we know about. Nothing to do.
964 // This is part of the pass-through path of this function
965 // that will mostly be taken when decoding any item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700966 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800967
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700968 case QCBOR_TAGFLAG_DATE_STRING:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700969 nReturn = DecodeDateString(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700970 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700972 case QCBOR_TAGFLAG_DATE_EPOCH:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700973 nReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700974 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800975
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700976 case QCBOR_TAGFLAG_POS_BIGNUM:
977 case QCBOR_TAGFLAG_NEG_BIGNUM:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700978 nReturn = DecodeBigNum(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700979 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800980
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700981 default:
982 // Encountering some mixed up CBOR like something that
983 // is tagged as both a string and integer date.
Laurence Lundblade30816f22018-11-10 13:40:22 +0700984 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700985 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800986
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700987Done:
988 return nReturn;
989}
990
991
992/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800993 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700994 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700995static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700996{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700997 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700998 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700999 if(nReturn)
1000 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001002 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001003 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001004 goto Done;
1005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001007 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1008 // In a map and caller wants maps decoded, not treated as arrays
1009
1010 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1011 // If in a map and the right decoding mode, get the label
1012
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001013 // Get the next item which will be the real data; Item will be the label
1014 QCBORItem LabelItem = *pDecodedItem;
1015 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1016 if(nReturn)
1017 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001018
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301019 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001020
1021 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1022 // strings are always good labels
1023 pDecodedItem->label.string = LabelItem.val.string;
1024 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1025 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
1026 // It's not a string and we only want strings, probably for easy translation to JSON
1027 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1028 goto Done;
1029 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1030 pDecodedItem->label.int64 = LabelItem.val.int64;
1031 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1032 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1033 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1034 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1035 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1036 pDecodedItem->label.string = LabelItem.val.string;
1037 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1038 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1039 } else {
1040 // label is not an int or a string. It is an arrray
1041 // or a float or such and this implementation doesn't handle that.
1042 // Also, tags on labels are ignored.
1043 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1044 goto Done;
1045 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001046 }
1047 } else {
1048 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1049 // Decoding a map as an array
1050 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1051 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001052 }
1053 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001054
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001055Done:
1056 return nReturn;
1057}
1058
1059
1060/*
1061 Public function, see header qcbor.h file
1062 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001063QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001065 // Stack ptr/int: 2, QCBORItem : 64
1066
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301067 // The public entry point for fetching and parsing the next QCBORItem.
1068 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001069 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001070
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001071 // Check if there are an
1072 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1073 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1074 goto Done;
1075 }
1076
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001077 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001078 if(nReturn) {
1079 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301081
1082 // Break ending arrays/maps are always processed at the end of this function.
1083 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301084 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301085 nReturn = QCBOR_ERR_BAD_BREAK;
1086 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301087 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundblade6de37062018-10-15 12:22:42 +05301089 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301090 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301091 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade6de37062018-10-15 12:22:42 +05301093 // Process the item just received for descent or decrement, and
1094 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001095 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001096 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001097 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001098 // Maps and arrays do count in as items in the map/array that encloses
1099 // them so a decrement needs to be done for them too, but that is done
1100 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001101 // are opened with the exception of an empty map or array.
1102 if(pDecodedItem->val.uCount == 0) {
1103 DecodeNesting_DecrementCount(&(me->nesting));
1104 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001105 } else {
1106 // Decrement the count of items in the enclosing map/array
1107 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301108 // triggers a decrement in the map/array above that and
1109 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001110 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001111 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301112 if(nReturn) {
1113 goto Done;
1114 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001115
Laurence Lundblade6de37062018-10-15 12:22:42 +05301116 // For indefinite length maps/arrays, looking at any and
1117 // all breaks that might terminate them. The equivalent
1118 // for definite length maps/arrays happens in
1119 // DecodeNesting_DecrementCount().
1120 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1121 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1122 // Peek forward one item to see if it is a break.
1123 QCBORItem Peek;
1124 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1125 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1126 if(nReturn) {
1127 goto Done;
1128 }
1129 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1130 // It is not a break, rewind so it can be processed normally.
1131 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1132 break;
1133 }
1134 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301135 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301136 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1137 if(nReturn) {
1138 // break occured outside of an indefinite length array/map
1139 goto Done;
1140 }
1141 }
1142 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001143
Laurence Lundblade6de37062018-10-15 12:22:42 +05301144 // Tell the caller what level is next. This tells them what maps/arrays
1145 // were closed out and makes it possible for them to reconstruct
1146 // the tree with just the information returned by GetNext
1147 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001149Done:
1150 return nReturn;
1151}
1152
1153
Laurence Lundblade30816f22018-11-10 13:40:22 +07001154QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001155{
1156 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1157}
1158
1159
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001160/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301161 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301162 next one down. If a layer has no work to do for a particular item
1163 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001164
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301165 - QCBORDecode_GetNext -- The top layer manages the beginnings and
1166 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301167 out of maps/arrays. It processes all breaks that terminate
1168 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001169
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301170 - GetNext_MapEntry -- This handles the combining of two
1171 items, the label and the data, that make up a map entry.
1172 It only does work on maps. It combines the label and data
1173 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301175 - GetNext_TaggedItem -- This handles the type 6 tagged items.
1176 It accumulates all the tags and combines them with the following
1177 non-tagged item. If the tagged item is something that is understood
1178 like a date, the decoding of that item is invoked.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001179
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301180 - GetNext_FullItem -- This assembles the sub items that make up
1181 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301182 string allocater to create contiguous space for the item. It
1183 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001184
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301185 - GetNext_Item -- This gets and decodes the most atomic
1186 item in CBOR, the thing with an initial byte containing
1187 the major type.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001188
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001189 Roughly this takes 300 bytes of stack for vars. Need to
1190 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301192 */
1193
1194
1195/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001196 Public function, see header qcbor.h file
1197 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001198int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
1199{
1200 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001201
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001202 uint8_t uTagBitIndex;
1203 // Do not care about errors in pCallerConfiguredTagMap here. They are
1204 // caught during GetNext() before this is called.
1205 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1206 return 0;
1207 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001208
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001209 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1210 return (uTagBit & pItem->uTagBits) != 0;
1211}
1212
1213
1214/*
1215 Public function, see header qcbor.h file
1216 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001217QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001218{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001219 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001220
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001221 // Error out if all the maps/arrays are not closed out
1222 if(DecodeNesting_IsNested(&(me->nesting))) {
1223 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1224 goto Done;
1225 }
1226
1227 // Error out if not all the bytes are consumed
1228 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1229 nReturn = QCBOR_ERR_EXTRA_BYTES;
1230 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001231
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001232Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301233 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001234 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001235 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001236
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001237 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001238}
1239
1240
1241
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242/*
1243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001245
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001246 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001248 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001249
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001250 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001251
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001252 - 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 -08001253
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001254 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001255
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001256 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001257
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001258 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001259
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001260 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001261
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001262 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001263
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001264 */
1265
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001266
1267
Laurence Lundbladef6531662018-12-04 10:42:22 +09001268
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001269/* ===========================================================================
1270 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001271
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001272 This implements a simple sting allocator for indefinite length
1273 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1274 implements the function type QCBORStringAllocate and allows easy
1275 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001276
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001277 This particular allocator is built-in for convenience. The caller
1278 can implement their own. All of this following code will get
1279 dead-stripped if QCBORDecode_SetMemPool() is not called.
1280
1281 This is a very primitive memory allocator. It does not track
1282 individual allocations, only a high-water mark. A free or
1283 reallocation must be of the last chunk allocated.
1284
1285 The size of the pool and offset to free memory are packed into the
1286 first 8 bytes of the memory pool so we don't have to keep them in
1287 the decode context. Since the address of the pool may not be
1288 aligned, they have to be packed and unpacked as if they were
1289 serialized data of the wire or such.
1290
1291 The sizes packed in are uint32_t to be the same on all CPU types
1292 and simplify the code.
1293 =========================================================================== */
1294
1295
1296static inline int MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
1297{
1298 // Use of UsefulInputBuf is overkill, but it is convenient.
1299 UsefulInputBuf UIB;
1300
1301 // Just assume the size here. It was checked during SetUp so the assumption is safe.
1302 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1303 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1304 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1305 return UsefulInputBuf_GetError(&UIB);
1306}
1307
1308
1309static inline int MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
1310{
1311 // Use of UsefulOutBuf is overkill, but convenient. The
1312 // length check performed here is useful.
1313 UsefulOutBuf UOB;
1314
1315 UsefulOutBuf_Init(&UOB, Pool);
1316 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1317 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1318 return UsefulOutBuf_GetError(&UOB);
1319}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001320
1321
1322/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001323 Internal function for an allocation, reallocation free and destuct.
1324
1325 Having only one function rather than one each per mode saves space in
1326 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001328 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1329 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001330static UsefulBuf MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001331{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001332 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001333
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001334 uint32_t uPoolSize;
1335 uint32_t uFreeOffset;
1336
1337 if(uNewSize > UINT32_MAX) {
1338 // This allocator is only good up to 4GB. This check should
1339 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1340 goto Done;
1341 }
1342 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1343
1344 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1345 goto Done;
1346 }
1347
1348 if(uNewSize) {
1349 if(pMem) {
1350 // REALLOCATION MODE
1351 // Calculate pointer to the end of the memory pool. It is
1352 // assumed that pPool + uPoolSize won't wrap around by
1353 // assuming the caller won't pass a pool buffer in that is
1354 // not in legitimate memory space.
1355 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1356
1357 // Check that the pointer for reallocation is in the range of the
1358 // pool. This also makes sure that pointer math further down
1359 // doesn't wrap under or over.
1360 if(pMem >= pPool && pMem < pPoolEnd) {
1361 // Offset to start of chunk for reallocation. This won't
1362 // wrap under because of check that pMem >= pPool. Cast
1363 // is safe because the pool is always less than UINT32_MAX
1364 // because of check in QCBORDecode_SetMemPool().
1365 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1366
1367 // Check to see if the allocation will fit. uPoolSize -
1368 // uMemOffset will not wrap under because of check that
1369 // pMem is in the range of the uPoolSize by check above.
1370 if(uNewSize <= uPoolSize - uMemOffset) {
1371 ReturnValue.ptr = pMem;
1372 ReturnValue.len = uNewSize;
1373
1374 // Addition won't wrap around over because uNewSize was
1375 // checked to be sure it is less than the pool size.
1376 uFreeOffset = uMemOffset + uNewSize32;
1377 }
1378 }
1379 } else {
1380 // ALLOCATION MODE
1381 // uPoolSize - uFreeOffset will not underflow because this
1382 // pool implementation makes sure uFreeOffset is always
1383 // smaller than uPoolSize through this check here and
1384 // reallocation case.
1385 if(uNewSize <= uPoolSize - uFreeOffset) {
1386 ReturnValue.len = uNewSize;
1387 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
1388 uFreeOffset += uNewSize;
1389 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001390 }
1391 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001392 if(pMem) {
1393 // FREE MODE
1394 // Cast is safe because of limit on pool size in
1395 // QCBORDecode_SetMemPool()
1396 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1397 } else {
1398 // DESTRUCT MODE
1399 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001400 }
1401 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001402
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001403 UsefulBuf Pool = {pPool, uPoolSize};
1404 MemPool_Pack(Pool, uFreeOffset);
1405
1406Done:
1407 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001408}
1409
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001410
Laurence Lundbladef6531662018-12-04 10:42:22 +09001411/*
1412 Public function, see header qcbor.h file
1413 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001414QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001415{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001416 // The pool size and free mem offset are packed into the beginning
1417 // of the pool memory. This compile time check make sure the
1418 // constant in the header is correct. This check should optimize
1419 // down to nothing.
1420 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001421 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001423
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001424 // The pool size and free offset packed in to the beginning of pool
1425 // memory are only 32-bits. This check will optimize out on 32-bit
1426 // machines.
1427 if(Pool.len > UINT32_MAX) {
1428 return QCBOR_ERR_BUFFER_TOO_LARGE;
1429 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001430
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001431 // This checks that the pool buffer given is big enough.
1432 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1433 return QCBOR_ERR_BUFFER_TOO_SMALL;
1434 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001435
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001436 pMe->StringAllocator.pfAllocator = MemPool_Function;
1437 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1438 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001439
Laurence Lundblade30816f22018-11-10 13:40:22 +07001440 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001441}