blob: 0c1eda9034a9c705ab1f0b55c413a53904aedbef [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 Lundblade1d7eb632019-02-17 17:23:38 -080045 02/17/19 llundblade Fixed: QCBORItem.u{Data|Label}Alloc when bAllStrings set
46 02/16/19 llundblade Redesign MemPool to fix memory access alignment bug
Laurence Lundblade4c0cf842019-01-12 03:25:44 -080047 01/10/19 llundblade Clever type and argument decoder is 250 bytes smaller
Laurence Lundblade8b06e2e2018-12-04 12:26:51 +090048 11/9/18 llundblade Error codes are now enums.
49 11/2/18 llundblade Simplify float decoding and align with preferred
50 float encoding
51 10/31/18 llundblade Switch to one license that is almost BSD-3.
52 10/28/18 llundblade Reworked tag decoding
53 10/15/18 llundblade Indefinite length maps and arrays supported
54 10/8/18 llundblade Indefinite length strings supported
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070055 02/04/17 llundbla Work on CPUs that don's require pointer alignment
56 by making use of changes in UsefulBuf
57 03/01/17 llundbla More data types; decoding improvements and fixes
58 11/13/16 llundbla Integrate most TZ changes back into github version.
59 09/30/16 gkanike Porting to TZ.
60 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080061
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070062 =====================================================================================*/
63
64#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070065#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070066
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070067
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053068/*
69 This casts away the const-ness of a pointer, usually so it can be
70 freed or realloced.
71 */
72#define UNCONST_POINTER(ptr) ((void *)(ptr))
73
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074
75/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080076 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077 */
78
79inline static int IsMapOrArray(uint8_t uDataType)
80{
81 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
82}
83
84inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
85{
86 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
87}
88
Laurence Lundblade041ffa52018-10-07 11:43:51 +070089inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070090{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070091 return pNesting->pCurrent->uCount == UINT16_MAX;
92}
93
Laurence Lundblade3a760b02018-10-08 13:46:03 +080094inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
95{
96 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
97}
98
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
100{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700101 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700103 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800104
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700105 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
106}
107
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800108// Process a break. This will either ascend the nesting or error out
Laurence Lundblade30816f22018-11-10 13:40:22 +0700109inline static QCBORError DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700110{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800111 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800113 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700114 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800115
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800116 // breaks can only occur when the map/array is indefinite length
117 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
118 return QCBOR_ERR_BAD_BREAK;
119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800120
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800121 // if all OK, the break reduces the level of nesting
122 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800123
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800124 return QCBOR_SUCCESS;
125}
126
127// Called on every single item except breaks including the opening of a map/array
128inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
129{
130 if(!DecodeNesting_IsNested(pNesting)) {
131 // at top level where there is no tracking
132 return;
133 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800134
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800135 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
136 // There is no count for indefinite length arrays/maps
137 return;
138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800139
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800140 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700141 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700142
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800143 // Pop up nesting levels if the counts at the levels are zero
144 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700145 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800146 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
147 pNesting->pCurrent->uCount--;
148 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700149 }
150}
151
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800152// Called on every map/array
Laurence Lundblade30816f22018-11-10 13:40:22 +0700153inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700155 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800156
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800157 if(pItem->val.uCount == 0) {
158 // Nothing to do for empty definite lenth arrays. They are just are
159 // effectively the same as an item that is not a map or array
160 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530161 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800162 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800163
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800164 // Error out if arrays is too long to handle
165 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700166 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
167 goto Done;
168 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800169
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800170 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700171 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
172 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
173 goto Done;
174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800175
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800176 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700177 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800178
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800179 // Record a few details for this nesting level
180 pNesting->pCurrent->uMajorType = pItem->uDataType;
181 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800182
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700183Done:
184 return nReturn;;
185}
186
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700187inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
188{
189 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
190}
191
192
193
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700194/*
195 This list of built-in tags. Only add tags here that are
196 clearly established and useful. Once a tag is added here
197 it can't be taken out as that would break backwards compatibility.
198 There are only 48 slots available forever.
199 */
200static const uint16_t spBuiltInTagMap[] = {
201 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR
202 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
203 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
204 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
205 CBOR_TAG_FRACTION,
206 CBOR_TAG_BIGFLOAT,
207 CBOR_TAG_COSE_ENCRYPTO,
208 CBOR_TAG_COSE_MAC0,
209 CBOR_TAG_COSE_SIGN1,
210 CBOR_TAG_ENC_AS_B64URL,
211 CBOR_TAG_ENC_AS_B64,
212 CBOR_TAG_ENC_AS_B16,
213 CBOR_TAG_CBOR,
214 CBOR_TAG_URI,
215 CBOR_TAG_B64URL,
216 CBOR_TAG_B64,
217 CBOR_TAG_REGEX,
218 CBOR_TAG_MIME,
219 CBOR_TAG_BIN_UUID,
220 CBOR_TAG_CWT,
221 CBOR_TAG_ENCRYPT,
222 CBOR_TAG_MAC,
223 CBOR_TAG_SIGN,
224 CBOR_TAG_GEO_COORD,
225 CBOR_TAG_CBOR_MAGIC
226};
227
228// This is used in a bit of cleverness in GetNext_TaggedItem() to
229// keep code size down and switch for the internal processing of
230// these types. This will break if the first four items in
231// spBuiltInTagMap don't have values 0,1,2,3. That is the
232// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3.
233#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
234#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
235#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
236#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
237
238#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
239 QCBOR_TAGFLAG_DATE_EPOCH |\
240 QCBOR_TAGFLAG_POS_BIGNUM |\
241 QCBOR_TAGFLAG_NEG_BIGNUM)
242
243#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
244#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
245#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
246
247static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
248{
249 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
250 // This is a cross-check to make sure the above array doesn't
251 // accidentally get made too big.
252 // In normal conditions the above test should optimize out
253 // as all the values are known at compile time.
254 return -1;
255 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800256
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700257 if(uTag > UINT16_MAX) {
258 // This tag map works only on 16-bit tags
259 return -1;
260 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800261
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700262 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
263 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
264 return nTagBitIndex;
265 }
266 }
267 return -1; // Indicates no match
268}
269
270static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
271{
272 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
273 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
274 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
275 }
276 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800277
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700278 return -1; // Indicates no match
279}
280
281/*
282 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700284 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800285 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700286 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700287static QCBORError TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700288{
289 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
290 if(nTagBitIndex >= 0) {
291 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
292 *puTagBitIndex = (uint8_t)nTagBitIndex;
293 return QCBOR_SUCCESS;
294 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800295
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700296 if(pCallerConfiguredTagMap) {
297 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
298 return QCBOR_ERR_TOO_MANY_TAGS;
299 }
300 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
301 if(nTagBitIndex >= 0) {
302 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
303
304 *puTagBitIndex = (uint8_t)nTagBitIndex;
305 return QCBOR_SUCCESS;
306 }
307 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800308
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700309 return QCBOR_ERR_BAD_OPT_TAG;
310}
311
312
313
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800314/* ===========================================================================
315 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
316
317 The following four functions are pretty wrappers for invocation of
318 the string allocator supplied by the caller.
319
320 ==============================================================================*/
321
322static inline void StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
323{
324 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
325}
326
327// StringAllocator_Reallocate called with pMem NULL is equal to StringAllocator_Allocate()
328static inline UsefulBuf StringAllocator_Reallocate(const QCORInternalAllocator *pMe, void *pMem, size_t uSize)
329{
330 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
331}
332
333static inline UsefulBuf StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
334{
335 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
336}
337
338static inline void StringAllocator_Destruct(const QCORInternalAllocator *pMe)
339{
340 if(pMe->pfAllocator) {
341 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
342 }
343}
344
345
346
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700347
348/*
349 Public function, see header file
350 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800351void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700352{
353 memset(me, 0, sizeof(QCBORDecodeContext));
354 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
355 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
356 // if the default normal mode of 0 was set.
357 me->uDecodeMode = nDecodeMode;
358 DecodeNesting_Init(&(me->nesting));
359}
360
361
362/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700363 Public function, see header file
364 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800365void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
366 QCBORStringAllocate pfAllocateFunction,
367 void *pAllocateContext,
368 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700369{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800370 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
371 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
372 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700373}
374
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800375
376/*
377 Public function, see header file
378 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700379void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
380{
381 me->pCallerConfiguredTagList = pTagList;
382}
383
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700384
385/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700386 This decodes the fundamental part of a CBOR data item, the type and number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800387
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700388 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800389
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700390 This does the network->host byte order conversion. The conversion here
391 also results in the conversion for floats in addition to that for
392 lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800393
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700394 This returns:
395 pnMajorType -- the major type for the item
396 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
397 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800398
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700399 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800400inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
401 int *pnMajorType,
402 uint64_t *puArgument,
403 uint8_t *puAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700404{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700405 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800406
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700407 // Get the initial byte that every CBOR data item has
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800408 const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800409
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700410 // Break down the initial byte
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800411 const uint8_t uTmpMajorType = uInitialByte >> 5;
412 const uint8_t uAdditionalInfo = uInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800413
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800414 // Where the number or argument accumulates
415 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800416
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800417 if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
418 // Need to get 1,2,4 or 8 additional argument bytes
419 // Map LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
420 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800421
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800422 // Loop getting all the bytes in the argument
423 uArgument = 0;
424 for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
425 // This shift and add gives the endian conversion
426 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
427 }
428 } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) {
429 // The reserved and thus-far unused additional info values
430 nReturn = QCBOR_ERR_UNSUPPORTED;
431 goto Done;
432 } else {
433 // Less than 24, additional info is argument or 31, an indefinite length
434 // No more bytes to get
435 uArgument = uAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700436 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800437
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700438 if(UsefulInputBuf_GetError(pUInBuf)) {
439 nReturn = QCBOR_ERR_HIT_END;
440 goto Done;
441 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800442
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700443 // All successful if we got here.
444 nReturn = QCBOR_SUCCESS;
445 *pnMajorType = uTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800446 *puArgument = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700447 *puAdditionalInfo = uAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800448
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700449Done:
450 return nReturn;
451}
452
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700453/*
454 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
455 use it these days and the test vectors in the RFC are so. All integers in the CBOR
456 structure are positive and the major type indicates positive or negative.
457 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
458 and negative integers down to 2^x. Note that negative numbers can be one
459 more away from zero than positive.
460 Stdint, as far as I can tell, uses two's compliment to represent
461 negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800462
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
464 used here in any way including in the interface
465 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700466inline static QCBORError DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700468 // Stack usage: int/ptr 1 -- 8
Laurence Lundblade30816f22018-11-10 13:40:22 +0700469 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800470
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700471 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
472 if (uNumber <= INT64_MAX) {
473 pDecodedItem->val.int64 = (int64_t)uNumber;
474 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800475
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700476 } else {
477 pDecodedItem->val.uint64 = uNumber;
478 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800479
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700480 }
481 } else {
482 if(uNumber <= INT64_MAX) {
483 pDecodedItem->val.int64 = -uNumber-1;
484 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800485
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700486 } else {
487 // C can't represent a negative integer in this range
488 // so it is an error. todo -- test this condition
489 nReturn = QCBOR_ERR_INT_OVERFLOW;
490 }
491 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800492
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700493 return nReturn;
494}
495
496// Make sure #define value line up as DecodeSimple counts on this.
497#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
498#error QCBOR_TYPE_FALSE macro value wrong
499#endif
500
501#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
502#error QCBOR_TYPE_TRUE macro value wrong
503#endif
504
505#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
506#error QCBOR_TYPE_NULL macro value wrong
507#endif
508
509#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
510#error QCBOR_TYPE_UNDEF macro value wrong
511#endif
512
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700513#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
514#error QCBOR_TYPE_BREAK macro value wrong
515#endif
516
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
518#error QCBOR_TYPE_DOUBLE macro value wrong
519#endif
520
521#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
522#error QCBOR_TYPE_FLOAT macro value wrong
523#endif
524
525/*
526 Decode true, false, floats, break...
527 */
528
Laurence Lundblade30816f22018-11-10 13:40:22 +0700529inline static QCBORError DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700530{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700531 // Stack usage: 0
Laurence Lundblade30816f22018-11-10 13:40:22 +0700532 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800533
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534 // uAdditionalInfo is 5 bits from the initial byte
535 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
536 pDecodedItem->uDataType = uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800537
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700538 switch(uAdditionalInfo) {
539 case ADDINFO_RESERVED1: // 28
540 case ADDINFO_RESERVED2: // 29
541 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542 nReturn = QCBOR_ERR_UNSUPPORTED;
543 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800544
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700545 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700546 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
547 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700548 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700549 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700550 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
551 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700552 break;
553 case DOUBLE_PREC_FLOAT:
554 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700555 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700556 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800557
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700558 case CBOR_SIMPLEV_FALSE: // 20
559 case CBOR_SIMPLEV_TRUE: // 21
560 case CBOR_SIMPLEV_NULL: // 22
561 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700562 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700563 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800564
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700565 case CBOR_SIMPLEV_ONEBYTE: // 24
566 if(uNumber <= CBOR_SIMPLE_BREAK) {
567 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700568 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700569 goto Done;
570 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800571 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700572 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800573
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574 default: // 0-19
575 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
576 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
577 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
578 pDecodedItem->val.uSimple = (uint8_t)uNumber;
579 break;
580 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800581
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700582Done:
583 return nReturn;
584}
585
586
587
588/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530589 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700590 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800591inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
592 int nMajorType,
593 uint64_t uStrLen,
594 UsefulInputBuf *pUInBuf,
595 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700596{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700597 // Stack usage: UsefulBuf 2, int/ptr 1 40
Laurence Lundblade30816f22018-11-10 13:40:22 +0700598 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800599
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800600 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530601 if(UsefulBuf_IsNULLC(Bytes)) {
602 // Failed to get the bytes for this string item
603 nReturn = QCBOR_ERR_HIT_END;
604 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700605 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530606
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800607 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530608 // We are asked to use string allocator to make a copy
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530610 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700611 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530612 goto Done;
613 }
614 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800615 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530616 } else {
617 // Normal case with no string allocator
618 pDecodedItem->val.string = Bytes;
619 }
620 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530622Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700623 return nReturn;
624}
625
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626
627/*
628 Mostly just assign the right data type for the date string.
629 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700630inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700632 // Stack Use: UsefulBuf 1 16
633 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 return QCBOR_ERR_BAD_OPT_TAG;
635 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800636
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800637 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700638 pDecodedItem->val.dateString = Temp;
639 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640 return QCBOR_SUCCESS;
641}
642
643
644/*
645 Mostly just assign the right data type for the bignum.
646 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700647inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700648{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700649 // Stack Use: UsefulBuf 1 -- 16
650 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 return QCBOR_ERR_BAD_OPT_TAG;
652 }
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800653 const UsefulBufC Temp = pDecodedItem->val.string;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700654 pDecodedItem->val.bigNum = Temp;
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700655 pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 return QCBOR_SUCCESS;
657}
658
659
660/*
661 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
662 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700663static int DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700665 // Stack usage: 1
Laurence Lundblade30816f22018-11-10 13:40:22 +0700666 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800669
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700670 switch (pDecodedItem->uDataType) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800671
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672 case QCBOR_TYPE_INT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700673 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800675
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 case QCBOR_TYPE_UINT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700677 if(pDecodedItem->val.uint64 > INT64_MAX) {
678 nReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679 goto Done;
680 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700681 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800683
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800684 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700685 {
686 const double d = pDecodedItem->val.dfnum;
687 if(d > INT64_MAX) {
688 nReturn = QCBOR_ERR_DATE_OVERFLOW;
689 goto Done;
690 }
691 pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
692 pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800693 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800694 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800695
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696 default:
697 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700698 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700700 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800701
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700702Done:
703 return nReturn;
704}
705
706
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700707
708
709// Make sure the constants align as this is assumed by the GetAnItem() implementation
710#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
711#error QCBOR_TYPE_ARRAY value not lined up with major type
712#endif
713#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
714#error QCBOR_TYPE_MAP value not lined up with major type
715#endif
716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700718 This gets a single data item and decodes it including preceding optional tagging. This does not
719 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
720 maps are handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700722 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
723 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800725static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
726 QCBORItem *pDecodedItem,
727 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700728{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700729 // Stack usage: int/ptr 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700730 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700732 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
733 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
734 int uMajorType;
735 uint64_t uNumber;
736 uint8_t uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800737
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 Lundbladefab1b522018-10-19 13:40:52 +0530746 memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800747
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700748 // At this point the major type and the value are valid. We've got the type and the number that
749 // starts every CBOR data item.
750 switch (uMajorType) {
751 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
752 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700753 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
754 nReturn = QCBOR_ERR_BAD_INT;
755 } else {
756 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
757 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700758 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800759
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700760 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
761 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
762 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
763 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530764 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700765 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800766 nReturn = DecodeBytes(pAllocator, uMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700767 }
768 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700770 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
771 case CBOR_MAJOR_TYPE_MAP: // Major type 5
772 // Record the number of items in the array or map
773 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
774 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
775 goto Done;
776 }
777 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530778 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 } else {
780 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
781 }
782 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
783 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800784
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700786 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700787 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
788 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700790 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
791 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
792 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
795 nReturn = QCBOR_ERR_UNSUPPORTED;
796 break;
797 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800798
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799Done:
800 return nReturn;
801}
802
803
804
805/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800806 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700807 individual chunk items together into one QCBORItem using the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530808 string allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800809
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530810 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700811 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700812static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700813{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700814 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700815 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800816 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
817 &(me->StringAllocator) :
818 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530819 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800820
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800821 nReturn = GetNext_Item(&(me->InBuf),
822 pDecodedItem,
823 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700824 if(nReturn) {
825 goto Done;
826 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800827
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700828 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530829 // code in this function from here down can be eliminated. Run tests, except
830 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800832 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
834 goto Done; // no need to do any work here on non-string types
835 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800837 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530838 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800839 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700840 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530842 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800843 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
845 goto Done;
846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800849 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700850 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800851
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700852 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700854 // Get item for next chunk
855 QCBORItem StringChunkItem;
856 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800857 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700858 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700859 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530862 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700863 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800864 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530866 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700867 break;
868 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800869
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700870 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530871 // Also catches error of other non-string types that don't belong.
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700872 if(StringChunkItem.uDataType != uStringType) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700873 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700874 break;
875 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800876
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800878 // The first time throurgh FullString.ptr is NULL and this is
879 // equivalent to StringAllocator_Allocate()
880 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
881 UNCONST_POINTER(FullString.ptr),
882 FullString.len + StringChunkItem.val.string.len);
883
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530885 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700886 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 break;
888 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700890 // Copy new string chunk at the end of string so far.
891 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800893
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800895 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
896 // Getting the item failed, clean up the allocated memory
897 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700898 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700900 return nReturn;
901}
902
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700903
904/*
905 Returns an error if there was something wrong with the optional item or it couldn't
906 be handled.
907 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700908static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700909{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700910 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700911 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700912 uint64_t uTagBits = 0;
913 if(pTags) {
914 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700916
917 for(;;) {
918 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700919 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700920 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700923 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
924 // Successful exit from loop; maybe got some tags, maybe not
925 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700926 break;
927 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700929 uint8_t uTagBitIndex;
930 // Tag was mapped, tag was not mapped, error with tag list
931 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700933 case QCBOR_SUCCESS:
934 // Successfully mapped the tag
935 uTagBits |= 0x01ULL << uTagBitIndex;
936 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700938 case QCBOR_ERR_BAD_OPT_TAG:
939 // Tag is not recognized. Do nothing
940 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700942 default:
943 // Error Condition
944 goto Done;
945 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700947 if(pTags) {
948 // Caller wants all tags recorded in the provided buffer
949 if(pTags->uNumUsed >= pTags->uNumAllocated) {
950 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
951 goto Done;
952 }
953 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
954 pTags->uNumUsed++;
955 }
956 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700958 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700959 case 0:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700960 // No tags at all or none we know about. Nothing to do.
961 // This is part of the pass-through path of this function
962 // that will mostly be taken when decoding any item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700963 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700965 case QCBOR_TAGFLAG_DATE_STRING:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700966 nReturn = DecodeDateString(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700969 case QCBOR_TAGFLAG_DATE_EPOCH:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700970 nReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700971 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700973 case QCBOR_TAGFLAG_POS_BIGNUM:
974 case QCBOR_TAGFLAG_NEG_BIGNUM:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700975 nReturn = DecodeBigNum(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700976 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700978 default:
979 // Encountering some mixed up CBOR like something that
980 // is tagged as both a string and integer date.
Laurence Lundblade30816f22018-11-10 13:40:22 +0700981 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700982 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800983
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700984Done:
985 return nReturn;
986}
987
988
989/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800990 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700991 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700992static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700993{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700994 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700995 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700996 if(nReturn)
997 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800999 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001000 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001001 goto Done;
1002 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001004 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1005 // In a map and caller wants maps decoded, not treated as arrays
1006
1007 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1008 // If in a map and the right decoding mode, get the label
1009
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001010 // Get the next item which will be the real data; Item will be the label
1011 QCBORItem LabelItem = *pDecodedItem;
1012 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1013 if(nReturn)
1014 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301016 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001017
1018 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1019 // strings are always good labels
1020 pDecodedItem->label.string = LabelItem.val.string;
1021 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1022 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
1023 // It's not a string and we only want strings, probably for easy translation to JSON
1024 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1025 goto Done;
1026 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1027 pDecodedItem->label.int64 = LabelItem.val.int64;
1028 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1029 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1030 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1031 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1032 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1033 pDecodedItem->label.string = LabelItem.val.string;
1034 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1035 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1036 } else {
1037 // label is not an int or a string. It is an arrray
1038 // or a float or such and this implementation doesn't handle that.
1039 // Also, tags on labels are ignored.
1040 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1041 goto Done;
1042 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001043 }
1044 } else {
1045 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1046 // Decoding a map as an array
1047 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1048 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001049 }
1050 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001051
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052Done:
1053 return nReturn;
1054}
1055
1056
1057/*
1058 Public function, see header qcbor.h file
1059 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001060QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001062 // Stack ptr/int: 2, QCBORItem : 64
1063
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301064 // The public entry point for fetching and parsing the next QCBORItem.
1065 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001066 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001068 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001069 if(nReturn) {
1070 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301072
1073 // Break ending arrays/maps are always processed at the end of this function.
1074 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301075 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301076 nReturn = QCBOR_ERR_BAD_BREAK;
1077 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301078 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundblade6de37062018-10-15 12:22:42 +05301080 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301081 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301082 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001083
Laurence Lundblade6de37062018-10-15 12:22:42 +05301084 // Process the item just received for descent or decrement, and
1085 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001086 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001087 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001088 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001089 // Maps and arrays do count in as items in the map/array that encloses
1090 // them so a decrement needs to be done for them too, but that is done
1091 // only when all the items in them have been processed, not when they
1092 // are opened.
1093 } else {
1094 // Decrement the count of items in the enclosing map/array
1095 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301096 // triggers a decrement in the map/array above that and
1097 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001098 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001099 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301100 if(nReturn) {
1101 goto Done;
1102 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001103
Laurence Lundblade6de37062018-10-15 12:22:42 +05301104 // For indefinite length maps/arrays, looking at any and
1105 // all breaks that might terminate them. The equivalent
1106 // for definite length maps/arrays happens in
1107 // DecodeNesting_DecrementCount().
1108 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1109 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1110 // Peek forward one item to see if it is a break.
1111 QCBORItem Peek;
1112 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1113 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1114 if(nReturn) {
1115 goto Done;
1116 }
1117 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1118 // It is not a break, rewind so it can be processed normally.
1119 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1120 break;
1121 }
1122 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301123 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301124 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1125 if(nReturn) {
1126 // break occured outside of an indefinite length array/map
1127 goto Done;
1128 }
1129 }
1130 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001131
Laurence Lundblade6de37062018-10-15 12:22:42 +05301132 // Tell the caller what level is next. This tells them what maps/arrays
1133 // were closed out and makes it possible for them to reconstruct
1134 // the tree with just the information returned by GetNext
1135 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001136
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001137Done:
1138 return nReturn;
1139}
1140
1141
Laurence Lundblade30816f22018-11-10 13:40:22 +07001142QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001143{
1144 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1145}
1146
1147
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001148/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301149 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301150 next one down. If a layer has no work to do for a particular item
1151 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001152
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301153 - QCBORDecode_GetNext -- The top layer manages the beginnings and
1154 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301155 out of maps/arrays. It processes all breaks that terminate
1156 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301158 - GetNext_MapEntry -- This handles the combining of two
1159 items, the label and the data, that make up a map entry.
1160 It only does work on maps. It combines the label and data
1161 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001162
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301163 - GetNext_TaggedItem -- This handles the type 6 tagged items.
1164 It accumulates all the tags and combines them with the following
1165 non-tagged item. If the tagged item is something that is understood
1166 like a date, the decoding of that item is invoked.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301168 - GetNext_FullItem -- This assembles the sub items that make up
1169 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301170 string allocater to create contiguous space for the item. It
1171 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001172
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301173 - GetNext_Item -- This gets and decodes the most atomic
1174 item in CBOR, the thing with an initial byte containing
1175 the major type.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001176
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001177 Roughly this takes 300 bytes of stack for vars. Need to
1178 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001179
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301180 */
1181
1182
1183/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001184 Public function, see header qcbor.h file
1185 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001186int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
1187{
1188 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001189
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001190 uint8_t uTagBitIndex;
1191 // Do not care about errors in pCallerConfiguredTagMap here. They are
1192 // caught during GetNext() before this is called.
1193 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1194 return 0;
1195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001196
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001197 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1198 return (uTagBit & pItem->uTagBits) != 0;
1199}
1200
1201
1202/*
1203 Public function, see header qcbor.h file
1204 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001205QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001206{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001207 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001208
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001209 // Error out if all the maps/arrays are not closed out
1210 if(DecodeNesting_IsNested(&(me->nesting))) {
1211 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1212 goto Done;
1213 }
1214
1215 // Error out if not all the bytes are consumed
1216 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1217 nReturn = QCBOR_ERR_EXTRA_BYTES;
1218 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001219
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001220Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301221 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001222 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001223 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001224
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001225 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001226}
1227
1228
1229
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001230/*
1231
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001232Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001233
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001234 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001235
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001236 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001237
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001238 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001239
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001240 - 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 -08001241
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001242 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001245
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001246 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001248 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001249
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001250 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001251
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001252 */
1253
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001254
1255
Laurence Lundbladef6531662018-12-04 10:42:22 +09001256
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001257/* ===========================================================================
1258 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001259
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001260 This implements a simple sting allocator for indefinite length
1261 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1262 implements the function type QCBORStringAllocate and allows easy
1263 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001264
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001265 This particular allocator is built-in for convenience. The caller
1266 can implement their own. All of this following code will get
1267 dead-stripped if QCBORDecode_SetMemPool() is not called.
1268
1269 This is a very primitive memory allocator. It does not track
1270 individual allocations, only a high-water mark. A free or
1271 reallocation must be of the last chunk allocated.
1272
1273 The size of the pool and offset to free memory are packed into the
1274 first 8 bytes of the memory pool so we don't have to keep them in
1275 the decode context. Since the address of the pool may not be
1276 aligned, they have to be packed and unpacked as if they were
1277 serialized data of the wire or such.
1278
1279 The sizes packed in are uint32_t to be the same on all CPU types
1280 and simplify the code.
1281 =========================================================================== */
1282
1283
1284static inline int MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
1285{
1286 // Use of UsefulInputBuf is overkill, but it is convenient.
1287 UsefulInputBuf UIB;
1288
1289 // Just assume the size here. It was checked during SetUp so the assumption is safe.
1290 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1291 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1292 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1293 return UsefulInputBuf_GetError(&UIB);
1294}
1295
1296
1297static inline int MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
1298{
1299 // Use of UsefulOutBuf is overkill, but convenient. The
1300 // length check performed here is useful.
1301 UsefulOutBuf UOB;
1302
1303 UsefulOutBuf_Init(&UOB, Pool);
1304 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1305 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1306 return UsefulOutBuf_GetError(&UOB);
1307}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001308
1309
1310/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001311 Internal function for an allocation, reallocation free and destuct.
1312
1313 Having only one function rather than one each per mode saves space in
1314 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001315
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001316 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1317 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001318static UsefulBuf MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001319{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001320 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001321
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001322 uint32_t uPoolSize;
1323 uint32_t uFreeOffset;
1324
1325 if(uNewSize > UINT32_MAX) {
1326 // This allocator is only good up to 4GB. This check should
1327 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1328 goto Done;
1329 }
1330 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1331
1332 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1333 goto Done;
1334 }
1335
1336 if(uNewSize) {
1337 if(pMem) {
1338 // REALLOCATION MODE
1339 // Calculate pointer to the end of the memory pool. It is
1340 // assumed that pPool + uPoolSize won't wrap around by
1341 // assuming the caller won't pass a pool buffer in that is
1342 // not in legitimate memory space.
1343 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1344
1345 // Check that the pointer for reallocation is in the range of the
1346 // pool. This also makes sure that pointer math further down
1347 // doesn't wrap under or over.
1348 if(pMem >= pPool && pMem < pPoolEnd) {
1349 // Offset to start of chunk for reallocation. This won't
1350 // wrap under because of check that pMem >= pPool. Cast
1351 // is safe because the pool is always less than UINT32_MAX
1352 // because of check in QCBORDecode_SetMemPool().
1353 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1354
1355 // Check to see if the allocation will fit. uPoolSize -
1356 // uMemOffset will not wrap under because of check that
1357 // pMem is in the range of the uPoolSize by check above.
1358 if(uNewSize <= uPoolSize - uMemOffset) {
1359 ReturnValue.ptr = pMem;
1360 ReturnValue.len = uNewSize;
1361
1362 // Addition won't wrap around over because uNewSize was
1363 // checked to be sure it is less than the pool size.
1364 uFreeOffset = uMemOffset + uNewSize32;
1365 }
1366 }
1367 } else {
1368 // ALLOCATION MODE
1369 // uPoolSize - uFreeOffset will not underflow because this
1370 // pool implementation makes sure uFreeOffset is always
1371 // smaller than uPoolSize through this check here and
1372 // reallocation case.
1373 if(uNewSize <= uPoolSize - uFreeOffset) {
1374 ReturnValue.len = uNewSize;
1375 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
1376 uFreeOffset += uNewSize;
1377 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001378 }
1379 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001380 if(pMem) {
1381 // FREE MODE
1382 // Cast is safe because of limit on pool size in
1383 // QCBORDecode_SetMemPool()
1384 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1385 } else {
1386 // DESTRUCT MODE
1387 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001388 }
1389 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001390
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001391 UsefulBuf Pool = {pPool, uPoolSize};
1392 MemPool_Pack(Pool, uFreeOffset);
1393
1394Done:
1395 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001396}
1397
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001398
Laurence Lundbladef6531662018-12-04 10:42:22 +09001399/*
1400 Public function, see header qcbor.h file
1401 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001402QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001403{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001404 // The pool size and free mem offset are packed into the beginning
1405 // of the pool memory. This compile time check make sure the
1406 // constant in the header is correct. This check should optimize
1407 // down to nothing.
1408 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001409 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001410 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001411
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001412 // The pool size and free offset packed in to the beginning of pool
1413 // memory are only 32-bits. This check will optimize out on 32-bit
1414 // machines.
1415 if(Pool.len > UINT32_MAX) {
1416 return QCBOR_ERR_BUFFER_TOO_LARGE;
1417 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001418
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001419 // This checks that the pool buffer given is big enough.
1420 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1421 return QCBOR_ERR_BUFFER_TOO_SMALL;
1422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001423
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001424 pMe->StringAllocator.pfAllocator = MemPool_Function;
1425 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1426 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001427
Laurence Lundblade30816f22018-11-10 13:40:22 +07001428 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001429}