blob: 079e77d0abf2677fb893370d328d6a276867b5a3 [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
568 nReturn = QCBOR_ERR_INVALID_CBOR;
569 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.
742 if(nReturn)
743 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530745 memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800746
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700747 // At this point the major type and the value are valid. We've got the type and the number that
748 // starts every CBOR data item.
749 switch (uMajorType) {
750 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
751 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
752 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
753 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
756 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
757 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
758 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530759 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700760 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800761 nReturn = DecodeBytes(pAllocator, uMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700762 }
763 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800764
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700765 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
766 case CBOR_MAJOR_TYPE_MAP: // Major type 5
767 // Record the number of items in the array or map
768 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
769 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
770 goto Done;
771 }
772 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530773 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700774 } else {
775 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
776 }
777 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
778 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800779
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700780 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700781 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700782 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
783 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800784
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
786 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
787 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
790 nReturn = QCBOR_ERR_UNSUPPORTED;
791 break;
792 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794Done:
795 return nReturn;
796}
797
798
799
800/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800801 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700802 individual chunk items together into one QCBORItem using the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530803 string allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800804
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530805 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700806 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700807static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700808{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700809 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700810 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800811 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
812 &(me->StringAllocator) :
813 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530814 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800815
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800816 nReturn = GetNext_Item(&(me->InBuf),
817 pDecodedItem,
818 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700819 if(nReturn) {
820 goto Done;
821 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700823 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530824 // code in this function from here down can be eliminated. Run tests, except
825 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800827 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700828 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
829 goto Done; // no need to do any work here on non-string types
830 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800832 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530833 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800834 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700835 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530837 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800838 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700839 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
840 goto Done;
841 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800842
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800844 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700847 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700849 // Get item for next chunk
850 QCBORItem StringChunkItem;
851 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800852 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, pAllocator);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700854 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700855 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800856
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530857 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700858 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800859 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530861 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700862 break;
863 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800864
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700865 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530866 // Also catches error of other non-string types that don't belong.
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700867 if(StringChunkItem.uDataType != uStringType) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700868 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 break;
870 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800873 // The first time throurgh FullString.ptr is NULL and this is
874 // equivalent to StringAllocator_Allocate()
875 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
876 UNCONST_POINTER(FullString.ptr),
877 FullString.len + StringChunkItem.val.string.len);
878
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700879 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530880 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700881 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 break;
883 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800884
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700885 // Copy new string chunk at the end of string so far.
886 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800888
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800890 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
891 // Getting the item failed, clean up the allocated memory
892 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800894
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700895 return nReturn;
896}
897
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898
899/*
900 Returns an error if there was something wrong with the optional item or it couldn't
901 be handled.
902 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700903static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700904{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700905 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700906 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700907 uint64_t uTagBits = 0;
908 if(pTags) {
909 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700911
912 for(;;) {
913 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700914 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700915 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800917
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700918 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
919 // Successful exit from loop; maybe got some tags, maybe not
920 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921 break;
922 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800923
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700924 uint8_t uTagBitIndex;
925 // Tag was mapped, tag was not mapped, error with tag list
926 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700928 case QCBOR_SUCCESS:
929 // Successfully mapped the tag
930 uTagBits |= 0x01ULL << uTagBitIndex;
931 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700933 case QCBOR_ERR_BAD_OPT_TAG:
934 // Tag is not recognized. Do nothing
935 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700937 default:
938 // Error Condition
939 goto Done;
940 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700942 if(pTags) {
943 // Caller wants all tags recorded in the provided buffer
944 if(pTags->uNumUsed >= pTags->uNumAllocated) {
945 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
946 goto Done;
947 }
948 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
949 pTags->uNumUsed++;
950 }
951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700953 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700954 case 0:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700955 // No tags at all or none we know about. Nothing to do.
956 // This is part of the pass-through path of this function
957 // that will mostly be taken when decoding any item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800959
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700960 case QCBOR_TAGFLAG_DATE_STRING:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700961 nReturn = DecodeDateString(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700962 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800963
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700964 case QCBOR_TAGFLAG_DATE_EPOCH:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700965 nReturn = DecodeDateEpoch(pDecodedItem);
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_POS_BIGNUM:
969 case QCBOR_TAGFLAG_NEG_BIGNUM:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700970 nReturn = DecodeBigNum(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 default:
974 // Encountering some mixed up CBOR like something that
975 // is tagged as both a string and integer date.
Laurence Lundblade30816f22018-11-10 13:40:22 +0700976 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700977 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800978
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700979Done:
980 return nReturn;
981}
982
983
984/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800985 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700986 */
Laurence Lundblade30816f22018-11-10 13:40:22 +0700987static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700988{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700989 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700990 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700991 if(nReturn)
992 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800993
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800994 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700995 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800996 goto Done;
997 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800999 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1000 // In a map and caller wants maps decoded, not treated as arrays
1001
1002 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1003 // If in a map and the right decoding mode, get the label
1004
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001005 // Get the next item which will be the real data; Item will be the label
1006 QCBORItem LabelItem = *pDecodedItem;
1007 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1008 if(nReturn)
1009 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301011 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001012
1013 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1014 // strings are always good labels
1015 pDecodedItem->label.string = LabelItem.val.string;
1016 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1017 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
1018 // It's not a string and we only want strings, probably for easy translation to JSON
1019 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1020 goto Done;
1021 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1022 pDecodedItem->label.int64 = LabelItem.val.int64;
1023 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1024 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1025 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1026 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1027 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1028 pDecodedItem->label.string = LabelItem.val.string;
1029 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1030 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1031 } else {
1032 // label is not an int or a string. It is an arrray
1033 // or a float or such and this implementation doesn't handle that.
1034 // Also, tags on labels are ignored.
1035 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1036 goto Done;
1037 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001038 }
1039 } else {
1040 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1041 // Decoding a map as an array
1042 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1043 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001044 }
1045 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001046
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047Done:
1048 return nReturn;
1049}
1050
1051
1052/*
1053 Public function, see header qcbor.h file
1054 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001055QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001056{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001057 // Stack ptr/int: 2, QCBORItem : 64
1058
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301059 // The public entry point for fetching and parsing the next QCBORItem.
1060 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001061 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001063 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001064 if(nReturn) {
1065 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301067
1068 // Break ending arrays/maps are always processed at the end of this function.
1069 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301070 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301071 nReturn = QCBOR_ERR_BAD_BREAK;
1072 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade6de37062018-10-15 12:22:42 +05301075 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301076 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301077 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundblade6de37062018-10-15 12:22:42 +05301079 // Process the item just received for descent or decrement, and
1080 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001081 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001082 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001083 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001084 // Maps and arrays do count in as items in the map/array that encloses
1085 // them so a decrement needs to be done for them too, but that is done
1086 // only when all the items in them have been processed, not when they
1087 // are opened.
1088 } else {
1089 // Decrement the count of items in the enclosing map/array
1090 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301091 // triggers a decrement in the map/array above that and
1092 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001093 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001094 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301095 if(nReturn) {
1096 goto Done;
1097 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001098
Laurence Lundblade6de37062018-10-15 12:22:42 +05301099 // For indefinite length maps/arrays, looking at any and
1100 // all breaks that might terminate them. The equivalent
1101 // for definite length maps/arrays happens in
1102 // DecodeNesting_DecrementCount().
1103 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1104 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1105 // Peek forward one item to see if it is a break.
1106 QCBORItem Peek;
1107 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1108 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1109 if(nReturn) {
1110 goto Done;
1111 }
1112 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1113 // It is not a break, rewind so it can be processed normally.
1114 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1115 break;
1116 }
1117 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301118 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301119 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1120 if(nReturn) {
1121 // break occured outside of an indefinite length array/map
1122 goto Done;
1123 }
1124 }
1125 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001126
Laurence Lundblade6de37062018-10-15 12:22:42 +05301127 // Tell the caller what level is next. This tells them what maps/arrays
1128 // were closed out and makes it possible for them to reconstruct
1129 // the tree with just the information returned by GetNext
1130 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001131
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001132Done:
1133 return nReturn;
1134}
1135
1136
Laurence Lundblade30816f22018-11-10 13:40:22 +07001137QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001138{
1139 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1140}
1141
1142
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001143/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301144 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301145 next one down. If a layer has no work to do for a particular item
1146 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001147
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301148 - QCBORDecode_GetNext -- The top layer manages the beginnings and
1149 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301150 out of maps/arrays. It processes all breaks that terminate
1151 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001152
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301153 - GetNext_MapEntry -- This handles the combining of two
1154 items, the label and the data, that make up a map entry.
1155 It only does work on maps. It combines the label and data
1156 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301158 - GetNext_TaggedItem -- This handles the type 6 tagged items.
1159 It accumulates all the tags and combines them with the following
1160 non-tagged item. If the tagged item is something that is understood
1161 like a date, the decoding of that item is invoked.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001162
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301163 - GetNext_FullItem -- This assembles the sub items that make up
1164 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301165 string allocater to create contiguous space for the item. It
1166 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301168 - GetNext_Item -- This gets and decodes the most atomic
1169 item in CBOR, the thing with an initial byte containing
1170 the major type.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001171
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001172 Roughly this takes 300 bytes of stack for vars. Need to
1173 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301175 */
1176
1177
1178/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179 Public function, see header qcbor.h file
1180 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001181int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
1182{
1183 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001184
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001185 uint8_t uTagBitIndex;
1186 // Do not care about errors in pCallerConfiguredTagMap here. They are
1187 // caught during GetNext() before this is called.
1188 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1189 return 0;
1190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001192 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1193 return (uTagBit & pItem->uTagBits) != 0;
1194}
1195
1196
1197/*
1198 Public function, see header qcbor.h file
1199 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001200QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001201{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001202 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001204 // Error out if all the maps/arrays are not closed out
1205 if(DecodeNesting_IsNested(&(me->nesting))) {
1206 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1207 goto Done;
1208 }
1209
1210 // Error out if not all the bytes are consumed
1211 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1212 nReturn = QCBOR_ERR_EXTRA_BYTES;
1213 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001214
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001215Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301216 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001217 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001218 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001219
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001220 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001221}
1222
1223
1224
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001225/*
1226
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001227Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001229 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001230
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001231 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001232
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001233 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001234
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001235 - 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 -08001236
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001237 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001238
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001239 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001240
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001241 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001243 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001245 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001246
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247 */
1248
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001249
1250
Laurence Lundbladef6531662018-12-04 10:42:22 +09001251
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001252/* ===========================================================================
1253 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001254
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001255 This implements a simple sting allocator for indefinite length
1256 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1257 implements the function type QCBORStringAllocate and allows easy
1258 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001259
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001260 This particular allocator is built-in for convenience. The caller
1261 can implement their own. All of this following code will get
1262 dead-stripped if QCBORDecode_SetMemPool() is not called.
1263
1264 This is a very primitive memory allocator. It does not track
1265 individual allocations, only a high-water mark. A free or
1266 reallocation must be of the last chunk allocated.
1267
1268 The size of the pool and offset to free memory are packed into the
1269 first 8 bytes of the memory pool so we don't have to keep them in
1270 the decode context. Since the address of the pool may not be
1271 aligned, they have to be packed and unpacked as if they were
1272 serialized data of the wire or such.
1273
1274 The sizes packed in are uint32_t to be the same on all CPU types
1275 and simplify the code.
1276 =========================================================================== */
1277
1278
1279static inline int MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
1280{
1281 // Use of UsefulInputBuf is overkill, but it is convenient.
1282 UsefulInputBuf UIB;
1283
1284 // Just assume the size here. It was checked during SetUp so the assumption is safe.
1285 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1286 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1287 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1288 return UsefulInputBuf_GetError(&UIB);
1289}
1290
1291
1292static inline int MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
1293{
1294 // Use of UsefulOutBuf is overkill, but convenient. The
1295 // length check performed here is useful.
1296 UsefulOutBuf UOB;
1297
1298 UsefulOutBuf_Init(&UOB, Pool);
1299 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1300 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1301 return UsefulOutBuf_GetError(&UOB);
1302}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303
1304
1305/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001306 Internal function for an allocation, reallocation free and destuct.
1307
1308 Having only one function rather than one each per mode saves space in
1309 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001310
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001311 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1312 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001313static UsefulBuf MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001314{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001315 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001316
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001317 uint32_t uPoolSize;
1318 uint32_t uFreeOffset;
1319
1320 if(uNewSize > UINT32_MAX) {
1321 // This allocator is only good up to 4GB. This check should
1322 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1323 goto Done;
1324 }
1325 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1326
1327 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1328 goto Done;
1329 }
1330
1331 if(uNewSize) {
1332 if(pMem) {
1333 // REALLOCATION MODE
1334 // Calculate pointer to the end of the memory pool. It is
1335 // assumed that pPool + uPoolSize won't wrap around by
1336 // assuming the caller won't pass a pool buffer in that is
1337 // not in legitimate memory space.
1338 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1339
1340 // Check that the pointer for reallocation is in the range of the
1341 // pool. This also makes sure that pointer math further down
1342 // doesn't wrap under or over.
1343 if(pMem >= pPool && pMem < pPoolEnd) {
1344 // Offset to start of chunk for reallocation. This won't
1345 // wrap under because of check that pMem >= pPool. Cast
1346 // is safe because the pool is always less than UINT32_MAX
1347 // because of check in QCBORDecode_SetMemPool().
1348 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1349
1350 // Check to see if the allocation will fit. uPoolSize -
1351 // uMemOffset will not wrap under because of check that
1352 // pMem is in the range of the uPoolSize by check above.
1353 if(uNewSize <= uPoolSize - uMemOffset) {
1354 ReturnValue.ptr = pMem;
1355 ReturnValue.len = uNewSize;
1356
1357 // Addition won't wrap around over because uNewSize was
1358 // checked to be sure it is less than the pool size.
1359 uFreeOffset = uMemOffset + uNewSize32;
1360 }
1361 }
1362 } else {
1363 // ALLOCATION MODE
1364 // uPoolSize - uFreeOffset will not underflow because this
1365 // pool implementation makes sure uFreeOffset is always
1366 // smaller than uPoolSize through this check here and
1367 // reallocation case.
1368 if(uNewSize <= uPoolSize - uFreeOffset) {
1369 ReturnValue.len = uNewSize;
1370 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
1371 uFreeOffset += uNewSize;
1372 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001373 }
1374 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001375 if(pMem) {
1376 // FREE MODE
1377 // Cast is safe because of limit on pool size in
1378 // QCBORDecode_SetMemPool()
1379 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1380 } else {
1381 // DESTRUCT MODE
1382 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001383 }
1384 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001385
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001386 UsefulBuf Pool = {pPool, uPoolSize};
1387 MemPool_Pack(Pool, uFreeOffset);
1388
1389Done:
1390 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001391}
1392
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001393
Laurence Lundbladef6531662018-12-04 10:42:22 +09001394/*
1395 Public function, see header qcbor.h file
1396 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001397QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001398{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001399 // The pool size and free mem offset are packed into the beginning
1400 // of the pool memory. This compile time check make sure the
1401 // constant in the header is correct. This check should optimize
1402 // down to nothing.
1403 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001404 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001405 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001406
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001407 // The pool size and free offset packed in to the beginning of pool
1408 // memory are only 32-bits. This check will optimize out on 32-bit
1409 // machines.
1410 if(Pool.len > UINT32_MAX) {
1411 return QCBOR_ERR_BUFFER_TOO_LARGE;
1412 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001413
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001414 // This checks that the pool buffer given is big enough.
1415 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1416 return QCBOR_ERR_BUFFER_TOO_SMALL;
1417 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001418
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001419 pMe->StringAllocator.pfAllocator = MemPool_Function;
1420 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1421 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001422
Laurence Lundblade30816f22018-11-10 13:40:22 +07001423 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001424}