blob: 26bc3f67cef9a708db14445b68797a6f06a8021e [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 Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, 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 Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundbladeee851742020-01-08 08:37:05 -080033/*==============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070034 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 Lundbladeee851742020-01-08 08:37:05 -080043 when who what, where, why
44 -------- ---- ---------------------------------------------------
45 01/08/2020 llundblade Documentation corrections & improved code formatting.
46 12/30/19 llundblade Add support for decimal fractions and bigfloats.
47 11/07/19 llundblade Fix long long conversion to double compiler warning
48 09/07/19 llundblade Fix bug decoding empty arrays and maps
49 07/31/19 llundblade Decode error fixes for some not-well-formed CBOR
50 07/31/19 llundblade New error code for better end of data handling
51 02/17/19 llundblade Fixed: QCBORItem.u{Data|Label}Alloc when
52 bAllStrings set
53 02/16/19 llundblade Redesign MemPool to fix memory access alignment bug
54 01/10/19 llundblade Clever type and argument decoder; 250 bytes smaller
55 11/9/18 llundblade Error codes are now enums.
56 11/2/18 llundblade Simplify float decoding and align with preferred
57 float encoding
58 10/31/18 llundblade Switch to one license that is almost BSD-3.
59 10/28/18 llundblade Reworked tag decoding
60 10/15/18 llundblade Indefinite length maps and arrays supported
61 10/8/18 llundblade Indefinite length strings supported
62 02/04/17 llundbla Work on CPUs that don's require pointer alignment
63 by making use of changes in UsefulBuf
64 03/01/17 llundbla More data types; decoding improvements and fixes
65 11/13/16 llundbla Integrate most TZ changes back into github version.
66 09/30/16 gkanike Porting to TZ.
67 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080068
Laurence Lundbladeee851742020-01-08 08:37:05 -080069 =============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070070
71#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070072#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070073
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053075/*
76 This casts away the const-ness of a pointer, usually so it can be
77 freed or realloced.
78 */
79#define UNCONST_POINTER(ptr) ((void *)(ptr))
80
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070081
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070082
Laurence Lundbladeee851742020-01-08 08:37:05 -080083/*===========================================================================
84 DecodeNesting -- Functions for tracking array/map nesting when decoding
85
86 See qcbor.h for definition of the object used here: QCBORDecodeNesting
87 ===========================================================================*/
88
89inline static int
90IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070091{
92 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
93}
94
Laurence Lundbladeee851742020-01-08 08:37:05 -080095inline static int
96DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097{
98 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
99}
100
Laurence Lundbladeee851742020-01-08 08:37:05 -0800101inline static int
102DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700103{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700104 return pNesting->pCurrent->uCount == UINT16_MAX;
105}
106
Laurence Lundbladeee851742020-01-08 08:37:05 -0800107inline static uint8_t
108DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800109{
110 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
111}
112
Laurence Lundbladeee851742020-01-08 08:37:05 -0800113inline static int
114DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700116 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700117 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700118 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800119
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700120 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
121}
122
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800123// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800124inline static QCBORError
125DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700126{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800127 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700128 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800129 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700130 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800131
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800132 // breaks can only occur when the map/array is indefinite length
133 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
134 return QCBOR_ERR_BAD_BREAK;
135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800137 // if all OK, the break reduces the level of nesting
138 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800139
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800140 return QCBOR_SUCCESS;
141}
142
Laurence Lundbladeee851742020-01-08 08:37:05 -0800143// Called on every single item except breaks including open of a map/array
144inline static void
145DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800146{
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700147 while(DecodeNesting_IsNested(pNesting)) {
148 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800149
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800150 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700151 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800152 pNesting->pCurrent->uCount--;
153 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700154
155 if(pNesting->pCurrent->uCount != 0) {
156 // Did not close out an array or map, so nothing further
157 break;
158 }
159
160 // Closed out an array or map so level up
161 pNesting->pCurrent--;
162
163 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164 }
165}
166
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800167// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800168inline static QCBORError
169DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700171 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800172
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800173 if(pItem->val.uCount == 0) {
174 // Nothing to do for empty definite lenth arrays. They are just are
175 // effectively the same as an item that is not a map or array
176 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530177 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800179
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800180 // Error out if arrays is too long to handle
181 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700182 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
183 goto Done;
184 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800185
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800186 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700187 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
188 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
189 goto Done;
190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700193 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800194
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800195 // Record a few details for this nesting level
196 pNesting->pCurrent->uMajorType = pItem->uDataType;
197 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800198
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700199Done:
200 return nReturn;;
201}
202
Laurence Lundbladeee851742020-01-08 08:37:05 -0800203inline static void
204DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700205{
206 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
207}
208
209
210
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700211/*
212 This list of built-in tags. Only add tags here that are
213 clearly established and useful. Once a tag is added here
214 it can't be taken out as that would break backwards compatibility.
215 There are only 48 slots available forever.
216 */
217static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800218 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
219 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
220 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
221 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
222 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
223 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700224 CBOR_TAG_COSE_ENCRYPTO,
225 CBOR_TAG_COSE_MAC0,
226 CBOR_TAG_COSE_SIGN1,
227 CBOR_TAG_ENC_AS_B64URL,
228 CBOR_TAG_ENC_AS_B64,
229 CBOR_TAG_ENC_AS_B16,
230 CBOR_TAG_CBOR,
231 CBOR_TAG_URI,
232 CBOR_TAG_B64URL,
233 CBOR_TAG_B64,
234 CBOR_TAG_REGEX,
235 CBOR_TAG_MIME,
236 CBOR_TAG_BIN_UUID,
237 CBOR_TAG_CWT,
238 CBOR_TAG_ENCRYPT,
239 CBOR_TAG_MAC,
240 CBOR_TAG_SIGN,
241 CBOR_TAG_GEO_COORD,
242 CBOR_TAG_CBOR_MAGIC
243};
244
245// This is used in a bit of cleverness in GetNext_TaggedItem() to
246// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800247// these types. This will break if the first six items in
248// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
249// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
250#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
251#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
252#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
253#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
254#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
255#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700256
Laurence Lundblade59289e52019-12-30 13:44:37 -0800257#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
258 QCBOR_TAGFLAG_DATE_EPOCH |\
259 QCBOR_TAGFLAG_POS_BIGNUM |\
260 QCBOR_TAGFLAG_NEG_BIGNUM |\
261 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
262 QCBOR_TAGFLAG_BIGFLOAT)
263
264#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
265 QCBOR_TAGFLAG_DATE_EPOCH |\
266 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700267 QCBOR_TAGFLAG_NEG_BIGNUM)
268
269#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
270#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
271#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
272
273static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
274{
275 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800276 /*
277 This is a cross-check to make sure the above array doesn't
278 accidentally get made too big. In normal conditions the above
279 test should optimize out as all the values are known at compile
280 time.
281 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700282 return -1;
283 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800284
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700285 if(uTag > UINT16_MAX) {
286 // This tag map works only on 16-bit tags
287 return -1;
288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700290 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
291 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
292 return nTagBitIndex;
293 }
294 }
295 return -1; // Indicates no match
296}
297
298static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
299{
300 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
301 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
302 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
303 }
304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700306 return -1; // Indicates no match
307}
308
309/*
310 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800311
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700312 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800313 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700314 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800315static QCBORError
316TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
317 uint64_t uTag,
318 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700319{
320 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
321 if(nTagBitIndex >= 0) {
322 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
323 *puTagBitIndex = (uint8_t)nTagBitIndex;
324 return QCBOR_SUCCESS;
325 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800326
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700327 if(pCallerConfiguredTagMap) {
328 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
329 return QCBOR_ERR_TOO_MANY_TAGS;
330 }
331 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
332 if(nTagBitIndex >= 0) {
333 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
334
335 *puTagBitIndex = (uint8_t)nTagBitIndex;
336 return QCBOR_SUCCESS;
337 }
338 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800339
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700340 return QCBOR_ERR_BAD_OPT_TAG;
341}
342
343
344
Laurence Lundbladeee851742020-01-08 08:37:05 -0800345/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800346 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
347
348 The following four functions are pretty wrappers for invocation of
349 the string allocator supplied by the caller.
350
Laurence Lundbladeee851742020-01-08 08:37:05 -0800351 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800352
Laurence Lundbladeee851742020-01-08 08:37:05 -0800353static inline void
354StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800355{
356 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
357}
358
Laurence Lundbladeee851742020-01-08 08:37:05 -0800359// StringAllocator_Reallocate called with pMem NULL is
360// equal to StringAllocator_Allocate()
361static inline UsefulBuf
362StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
363 void *pMem,
364 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800365{
366 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
367}
368
Laurence Lundbladeee851742020-01-08 08:37:05 -0800369static inline UsefulBuf
370StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800371{
372 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
373}
374
Laurence Lundbladeee851742020-01-08 08:37:05 -0800375static inline void
376StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800377{
378 if(pMe->pfAllocator) {
379 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
380 }
381}
382
383
384
Laurence Lundbladeee851742020-01-08 08:37:05 -0800385/*===========================================================================
386 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700387
Laurence Lundbladeee851742020-01-08 08:37:05 -0800388 See qcbor.h for definition of the object used here: QCBORDecodeContext
389 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700390/*
391 Public function, see header file
392 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800393void QCBORDecode_Init(QCBORDecodeContext *me,
394 UsefulBufC EncodedCBOR,
395 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700396{
397 memset(me, 0, sizeof(QCBORDecodeContext));
398 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800399 // Don't bother with error check on decode mode. If a bad value is
400 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700401 me->uDecodeMode = nDecodeMode;
402 DecodeNesting_Init(&(me->nesting));
403}
404
405
406/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700407 Public function, see header file
408 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800409void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
410 QCBORStringAllocate pfAllocateFunction,
411 void *pAllocateContext,
412 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700413{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800414 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
415 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
416 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700417}
418
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800419
420/*
421 Public function, see header file
422 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800423void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
424 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700425{
426 me->pCallerConfiguredTagList = pTagList;
427}
428
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700429
430/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800431 This decodes the fundamental part of a CBOR data item, the type and
432 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800433
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800435
Laurence Lundbladeee851742020-01-08 08:37:05 -0800436 This does the network->host byte order conversion. The conversion
437 here also results in the conversion for floats in addition to that
438 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800439
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700440 This returns:
441 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800442
443 puNumber -- the "number" which is used a the value for integers,
444 tags and floats and length for strings and arrays
445
446 puAdditionalInfo -- Pass this along to know what kind of float or
447 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800448
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700449 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800450inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
451 int *pnMajorType,
452 uint64_t *puArgument,
453 uint8_t *puAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700454{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700455 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800456
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700457 // Get the initial byte that every CBOR data item has
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800458 const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700460 // Break down the initial byte
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800461 const uint8_t uTmpMajorType = uInitialByte >> 5;
462 const uint8_t uAdditionalInfo = uInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800463
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800464 // Where the number or argument accumulates
465 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800466
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800467 if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800468 // Need to get 1,2,4 or 8 additional argument bytes Map
469 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800470 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800471
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800472 // Loop getting all the bytes in the argument
473 uArgument = 0;
474 for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
475 // This shift and add gives the endian conversion
476 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
477 }
478 } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) {
479 // The reserved and thus-far unused additional info values
480 nReturn = QCBOR_ERR_UNSUPPORTED;
481 goto Done;
482 } else {
483 // Less than 24, additional info is argument or 31, an indefinite length
484 // No more bytes to get
485 uArgument = uAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700486 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800487
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700488 if(UsefulInputBuf_GetError(pUInBuf)) {
489 nReturn = QCBOR_ERR_HIT_END;
490 goto Done;
491 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800492
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700493 // All successful if we got here.
494 nReturn = QCBOR_SUCCESS;
495 *pnMajorType = uTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800496 *puArgument = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700497 *puAdditionalInfo = uAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800498
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700499Done:
500 return nReturn;
501}
502
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700503/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800504 CBOR doesn't explicitly specify two's compliment for integers but all
505 CPUs use it these days and the test vectors in the RFC are so. All
506 integers in the CBOR structure are positive and the major type
507 indicates positive or negative. CBOR can express positive integers
508 up to 2^x - 1 where x is the number of bits and negative integers
509 down to 2^x. Note that negative numbers can be one more away from
510 zero than positive. Stdint, as far as I can tell, uses two's
511 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800512
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700513 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
514 used here in any way including in the interface
515 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516inline static QCBORError
517DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700518{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700519 // Stack usage: int/ptr 1 -- 8
Laurence Lundblade30816f22018-11-10 13:40:22 +0700520 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800521
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700522 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
523 if (uNumber <= INT64_MAX) {
524 pDecodedItem->val.int64 = (int64_t)uNumber;
525 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800526
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700527 } else {
528 pDecodedItem->val.uint64 = uNumber;
529 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531 }
532 } else {
533 if(uNumber <= INT64_MAX) {
534 pDecodedItem->val.int64 = -uNumber-1;
535 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800536
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700537 } else {
538 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000539 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 nReturn = QCBOR_ERR_INT_OVERFLOW;
541 }
542 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800543
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544 return nReturn;
545}
546
547// Make sure #define value line up as DecodeSimple counts on this.
548#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
549#error QCBOR_TYPE_FALSE macro value wrong
550#endif
551
552#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
553#error QCBOR_TYPE_TRUE macro value wrong
554#endif
555
556#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
557#error QCBOR_TYPE_NULL macro value wrong
558#endif
559
560#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
561#error QCBOR_TYPE_UNDEF macro value wrong
562#endif
563
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700564#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
565#error QCBOR_TYPE_BREAK macro value wrong
566#endif
567
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
569#error QCBOR_TYPE_DOUBLE macro value wrong
570#endif
571
572#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
573#error QCBOR_TYPE_FLOAT macro value wrong
574#endif
575
576/*
577 Decode true, false, floats, break...
578 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579inline static QCBORError
580DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700581{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700582 // Stack usage: 0
Laurence Lundblade30816f22018-11-10 13:40:22 +0700583 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800584
Laurence Lundbladeee851742020-01-08 08:37:05 -0800585 // uAdditionalInfo is 5 bits from the initial byte compile time checks
586 // above make sure uAdditionalInfo values line up with uDataType values
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700587 pDecodedItem->uDataType = uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800588
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700589 switch(uAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
591 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800592
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700593 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700594 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
595 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700596 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700597 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700598 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
599 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700600 break;
601 case DOUBLE_PREC_FLOAT:
602 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700603 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700604 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700606 case CBOR_SIMPLEV_FALSE: // 20
607 case CBOR_SIMPLEV_TRUE: // 21
608 case CBOR_SIMPLEV_NULL: // 22
609 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700610 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700611 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613 case CBOR_SIMPLEV_ONEBYTE: // 24
614 if(uNumber <= CBOR_SIMPLE_BREAK) {
615 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700616 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617 goto Done;
618 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800619 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622 default: // 0-19
623 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800624 /*
625 DecodeTypeAndNumber will make uNumber equal to
626 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
627 safe because the 2, 4 and 8 byte lengths of uNumber are in
628 the double/float cases above
629 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700630 pDecodedItem->val.uSimple = (uint8_t)uNumber;
631 break;
632 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634Done:
635 return nReturn;
636}
637
638
639
640/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530641 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800643inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
644 int nMajorType,
645 uint64_t uStrLen,
646 UsefulInputBuf *pUInBuf,
647 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700648{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700649 // Stack usage: UsefulBuf 2, int/ptr 1 40
Laurence Lundblade30816f22018-11-10 13:40:22 +0700650 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800651
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800652 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530653 if(UsefulBuf_IsNULLC(Bytes)) {
654 // Failed to get the bytes for this string item
655 nReturn = QCBOR_ERR_HIT_END;
656 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700657 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530658
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530660 // We are asked to use string allocator to make a copy
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800661 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530662 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700663 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530664 goto Done;
665 }
666 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800667 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530668 } else {
669 // Normal case with no string allocator
670 pDecodedItem->val.string = Bytes;
671 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800672 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
673 pDecodedItem->uDataType = bIsBstr ? QCBOR_TYPE_BYTE_STRING
674 : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800675
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530676Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700677 return nReturn;
678}
679
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682
683
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700684
685
Laurence Lundbladeee851742020-01-08 08:37:05 -0800686// Make sure the constants align as this is assumed by
687// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700688#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
689#error QCBOR_TYPE_ARRAY value not lined up with major type
690#endif
691#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
692#error QCBOR_TYPE_MAP value not lined up with major type
693#endif
694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800696 This gets a single data item and decodes it including preceding
697 optional tagging. This does not deal with arrays and maps and nesting
698 except to decode the data item introducing them. Arrays and maps are
699 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeee851742020-01-08 08:37:05 -0800701 Errors detected here include: an array that is too long to decode,
702 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700703 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800704static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
705 QCBORItem *pDecodedItem,
706 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700707{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700708 // Stack usage: int/ptr 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700709 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800710
Laurence Lundbladeee851742020-01-08 08:37:05 -0800711 /*
712 Get the major type and the number. Number could be length of more
713 bytes or the value depending on the major type nAdditionalInfo is
714 an encoding of the length of the uNumber and is needed to decode
715 floats and doubles
716 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700717 int uMajorType;
718 uint64_t uNumber;
719 uint8_t uAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800720
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700721 memset(pDecodedItem, 0, sizeof(QCBORItem));
722
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700723 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800724
Laurence Lundbladeee851742020-01-08 08:37:05 -0800725 // Error out here if we got into trouble on the type and number. The
726 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700727 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700728 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700729 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800730
Laurence Lundbladeee851742020-01-08 08:37:05 -0800731 // At this point the major type and the value are valid. We've got
732 // the type and the number that starts every CBOR data item.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700733 switch (uMajorType) {
734 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
735 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700736 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
737 nReturn = QCBOR_ERR_BAD_INT;
738 } else {
739 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
740 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700741 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800742
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700743 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
744 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
745 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800746 const bool bIsBstr = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
747 pDecodedItem->uDataType = bIsBstr ? QCBOR_TYPE_BYTE_STRING
748 : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530749 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700750 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800751 nReturn = DecodeBytes(pAllocator, uMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700752 }
753 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
756 case CBOR_MAJOR_TYPE_MAP: // Major type 5
757 // Record the number of items in the array or map
758 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
759 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
760 goto Done;
761 }
762 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530763 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800765 // type conversion OK because of check above
766 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700767 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800768 // C preproc #if above makes sure constants for major types align
769 pDecodedItem->uDataType = uMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700770 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800771
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700772 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700773 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
774 nReturn = QCBOR_ERR_BAD_INT;
775 } else {
776 pDecodedItem->val.uTagV = uNumber;
777 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
778 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800780
Laurence Lundbladeee851742020-01-08 08:37:05 -0800781 case CBOR_MAJOR_TYPE_SIMPLE:
782 // Major type 7, float, double, true, false, null...
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700783 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
784 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800785
Laurence Lundbladeee851742020-01-08 08:37:05 -0800786 default:
787 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 nReturn = QCBOR_ERR_UNSUPPORTED;
789 break;
790 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792Done:
793 return nReturn;
794}
795
796
797
798/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800799 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800800 individual chunk items together into one QCBORItem using the string
801 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530803 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700804 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800805static inline QCBORError
806GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700807{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700808 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700809 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800810 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
811 &(me->StringAllocator) :
812 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530813 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800814
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800815 nReturn = GetNext_Item(&(me->InBuf),
816 pDecodedItem,
817 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700818 if(nReturn) {
819 goto Done;
820 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700822 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530823 // code in this function from here down can be eliminated. Run tests, except
824 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800825
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800826 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700827 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
828 goto Done; // no need to do any work here on non-string types
829 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800830
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800831 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530832 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800833 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530836 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800837 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700838 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
839 goto Done;
840 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800843 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800845
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700846 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700847 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700848 // Get item for next chunk
849 QCBORItem StringChunkItem;
850 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800851 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700853 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700854 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800855
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530856 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700857 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800858 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700859 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530860 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 break;
862 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800863
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700864 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530865 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700866 // Also catches indefinite length strings inside indefinite length strings
867 if(StringChunkItem.uDataType != uStringType || StringChunkItem.val.string.len == SIZE_MAX) {
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/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800900 Gets all optional tag data items preceding a data item that is not an
901 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700902 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800903static QCBORError
904GetNext_TaggedItem(QCBORDecodeContext *me,
905 QCBORItem *pDecodedItem,
906 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700908 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700909 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700910 uint64_t uTagBits = 0;
911 if(pTags) {
912 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700913 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700914
Laurence Lundblade59289e52019-12-30 13:44:37 -0800915 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700916 for(;;) {
917 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700919 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800921
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700922 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
923 // Successful exit from loop; maybe got some tags, maybe not
924 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 break;
926 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700928 uint8_t uTagBitIndex;
929 // Tag was mapped, tag was not mapped, error with tag list
930 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800931
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700932 case QCBOR_SUCCESS:
933 // Successfully mapped the tag
934 uTagBits |= 0x01ULL << uTagBitIndex;
935 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700937 case QCBOR_ERR_BAD_OPT_TAG:
938 // Tag is not recognized. Do nothing
939 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700941 default:
942 // Error Condition
943 goto Done;
944 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800945
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700946 if(pTags) {
947 // Caller wants all tags recorded in the provided buffer
948 if(pTags->uNumUsed >= pTags->uNumAllocated) {
949 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
950 goto Done;
951 }
952 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
953 pTags->uNumUsed++;
954 }
955 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700957Done:
958 return nReturn;
959}
960
961
962/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800963 This layer takes care of map entries. It combines the label and data
964 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700965 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800966static inline QCBORError
967GetNext_MapEntry(QCBORDecodeContext *me,
968 QCBORItem *pDecodedItem,
969 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700970{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700971 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700972 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700973 if(nReturn)
974 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800975
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800976 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700977 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800978 goto Done;
979 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800980
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800981 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
982 // In a map and caller wants maps decoded, not treated as arrays
983
984 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
985 // If in a map and the right decoding mode, get the label
986
Laurence Lundbladeee851742020-01-08 08:37:05 -0800987 // Save label in pDecodedItem and get the next which will
988 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900989 QCBORItem LabelItem = *pDecodedItem;
990 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
991 if(nReturn)
992 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800993
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530994 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900995
996 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
997 // strings are always good labels
998 pDecodedItem->label.string = LabelItem.val.string;
999 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1000 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001002 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1003 goto Done;
1004 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1005 pDecodedItem->label.int64 = LabelItem.val.int64;
1006 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1007 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1008 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1009 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1010 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1011 pDecodedItem->label.string = LabelItem.val.string;
1012 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1013 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1014 } else {
1015 // label is not an int or a string. It is an arrray
1016 // or a float or such and this implementation doesn't handle that.
1017 // Also, tags on labels are ignored.
1018 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1019 goto Done;
1020 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001021 }
1022 } else {
1023 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1024 // Decoding a map as an array
1025 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1026 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001027 }
1028 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001029
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030Done:
1031 return nReturn;
1032}
1033
1034
1035/*
1036 Public function, see header qcbor.h file
1037 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001038QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1039 QCBORItem *pDecodedItem,
1040 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001042 // Stack ptr/int: 2, QCBORItem : 64
1043
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301044 // The public entry point for fetching and parsing the next QCBORItem.
1045 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001046 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001047
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001048 // Check if there are an
1049 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1050 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1051 goto Done;
1052 }
1053
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001054 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001055 if(nReturn) {
1056 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001057 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301058
1059 // Break ending arrays/maps are always processed at the end of this function.
1060 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301061 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301062 nReturn = QCBOR_ERR_BAD_BREAK;
1063 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301064 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001065
Laurence Lundblade6de37062018-10-15 12:22:42 +05301066 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301067 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301068 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001069
Laurence Lundblade6de37062018-10-15 12:22:42 +05301070 // Process the item just received for descent or decrement, and
1071 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001072 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001073 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001074 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001075 // Maps and arrays do count in as items in the map/array that encloses
1076 // them so a decrement needs to be done for them too, but that is done
1077 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001078 // are opened with the exception of an empty map or array.
1079 if(pDecodedItem->val.uCount == 0) {
1080 DecodeNesting_DecrementCount(&(me->nesting));
1081 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001082 } else {
1083 // Decrement the count of items in the enclosing map/array
1084 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301085 // triggers a decrement in the map/array above that and
1086 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001087 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001088 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301089 if(nReturn) {
1090 goto Done;
1091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade6de37062018-10-15 12:22:42 +05301093 // For indefinite length maps/arrays, looking at any and
1094 // all breaks that might terminate them. The equivalent
1095 // for definite length maps/arrays happens in
1096 // DecodeNesting_DecrementCount().
1097 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1098 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1099 // Peek forward one item to see if it is a break.
1100 QCBORItem Peek;
1101 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1102 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1103 if(nReturn) {
1104 goto Done;
1105 }
1106 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1107 // It is not a break, rewind so it can be processed normally.
1108 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1109 break;
1110 }
1111 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301112 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301113 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1114 if(nReturn) {
1115 // break occured outside of an indefinite length array/map
1116 goto Done;
1117 }
1118 }
1119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundblade6de37062018-10-15 12:22:42 +05301121 // Tell the caller what level is next. This tells them what maps/arrays
1122 // were closed out and makes it possible for them to reconstruct
1123 // the tree with just the information returned by GetNext
1124 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001125
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001126Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001127 if(nReturn != QCBOR_SUCCESS) {
1128 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1129 memset(pDecodedItem, 0, sizeof(QCBORItem));
1130 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131 return nReturn;
1132}
1133
1134
Laurence Lundblade59289e52019-12-30 13:44:37 -08001135/*
1136 Mostly just assign the right data type for the date string.
1137 */
1138inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1139{
1140 // Stack Use: UsefulBuf 1 16
1141 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1142 return QCBOR_ERR_BAD_OPT_TAG;
1143 }
1144
1145 const UsefulBufC Temp = pDecodedItem->val.string;
1146 pDecodedItem->val.dateString = Temp;
1147 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1148 return QCBOR_SUCCESS;
1149}
1150
1151
1152/*
1153 Mostly just assign the right data type for the bignum.
1154 */
1155inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1156{
1157 // Stack Use: UsefulBuf 1 -- 16
1158 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1159 return QCBOR_ERR_BAD_OPT_TAG;
1160 }
1161 const UsefulBufC Temp = pDecodedItem->val.string;
1162 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001163 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
1164 pDecodedItem->uDataType = bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001165 return QCBOR_SUCCESS;
1166}
1167
1168
1169/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001170 The epoch formatted date. Turns lots of different forms of encoding
1171 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001172 */
1173static int DecodeDateEpoch(QCBORItem *pDecodedItem)
1174{
1175 // Stack usage: 1
1176 QCBORError nReturn = QCBOR_SUCCESS;
1177
1178 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1179
1180 switch (pDecodedItem->uDataType) {
1181
1182 case QCBOR_TYPE_INT64:
1183 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1184 break;
1185
1186 case QCBOR_TYPE_UINT64:
1187 if(pDecodedItem->val.uint64 > INT64_MAX) {
1188 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1189 goto Done;
1190 }
1191 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
1192 break;
1193
1194 case QCBOR_TYPE_DOUBLE:
1195 {
1196 // This comparison needs to be done as a float before
1197 // conversion to an int64_t to be able to detect doubles
1198 // that are too large to fit into an int64_t. A double
1199 // has 52 bits of preceision. An int64_t has 63. Casting
1200 // INT64_MAX to a double actually causes a round up which
1201 // is bad and wrong for the comparison because it will
1202 // allow conversion of doubles that can't fit into a
1203 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1204 // the cutoff point as if that rounds up in conversion to
1205 // double it will still be less than INT64_MAX. 0x7ff is
1206 // picked because it has 11 bits set.
1207 //
1208 // INT64_MAX seconds is on the order of 10 billion years,
1209 // and the earth is less than 5 billion years old, so for
1210 // most uses this conversion error won't occur even though
1211 // doubles can go much larger.
1212 //
1213 // Without the 0x7ff there is a ~30 minute range of time
1214 // values 10 billion years in the past and in the future
1215 // where this this code would go wrong.
1216 const double d = pDecodedItem->val.dfnum;
1217 if(d > (double)(INT64_MAX - 0x7ff)) {
1218 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1219 goto Done;
1220 }
1221 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1222 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1223 }
1224 break;
1225
1226 default:
1227 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1228 goto Done;
1229 }
1230 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1231
1232Done:
1233 return nReturn;
1234}
1235
1236
1237#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1238/*
1239 Decode decimal fractions and big floats.
1240
1241 When called pDecodedItem must be the array that is tagged as a big
1242 float or decimal fraction, the array that has the two members, the
1243 exponent and mantissa.
1244
1245 This will fetch and decode the exponent and mantissa and put the
1246 result back into pDecodedItem.
1247 */
1248inline static QCBORError
1249QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1250{
1251 QCBORError nReturn;
1252
1253 // --- Make sure it is an array; track nesting level of members ---
1254 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1255 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1256 goto Done;
1257 }
1258
1259 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001260 // definite length arrays, but not for indefnite. Instead remember
1261 // the nesting level the two integers must be at, which is one
1262 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001263 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1264
1265 // --- Is it a decimal fraction or a bigfloat? ---
1266 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1267 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1268
1269 // --- Get the exponent ---
1270 QCBORItem exponentItem;
1271 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1272 if(nReturn != QCBOR_SUCCESS) {
1273 goto Done;
1274 }
1275 if(exponentItem.uNestingLevel != nNestLevel) {
1276 // Array is empty or a map/array encountered when expecting an int
1277 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1278 goto Done;
1279 }
1280 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1281 // Data arriving as an unsigned int < INT64_MAX has been converted
1282 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1283 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1284 // will be too large for this to handle and thus an error that will
1285 // get handled in the next else.
1286 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1287 } else {
1288 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1289 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1290 goto Done;
1291 }
1292
1293 // --- Get the mantissa ---
1294 QCBORItem mantissaItem;
1295 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1296 if(nReturn != QCBOR_SUCCESS) {
1297 goto Done;
1298 }
1299 if(mantissaItem.uNestingLevel != nNestLevel) {
1300 // Mantissa missing or map/array encountered when expecting number
1301 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1302 goto Done;
1303 }
1304 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1305 // Data arriving as an unsigned int < INT64_MAX has been converted
1306 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1307 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1308 // will be too large for this to handle and thus an error that
1309 // will get handled in an else below.
1310 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1311 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1312 // Got a good big num mantissa
1313 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1314 // Depends on numbering of QCBOR_TYPE_XXX
1315 pDecodedItem->uDataType += 1 + mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM;
1316 } else {
1317 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1318 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1319 goto Done;
1320 }
1321
1322 // --- Check that array only has the two numbers ---
1323 if(mantissaItem.uNextNestLevel == nNestLevel) {
1324 // Extra items in the decimal fraction / big num
1325 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1326 goto Done;
1327 }
1328
1329Done:
1330
1331 return nReturn;
1332}
1333#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1334
1335
1336/*
1337 Public function, see header qcbor.h file
1338 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001339QCBORError
1340QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1341 QCBORItem *pDecodedItem,
1342 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001343{
1344 QCBORError nReturn;
1345
1346 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1347 if(nReturn != QCBOR_SUCCESS) {
1348 goto Done;
1349 }
1350
1351#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1352#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1353#else
1354#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1355#endif
1356
1357 // Only pay attention to tags this code knows how to decode.
1358 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1359 case 0:
1360 // No tags at all or none we know about. Nothing to do.
1361 // This is the pass-through path of this function
1362 // that will mostly be taken when decoding any item.
1363 break;
1364
1365 case QCBOR_TAGFLAG_DATE_STRING:
1366 nReturn = DecodeDateString(pDecodedItem);
1367 break;
1368
1369 case QCBOR_TAGFLAG_DATE_EPOCH:
1370 nReturn = DecodeDateEpoch(pDecodedItem);
1371 break;
1372
1373 case QCBOR_TAGFLAG_POS_BIGNUM:
1374 case QCBOR_TAGFLAG_NEG_BIGNUM:
1375 nReturn = DecodeBigNum(pDecodedItem);
1376 break;
1377
1378#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1379 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1380 case QCBOR_TAGFLAG_BIGFLOAT:
1381 // For aggregate tagged types, what goes into pTags is only collected
1382 // from the surrounding data item, not the contents, so pTags is not
1383 // passed on here.
1384
1385 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1386 break;
1387#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1388
1389 default:
1390 // Encountering some mixed-up CBOR like something that
1391 // is tagged as both a string and integer date.
1392 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1393 }
1394
1395Done:
1396 if(nReturn != QCBOR_SUCCESS) {
1397 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1398 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1399 }
1400 return nReturn;
1401}
1402
1403
1404/*
1405 Public function, see header qcbor.h file
1406 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001407QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001408{
1409 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1410}
1411
1412
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001413/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301414 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301415 next one down. If a layer has no work to do for a particular item
1416 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001417
Laurence Lundblade59289e52019-12-30 13:44:37 -08001418 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1419 tagged data items, turning them into the local C representation.
1420 For the most simple it is just associating a QCBOR_TYPE with the data. For
1421 the complex ones that an aggregate of data items, there is some further
1422 decoding and a little bit of recursion.
1423
1424 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301425 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301426 out of maps/arrays. It processes all breaks that terminate
1427 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001428
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301429 - GetNext_MapEntry -- This handles the combining of two
1430 items, the label and the data, that make up a map entry.
1431 It only does work on maps. It combines the label and data
1432 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001433
Laurence Lundblade59289e52019-12-30 13:44:37 -08001434 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1435 tags into bit flags associated with the data item. No actual decoding
1436 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001437
Laurence Lundblade59289e52019-12-30 13:44:37 -08001438 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301439 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301440 string allocater to create contiguous space for the item. It
1441 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001442
Laurence Lundblade59289e52019-12-30 13:44:37 -08001443 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1444 atomic data item has a "major type", an integer "argument" and optionally
1445 some content. For text and byte strings, the content is the bytes
1446 that make up the string. These are the smallest data items that are
1447 considered to be well-formed. The content may also be other data items in
1448 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001449
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001450 Roughly this takes 300 bytes of stack for vars. Need to
1451 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001452
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301453 */
1454
1455
1456/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001457 Public function, see header qcbor.h file
1458 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001459int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1460 const QCBORItem *pItem,
1461 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001462{
1463 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001464
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001465 uint8_t uTagBitIndex;
1466 // Do not care about errors in pCallerConfiguredTagMap here. They are
1467 // caught during GetNext() before this is called.
1468 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1469 return 0;
1470 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001471
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001472 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1473 return (uTagBit & pItem->uTagBits) != 0;
1474}
1475
1476
1477/*
1478 Public function, see header qcbor.h file
1479 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001480QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001481{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001482 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001483
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001484 // Error out if all the maps/arrays are not closed out
1485 if(DecodeNesting_IsNested(&(me->nesting))) {
1486 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1487 goto Done;
1488 }
1489
1490 // Error out if not all the bytes are consumed
1491 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1492 nReturn = QCBOR_ERR_EXTRA_BYTES;
1493 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001494
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001495Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301496 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001497 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001498 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001499
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001500 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001501}
1502
1503
1504
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001505/*
1506
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001507Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001508
Laurence Lundbladeee851742020-01-08 08:37:05 -08001509 - Hit end of input before it was expected while decoding type and
1510 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001511
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001512 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001513
Laurence Lundbladeee851742020-01-08 08:37:05 -08001514 - Hit end of input while decoding a text or byte string
1515 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001516
Laurence Lundbladeee851742020-01-08 08:37:05 -08001517 - Encountered conflicting tags -- e.g., an item is tagged both a date
1518 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001519
Laurence Lundbladeee851742020-01-08 08:37:05 -08001520 - Encontered an array or mapp that has too many items
1521 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001522
Laurence Lundbladeee851742020-01-08 08:37:05 -08001523 - Encountered array/map nesting that is too deep
1524 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001525
Laurence Lundbladeee851742020-01-08 08:37:05 -08001526 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1527 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001528
Laurence Lundbladeee851742020-01-08 08:37:05 -08001529 - The type of a map label is not a string or int
1530 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001532 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001533
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001534 */
1535
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001536
1537
Laurence Lundbladef6531662018-12-04 10:42:22 +09001538
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001539/* ===========================================================================
1540 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001541
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001542 This implements a simple sting allocator for indefinite length
1543 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1544 implements the function type QCBORStringAllocate and allows easy
1545 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001546
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001547 This particular allocator is built-in for convenience. The caller
1548 can implement their own. All of this following code will get
1549 dead-stripped if QCBORDecode_SetMemPool() is not called.
1550
1551 This is a very primitive memory allocator. It does not track
1552 individual allocations, only a high-water mark. A free or
1553 reallocation must be of the last chunk allocated.
1554
1555 The size of the pool and offset to free memory are packed into the
1556 first 8 bytes of the memory pool so we don't have to keep them in
1557 the decode context. Since the address of the pool may not be
1558 aligned, they have to be packed and unpacked as if they were
1559 serialized data of the wire or such.
1560
1561 The sizes packed in are uint32_t to be the same on all CPU types
1562 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001563 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001564
1565
Laurence Lundbladeee851742020-01-08 08:37:05 -08001566static inline int
1567MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001568{
1569 // Use of UsefulInputBuf is overkill, but it is convenient.
1570 UsefulInputBuf UIB;
1571
Laurence Lundbladeee851742020-01-08 08:37:05 -08001572 // Just assume the size here. It was checked during SetUp so
1573 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001574 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1575 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1576 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1577 return UsefulInputBuf_GetError(&UIB);
1578}
1579
1580
Laurence Lundbladeee851742020-01-08 08:37:05 -08001581static inline int
1582MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001583{
1584 // Use of UsefulOutBuf is overkill, but convenient. The
1585 // length check performed here is useful.
1586 UsefulOutBuf UOB;
1587
1588 UsefulOutBuf_Init(&UOB, Pool);
1589 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1590 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1591 return UsefulOutBuf_GetError(&UOB);
1592}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001593
1594
1595/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001596 Internal function for an allocation, reallocation free and destuct.
1597
1598 Having only one function rather than one each per mode saves space in
1599 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001600
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001601 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1602 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001603static UsefulBuf
1604MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001605{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001606 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001607
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001608 uint32_t uPoolSize;
1609 uint32_t uFreeOffset;
1610
1611 if(uNewSize > UINT32_MAX) {
1612 // This allocator is only good up to 4GB. This check should
1613 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1614 goto Done;
1615 }
1616 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1617
1618 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1619 goto Done;
1620 }
1621
1622 if(uNewSize) {
1623 if(pMem) {
1624 // REALLOCATION MODE
1625 // Calculate pointer to the end of the memory pool. It is
1626 // assumed that pPool + uPoolSize won't wrap around by
1627 // assuming the caller won't pass a pool buffer in that is
1628 // not in legitimate memory space.
1629 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1630
1631 // Check that the pointer for reallocation is in the range of the
1632 // pool. This also makes sure that pointer math further down
1633 // doesn't wrap under or over.
1634 if(pMem >= pPool && pMem < pPoolEnd) {
1635 // Offset to start of chunk for reallocation. This won't
1636 // wrap under because of check that pMem >= pPool. Cast
1637 // is safe because the pool is always less than UINT32_MAX
1638 // because of check in QCBORDecode_SetMemPool().
1639 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1640
1641 // Check to see if the allocation will fit. uPoolSize -
1642 // uMemOffset will not wrap under because of check that
1643 // pMem is in the range of the uPoolSize by check above.
1644 if(uNewSize <= uPoolSize - uMemOffset) {
1645 ReturnValue.ptr = pMem;
1646 ReturnValue.len = uNewSize;
1647
1648 // Addition won't wrap around over because uNewSize was
1649 // checked to be sure it is less than the pool size.
1650 uFreeOffset = uMemOffset + uNewSize32;
1651 }
1652 }
1653 } else {
1654 // ALLOCATION MODE
1655 // uPoolSize - uFreeOffset will not underflow because this
1656 // pool implementation makes sure uFreeOffset is always
1657 // smaller than uPoolSize through this check here and
1658 // reallocation case.
1659 if(uNewSize <= uPoolSize - uFreeOffset) {
1660 ReturnValue.len = uNewSize;
1661 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
1662 uFreeOffset += uNewSize;
1663 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001664 }
1665 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001666 if(pMem) {
1667 // FREE MODE
1668 // Cast is safe because of limit on pool size in
1669 // QCBORDecode_SetMemPool()
1670 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1671 } else {
1672 // DESTRUCT MODE
1673 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001674 }
1675 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001676
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001677 UsefulBuf Pool = {pPool, uPoolSize};
1678 MemPool_Pack(Pool, uFreeOffset);
1679
1680Done:
1681 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001682}
1683
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001684
Laurence Lundbladef6531662018-12-04 10:42:22 +09001685/*
1686 Public function, see header qcbor.h file
1687 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001688QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1689 UsefulBuf Pool,
1690 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001691{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001692 // The pool size and free mem offset are packed into the beginning
1693 // of the pool memory. This compile time check make sure the
1694 // constant in the header is correct. This check should optimize
1695 // down to nothing.
1696 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001697 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001698 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001699
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001700 // The pool size and free offset packed in to the beginning of pool
1701 // memory are only 32-bits. This check will optimize out on 32-bit
1702 // machines.
1703 if(Pool.len > UINT32_MAX) {
1704 return QCBOR_ERR_BUFFER_TOO_LARGE;
1705 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001706
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001707 // This checks that the pool buffer given is big enough.
1708 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1709 return QCBOR_ERR_BUFFER_TOO_SMALL;
1710 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001711
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001712 pMe->StringAllocator.pfAllocator = MemPool_Function;
1713 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1714 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001715
Laurence Lundblade30816f22018-11-10 13:40:22 +07001716 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001717}