blob: 1115fa9764dd4aee61a14661fa38322f594638b4 [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 Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053038/*
39 This casts away the const-ness of a pointer, usually so it can be
40 freed or realloced.
41 */
42#define UNCONST_POINTER(ptr) ((void *)(ptr))
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundbladeee851742020-01-08 08:37:05 -080046/*===========================================================================
47 DecodeNesting -- Functions for tracking array/map nesting when decoding
48
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080049 See qcbor/qcbor_decode.h for definition of the object
50 used here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080051 ===========================================================================*/
52
53inline static int
54IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070055{
56 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
57}
58
Laurence Lundbladeee851742020-01-08 08:37:05 -080059inline static int
60DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070061{
62 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
63}
64
Laurence Lundbladeee851742020-01-08 08:37:05 -080065inline static int
66DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070067{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070068 return pNesting->pCurrent->uCount == UINT16_MAX;
69}
70
Laurence Lundbladeee851742020-01-08 08:37:05 -080071inline static uint8_t
72DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +080073{
Laurence Lundbladec5fef682020-01-25 11:38:45 -080074 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -070075 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -080076 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +080077}
78
Laurence Lundbladeee851742020-01-08 08:37:05 -080079inline static int
80DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070081{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070082 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070083 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -070084 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080085
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070086 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
87}
88
Laurence Lundblade3a760b02018-10-08 13:46:03 +080089// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -080090inline static QCBORError
91DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +070092{
Laurence Lundblade3a760b02018-10-08 13:46:03 +080093 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +080095 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080097
Laurence Lundblade3a760b02018-10-08 13:46:03 +080098 // breaks can only occur when the map/array is indefinite length
99 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
100 return QCBOR_ERR_BAD_BREAK;
101 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800102
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800103 // if all OK, the break reduces the level of nesting
104 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800105
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800106 return QCBOR_SUCCESS;
107}
108
Laurence Lundbladeee851742020-01-08 08:37:05 -0800109// Called on every single item except breaks including open of a map/array
110inline static void
111DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800112{
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700113 while(DecodeNesting_IsNested(pNesting)) {
114 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800115
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800116 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700117 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800118 pNesting->pCurrent->uCount--;
119 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700120
121 if(pNesting->pCurrent->uCount != 0) {
122 // Did not close out an array or map, so nothing further
123 break;
124 }
125
126 // Closed out an array or map so level up
127 pNesting->pCurrent--;
128
129 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700130 }
131}
132
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800133// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800134inline static QCBORError
135DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700136{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700137 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800138
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800139 if(pItem->val.uCount == 0) {
140 // Nothing to do for empty definite lenth arrays. They are just are
141 // effectively the same as an item that is not a map or array
142 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530143 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800144 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800145
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800146 // Error out if arrays is too long to handle
147 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
149 goto Done;
150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800151
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800152 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
154 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
155 goto Done;
156 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800157
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800158 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700159 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800160
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800161 // Record a few details for this nesting level
162 pNesting->pCurrent->uMajorType = pItem->uDataType;
163 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800164
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700165Done:
166 return nReturn;;
167}
168
Laurence Lundbladeee851742020-01-08 08:37:05 -0800169inline static void
170DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700171{
172 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
173}
174
175
176
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700177/*
178 This list of built-in tags. Only add tags here that are
179 clearly established and useful. Once a tag is added here
180 it can't be taken out as that would break backwards compatibility.
181 There are only 48 slots available forever.
182 */
183static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800184 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
185 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
186 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
187 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
188 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
189 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700190 CBOR_TAG_COSE_ENCRYPTO,
191 CBOR_TAG_COSE_MAC0,
192 CBOR_TAG_COSE_SIGN1,
193 CBOR_TAG_ENC_AS_B64URL,
194 CBOR_TAG_ENC_AS_B64,
195 CBOR_TAG_ENC_AS_B16,
196 CBOR_TAG_CBOR,
197 CBOR_TAG_URI,
198 CBOR_TAG_B64URL,
199 CBOR_TAG_B64,
200 CBOR_TAG_REGEX,
201 CBOR_TAG_MIME,
202 CBOR_TAG_BIN_UUID,
203 CBOR_TAG_CWT,
204 CBOR_TAG_ENCRYPT,
205 CBOR_TAG_MAC,
206 CBOR_TAG_SIGN,
207 CBOR_TAG_GEO_COORD,
208 CBOR_TAG_CBOR_MAGIC
209};
210
211// This is used in a bit of cleverness in GetNext_TaggedItem() to
212// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800213// these types. This will break if the first six items in
214// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
215// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
216#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
217#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
218#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
219#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
220#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
221#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700222
Laurence Lundblade59289e52019-12-30 13:44:37 -0800223#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
224 QCBOR_TAGFLAG_DATE_EPOCH |\
225 QCBOR_TAGFLAG_POS_BIGNUM |\
226 QCBOR_TAGFLAG_NEG_BIGNUM |\
227 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
228 QCBOR_TAGFLAG_BIGFLOAT)
229
230#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
231 QCBOR_TAGFLAG_DATE_EPOCH |\
232 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700233 QCBOR_TAGFLAG_NEG_BIGNUM)
234
235#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
236#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
237#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
238
239static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
240{
241 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800242 /*
243 This is a cross-check to make sure the above array doesn't
244 accidentally get made too big. In normal conditions the above
245 test should optimize out as all the values are known at compile
246 time.
247 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700248 return -1;
249 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800250
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700251 if(uTag > UINT16_MAX) {
252 // This tag map works only on 16-bit tags
253 return -1;
254 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800255
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700256 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
257 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
258 return nTagBitIndex;
259 }
260 }
261 return -1; // Indicates no match
262}
263
264static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
265{
266 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
267 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
268 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
269 }
270 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800271
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700272 return -1; // Indicates no match
273}
274
275/*
276 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800277
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700278 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800279 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700280 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800281static QCBORError
282TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
283 uint64_t uTag,
284 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700285{
286 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
287 if(nTagBitIndex >= 0) {
288 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
289 *puTagBitIndex = (uint8_t)nTagBitIndex;
290 return QCBOR_SUCCESS;
291 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800292
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700293 if(pCallerConfiguredTagMap) {
294 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
295 return QCBOR_ERR_TOO_MANY_TAGS;
296 }
297 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
298 if(nTagBitIndex >= 0) {
299 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
300
301 *puTagBitIndex = (uint8_t)nTagBitIndex;
302 return QCBOR_SUCCESS;
303 }
304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700306 return QCBOR_ERR_BAD_OPT_TAG;
307}
308
309
310
Laurence Lundbladeee851742020-01-08 08:37:05 -0800311/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800312 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
313
314 The following four functions are pretty wrappers for invocation of
315 the string allocator supplied by the caller.
316
Laurence Lundbladeee851742020-01-08 08:37:05 -0800317 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800318
Laurence Lundbladeee851742020-01-08 08:37:05 -0800319static inline void
320StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800321{
322 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
323}
324
Laurence Lundbladeee851742020-01-08 08:37:05 -0800325// StringAllocator_Reallocate called with pMem NULL is
326// equal to StringAllocator_Allocate()
327static inline UsefulBuf
328StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
329 void *pMem,
330 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800331{
332 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
333}
334
Laurence Lundbladeee851742020-01-08 08:37:05 -0800335static inline UsefulBuf
336StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800337{
338 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
339}
340
Laurence Lundbladeee851742020-01-08 08:37:05 -0800341static inline void
342StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800343{
344 if(pMe->pfAllocator) {
345 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
346 }
347}
348
349
350
Laurence Lundbladeee851742020-01-08 08:37:05 -0800351/*===========================================================================
352 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700353
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800354 See qcbor/qcbor_decode.h for definition of the object
355 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800356 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700357/*
358 Public function, see header file
359 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800360void QCBORDecode_Init(QCBORDecodeContext *me,
361 UsefulBufC EncodedCBOR,
362 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700363{
364 memset(me, 0, sizeof(QCBORDecodeContext));
365 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800366 // Don't bother with error check on decode mode. If a bad value is
367 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700368 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700369 DecodeNesting_Init(&(me->nesting));
370}
371
372
373/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700374 Public function, see header file
375 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800376void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
377 QCBORStringAllocate pfAllocateFunction,
378 void *pAllocateContext,
379 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700380{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800381 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
382 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
383 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700384}
385
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800386
387/*
388 Public function, see header file
389 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800390void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
391 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700392{
393 me->pCallerConfiguredTagList = pTagList;
394}
395
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700396
397/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800398 This decodes the fundamental part of a CBOR data item, the type and
399 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800400
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700401 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800402
Laurence Lundbladeee851742020-01-08 08:37:05 -0800403 This does the network->host byte order conversion. The conversion
404 here also results in the conversion for floats in addition to that
405 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800406
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700407 This returns:
408 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800409
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800410 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800411 tags and floats and length for strings and arrays
412
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800413 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800414 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800415
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800416 The int type is preferred to uint8_t for some variables as this
417 avoids integer promotions, can reduce code size and makes
418 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700419 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800420inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
421 int *pnMajorType,
422 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800423 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700424{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700425 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800426
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700427 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800428 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800429
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700430 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800431 const int nTmpMajorType = nInitialByte >> 5;
432 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800433
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800434 // Where the number or argument accumulates
435 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800436
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800437 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800438 // Need to get 1,2,4 or 8 additional argument bytes Map
439 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800440 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800441
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800442 // Loop getting all the bytes in the argument
443 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800444 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800445 // This shift and add gives the endian conversion
446 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
447 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800448 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800449 // The reserved and thus-far unused additional info values
450 nReturn = QCBOR_ERR_UNSUPPORTED;
451 goto Done;
452 } else {
453 // Less than 24, additional info is argument or 31, an indefinite length
454 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800455 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700456 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800457
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700458 if(UsefulInputBuf_GetError(pUInBuf)) {
459 nReturn = QCBOR_ERR_HIT_END;
460 goto Done;
461 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800462
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463 // All successful if we got here.
464 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800465 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800466 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800467 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800468
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700469Done:
470 return nReturn;
471}
472
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800473
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700474/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800475 CBOR doesn't explicitly specify two's compliment for integers but all
476 CPUs use it these days and the test vectors in the RFC are so. All
477 integers in the CBOR structure are positive and the major type
478 indicates positive or negative. CBOR can express positive integers
479 up to 2^x - 1 where x is the number of bits and negative integers
480 down to 2^x. Note that negative numbers can be one more away from
481 zero than positive. Stdint, as far as I can tell, uses two's
482 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800483
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700484 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800485 used carefully here, and in particular why it isn't used in the interface.
486 Also see
487 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
488
489 Int is used for values that need less than 16-bits and would be subject
490 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700491 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492inline static QCBORError
493DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700494{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700495 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800496
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700497 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
498 if (uNumber <= INT64_MAX) {
499 pDecodedItem->val.int64 = (int64_t)uNumber;
500 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800501
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700502 } else {
503 pDecodedItem->val.uint64 = uNumber;
504 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800505
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700506 }
507 } else {
508 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800509 // CBOR's representation of negative numbers lines up with the
510 // two-compliment representation. A negative integer has one
511 // more in range than a positive integer. INT64_MIN is
512 // equal to (-INT64_MAX) - 1.
513 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700514 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800515
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700516 } else {
517 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000518 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700519 nReturn = QCBOR_ERR_INT_OVERFLOW;
520 }
521 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800522
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700523 return nReturn;
524}
525
526// Make sure #define value line up as DecodeSimple counts on this.
527#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
528#error QCBOR_TYPE_FALSE macro value wrong
529#endif
530
531#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
532#error QCBOR_TYPE_TRUE macro value wrong
533#endif
534
535#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
536#error QCBOR_TYPE_NULL macro value wrong
537#endif
538
539#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
540#error QCBOR_TYPE_UNDEF macro value wrong
541#endif
542
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700543#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
544#error QCBOR_TYPE_BREAK macro value wrong
545#endif
546
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
548#error QCBOR_TYPE_DOUBLE macro value wrong
549#endif
550
551#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
552#error QCBOR_TYPE_FLOAT macro value wrong
553#endif
554
555/*
556 Decode true, false, floats, break...
557 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800558inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800559DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700560{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700561 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800562
Laurence Lundbladeee851742020-01-08 08:37:05 -0800563 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800564 // above make sure uAdditionalInfo values line up with uDataType values.
565 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
566 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800567
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800568 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800569 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
570 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800571
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700572 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700573 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
574 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700575 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700576 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700577 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
578 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700579 break;
580 case DOUBLE_PREC_FLOAT:
581 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700582 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700583 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800584
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585 case CBOR_SIMPLEV_FALSE: // 20
586 case CBOR_SIMPLEV_TRUE: // 21
587 case CBOR_SIMPLEV_NULL: // 22
588 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700589 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700590 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800591
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592 case CBOR_SIMPLEV_ONEBYTE: // 24
593 if(uNumber <= CBOR_SIMPLE_BREAK) {
594 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700595 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700596 goto Done;
597 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800598 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800600
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700601 default: // 0-19
602 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800603 /*
604 DecodeTypeAndNumber will make uNumber equal to
605 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
606 safe because the 2, 4 and 8 byte lengths of uNumber are in
607 the double/float cases above
608 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700609 pDecodedItem->val.uSimple = (uint8_t)uNumber;
610 break;
611 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613Done:
614 return nReturn;
615}
616
617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700618/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530619 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800621inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
622 int nMajorType,
623 uint64_t uStrLen,
624 UsefulInputBuf *pUInBuf,
625 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700626{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700627 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800628
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800629 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
630 // This check makes the casts to size_t below safe.
631
632 // 4 bytes less than the largest sizeof() so this can be tested by
633 // putting a SIZE_MAX length in the CBOR test input (no one will
634 // care the limit on strings is 4 bytes shorter).
635 if(uStrLen > SIZE_MAX-4) {
636 nReturn = QCBOR_ERR_STRING_TOO_LONG;
637 goto Done;
638 }
639
640 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530641 if(UsefulBuf_IsNULLC(Bytes)) {
642 // Failed to get the bytes for this string item
643 nReturn = QCBOR_ERR_HIT_END;
644 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700645 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530646
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800647 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530648 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530650 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700651 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530652 goto Done;
653 }
654 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530656 } else {
657 // Normal case with no string allocator
658 pDecodedItem->val.string = Bytes;
659 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800660 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800661 // Cast because ternary operator causes promotion to integer
662 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
663 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800664
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530665Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700666 return nReturn;
667}
668
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671
672
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700673
674
Laurence Lundbladeee851742020-01-08 08:37:05 -0800675// Make sure the constants align as this is assumed by
676// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700677#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
678#error QCBOR_TYPE_ARRAY value not lined up with major type
679#endif
680#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
681#error QCBOR_TYPE_MAP value not lined up with major type
682#endif
683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800685 This gets a single data item and decodes it including preceding
686 optional tagging. This does not deal with arrays and maps and nesting
687 except to decode the data item introducing them. Arrays and maps are
688 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800689
Laurence Lundbladeee851742020-01-08 08:37:05 -0800690 Errors detected here include: an array that is too long to decode,
691 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800693static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
694 QCBORItem *pDecodedItem,
695 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700696{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700697 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800698
Laurence Lundbladeee851742020-01-08 08:37:05 -0800699 /*
700 Get the major type and the number. Number could be length of more
701 bytes or the value depending on the major type nAdditionalInfo is
702 an encoding of the length of the uNumber and is needed to decode
703 floats and doubles
704 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800705 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700706 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800707 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800708
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700709 memset(pDecodedItem, 0, sizeof(QCBORItem));
710
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800712
Laurence Lundbladeee851742020-01-08 08:37:05 -0800713 // Error out here if we got into trouble on the type and number. The
714 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700715 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700716 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700717 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800718
Laurence Lundbladeee851742020-01-08 08:37:05 -0800719 // At this point the major type and the value are valid. We've got
720 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800721 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700722 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
723 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800724 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700725 nReturn = QCBOR_ERR_BAD_INT;
726 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800727 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700728 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700729 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800730
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700731 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
732 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
734 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
735 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
736 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530737 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700738 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800739 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700740 }
741 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800742
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700743 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
744 case CBOR_MAJOR_TYPE_MAP: // Major type 5
745 // Record the number of items in the array or map
746 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
747 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
748 goto Done;
749 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530751 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700752 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800753 // type conversion OK because of check above
754 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800756 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800757 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
758 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700759 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800760
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700761 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800762 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700763 nReturn = QCBOR_ERR_BAD_INT;
764 } else {
765 pDecodedItem->val.uTagV = uNumber;
766 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
767 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700768 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundbladeee851742020-01-08 08:37:05 -0800770 case CBOR_MAJOR_TYPE_SIMPLE:
771 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700773 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800774
Laurence Lundbladeee851742020-01-08 08:37:05 -0800775 default:
776 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 nReturn = QCBOR_ERR_UNSUPPORTED;
778 break;
779 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800780
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781Done:
782 return nReturn;
783}
784
785
786
787/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800788 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 individual chunk items together into one QCBORItem using the string
790 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530792 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700793 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800794static inline QCBORError
795GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700796{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700797 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700798 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800799 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
800 &(me->StringAllocator) :
801 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530802 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800803
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800804 nReturn = GetNext_Item(&(me->InBuf),
805 pDecodedItem,
806 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700807 if(nReturn) {
808 goto Done;
809 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700811 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530812 // code in this function from here down can be eliminated. Run tests, except
813 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800814
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800815 // Only do indefinite length processing on strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800816 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING &&
817 pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700818 goto Done; // no need to do any work here on non-string types
819 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800820
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800821 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530822 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800823 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700824 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800825
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530826 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800827 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700828 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
829 goto Done;
830 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700832 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800833 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700836 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700837 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700838 // Get item for next chunk
839 QCBORItem StringChunkItem;
840 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800841 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700843 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800845
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530846 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700847 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800848 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700849 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530850 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700851 break;
852 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800853
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700854 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530855 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700856 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 if(StringChunkItem.uDataType != uStringType ||
858 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700859 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 break;
861 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530863 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800864 // The first time throurgh FullString.ptr is NULL and this is
865 // equivalent to StringAllocator_Allocate()
866 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
867 UNCONST_POINTER(FullString.ptr),
868 FullString.len + StringChunkItem.val.string.len);
869
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700870 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530871 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700872 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700873 break;
874 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700876 // Copy new string chunk at the end of string so far.
877 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800879
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800881 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
882 // Getting the item failed, clean up the allocated memory
883 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700886 return nReturn;
887}
888
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889
890/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800891 Gets all optional tag data items preceding a data item that is not an
892 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700893 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800894static QCBORError
895GetNext_TaggedItem(QCBORDecodeContext *me,
896 QCBORItem *pDecodedItem,
897 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700899 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700900 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700901 uint64_t uTagBits = 0;
902 if(pTags) {
903 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700905
Laurence Lundblade59289e52019-12-30 13:44:37 -0800906 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700907 for(;;) {
908 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700909 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700910 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700911 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800912
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700913 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
914 // Successful exit from loop; maybe got some tags, maybe not
915 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916 break;
917 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800918
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700919 uint8_t uTagBitIndex;
920 // Tag was mapped, tag was not mapped, error with tag list
921 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700923 case QCBOR_SUCCESS:
924 // Successfully mapped the tag
925 uTagBits |= 0x01ULL << uTagBitIndex;
926 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700928 case QCBOR_ERR_BAD_OPT_TAG:
929 // Tag is not recognized. Do nothing
930 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800931
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700932 default:
933 // Error Condition
934 goto Done;
935 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700937 if(pTags) {
938 // Caller wants all tags recorded in the provided buffer
939 if(pTags->uNumUsed >= pTags->uNumAllocated) {
940 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
941 goto Done;
942 }
943 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
944 pTags->uNumUsed++;
945 }
946 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948Done:
949 return nReturn;
950}
951
952
953/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800954 This layer takes care of map entries. It combines the label and data
955 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700956 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800957static inline QCBORError
958GetNext_MapEntry(QCBORDecodeContext *me,
959 QCBORItem *pDecodedItem,
960 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700961{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700962 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700963 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700964 if(nReturn)
965 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800966
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800967 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700968 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800969 goto Done;
970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800972 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
973 // In a map and caller wants maps decoded, not treated as arrays
974
975 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
976 // If in a map and the right decoding mode, get the label
977
Laurence Lundbladeee851742020-01-08 08:37:05 -0800978 // Save label in pDecodedItem and get the next which will
979 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900980 QCBORItem LabelItem = *pDecodedItem;
981 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
982 if(nReturn)
983 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530985 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900986
987 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
988 // strings are always good labels
989 pDecodedItem->label.string = LabelItem.val.string;
990 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
991 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800992 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +0900993 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
994 goto Done;
995 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
996 pDecodedItem->label.int64 = LabelItem.val.int64;
997 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
998 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
999 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1000 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1001 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1002 pDecodedItem->label.string = LabelItem.val.string;
1003 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1004 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1005 } else {
1006 // label is not an int or a string. It is an arrray
1007 // or a float or such and this implementation doesn't handle that.
1008 // Also, tags on labels are ignored.
1009 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1010 goto Done;
1011 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001012 }
1013 } else {
1014 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001015 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1016 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1017 goto Done;
1018 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001019 // Decoding a map as an array
1020 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001021 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1022 // Cast is needed because of integer promotion
1023 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024 }
1025 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001027Done:
1028 return nReturn;
1029}
1030
1031
1032/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001033 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001034 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001036QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1037 QCBORItem *pDecodedItem,
1038 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001039{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001040 // Stack ptr/int: 2, QCBORItem : 64
1041
Laurence Lundblade30816f22018-11-10 13:40:22 +07001042 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001043
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001044 // Check if there are an TODO: incomplete
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001045 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1046 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1047 goto Done;
1048 }
1049
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001050 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001051 if(nReturn) {
1052 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301054
1055 // Break ending arrays/maps are always processed at the end of this function.
1056 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301057 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301058 nReturn = QCBOR_ERR_BAD_BREAK;
1059 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301060 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001061
Laurence Lundblade6de37062018-10-15 12:22:42 +05301062 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301063 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301064 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001065
Laurence Lundblade6de37062018-10-15 12:22:42 +05301066 // Process the item just received for descent or decrement, and
1067 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001068 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001069 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001070 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001071 // Maps and arrays do count in as items in the map/array that encloses
1072 // them so a decrement needs to be done for them too, but that is done
1073 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001074 // are opened with the exception of an empty map or array.
1075 if(pDecodedItem->val.uCount == 0) {
1076 DecodeNesting_DecrementCount(&(me->nesting));
1077 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001078 } else {
1079 // Decrement the count of items in the enclosing map/array
1080 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301081 // triggers a decrement in the map/array above that and
1082 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001083 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001084 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301085 if(nReturn) {
1086 goto Done;
1087 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundblade6de37062018-10-15 12:22:42 +05301089 // For indefinite length maps/arrays, looking at any and
1090 // all breaks that might terminate them. The equivalent
1091 // for definite length maps/arrays happens in
1092 // DecodeNesting_DecrementCount().
1093 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1094 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1095 // Peek forward one item to see if it is a break.
1096 QCBORItem Peek;
1097 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1098 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1099 if(nReturn) {
1100 goto Done;
1101 }
1102 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1103 // It is not a break, rewind so it can be processed normally.
1104 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1105 break;
1106 }
1107 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301108 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301109 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1110 if(nReturn) {
1111 // break occured outside of an indefinite length array/map
1112 goto Done;
1113 }
1114 }
1115 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001116
Laurence Lundblade6de37062018-10-15 12:22:42 +05301117 // Tell the caller what level is next. This tells them what maps/arrays
1118 // were closed out and makes it possible for them to reconstruct
1119 // the tree with just the information returned by GetNext
1120 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001122Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001123 if(nReturn != QCBOR_SUCCESS) {
1124 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1125 memset(pDecodedItem, 0, sizeof(QCBORItem));
1126 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001127 return nReturn;
1128}
1129
1130
Laurence Lundblade59289e52019-12-30 13:44:37 -08001131/*
1132 Mostly just assign the right data type for the date string.
1133 */
1134inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1135{
1136 // Stack Use: UsefulBuf 1 16
1137 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1138 return QCBOR_ERR_BAD_OPT_TAG;
1139 }
1140
1141 const UsefulBufC Temp = pDecodedItem->val.string;
1142 pDecodedItem->val.dateString = Temp;
1143 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1144 return QCBOR_SUCCESS;
1145}
1146
1147
1148/*
1149 Mostly just assign the right data type for the bignum.
1150 */
1151inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1152{
1153 // Stack Use: UsefulBuf 1 -- 16
1154 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1155 return QCBOR_ERR_BAD_OPT_TAG;
1156 }
1157 const UsefulBufC Temp = pDecodedItem->val.string;
1158 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001159 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001160 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1161 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001162 return QCBOR_SUCCESS;
1163}
1164
1165
1166/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001167 The epoch formatted date. Turns lots of different forms of encoding
1168 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001169 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001170static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001171{
1172 // Stack usage: 1
1173 QCBORError nReturn = QCBOR_SUCCESS;
1174
1175 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1176
1177 switch (pDecodedItem->uDataType) {
1178
1179 case QCBOR_TYPE_INT64:
1180 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1181 break;
1182
1183 case QCBOR_TYPE_UINT64:
1184 if(pDecodedItem->val.uint64 > INT64_MAX) {
1185 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1186 goto Done;
1187 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001188 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001189 break;
1190
1191 case QCBOR_TYPE_DOUBLE:
1192 {
1193 // This comparison needs to be done as a float before
1194 // conversion to an int64_t to be able to detect doubles
1195 // that are too large to fit into an int64_t. A double
1196 // has 52 bits of preceision. An int64_t has 63. Casting
1197 // INT64_MAX to a double actually causes a round up which
1198 // is bad and wrong for the comparison because it will
1199 // allow conversion of doubles that can't fit into a
1200 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1201 // the cutoff point as if that rounds up in conversion to
1202 // double it will still be less than INT64_MAX. 0x7ff is
1203 // picked because it has 11 bits set.
1204 //
1205 // INT64_MAX seconds is on the order of 10 billion years,
1206 // and the earth is less than 5 billion years old, so for
1207 // most uses this conversion error won't occur even though
1208 // doubles can go much larger.
1209 //
1210 // Without the 0x7ff there is a ~30 minute range of time
1211 // values 10 billion years in the past and in the future
1212 // where this this code would go wrong.
1213 const double d = pDecodedItem->val.dfnum;
1214 if(d > (double)(INT64_MAX - 0x7ff)) {
1215 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1216 goto Done;
1217 }
1218 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1219 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1220 }
1221 break;
1222
1223 default:
1224 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1225 goto Done;
1226 }
1227 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1228
1229Done:
1230 return nReturn;
1231}
1232
1233
1234#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1235/*
1236 Decode decimal fractions and big floats.
1237
1238 When called pDecodedItem must be the array that is tagged as a big
1239 float or decimal fraction, the array that has the two members, the
1240 exponent and mantissa.
1241
1242 This will fetch and decode the exponent and mantissa and put the
1243 result back into pDecodedItem.
1244 */
1245inline static QCBORError
1246QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1247{
1248 QCBORError nReturn;
1249
1250 // --- Make sure it is an array; track nesting level of members ---
1251 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1252 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1253 goto Done;
1254 }
1255
1256 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001257 // definite length arrays, but not for indefnite. Instead remember
1258 // the nesting level the two integers must be at, which is one
1259 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001260 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1261
1262 // --- Is it a decimal fraction or a bigfloat? ---
1263 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1264 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1265
1266 // --- Get the exponent ---
1267 QCBORItem exponentItem;
1268 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1269 if(nReturn != QCBOR_SUCCESS) {
1270 goto Done;
1271 }
1272 if(exponentItem.uNestingLevel != nNestLevel) {
1273 // Array is empty or a map/array encountered when expecting an int
1274 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1275 goto Done;
1276 }
1277 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1278 // Data arriving as an unsigned int < INT64_MAX has been converted
1279 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1280 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1281 // will be too large for this to handle and thus an error that will
1282 // get handled in the next else.
1283 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1284 } else {
1285 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1286 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1287 goto Done;
1288 }
1289
1290 // --- Get the mantissa ---
1291 QCBORItem mantissaItem;
1292 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1293 if(nReturn != QCBOR_SUCCESS) {
1294 goto Done;
1295 }
1296 if(mantissaItem.uNestingLevel != nNestLevel) {
1297 // Mantissa missing or map/array encountered when expecting number
1298 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1299 goto Done;
1300 }
1301 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1302 // Data arriving as an unsigned int < INT64_MAX has been converted
1303 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1304 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1305 // will be too large for this to handle and thus an error that
1306 // will get handled in an else below.
1307 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1308 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1309 // Got a good big num mantissa
1310 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1311 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001312 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1313 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1314 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001315 } else {
1316 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1317 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1318 goto Done;
1319 }
1320
1321 // --- Check that array only has the two numbers ---
1322 if(mantissaItem.uNextNestLevel == nNestLevel) {
1323 // Extra items in the decimal fraction / big num
1324 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1325 goto Done;
1326 }
1327
1328Done:
1329
1330 return nReturn;
1331}
1332#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1333
1334
1335/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001336 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001337 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001338QCBORError
1339QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1340 QCBORItem *pDecodedItem,
1341 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001342{
1343 QCBORError nReturn;
1344
1345 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1346 if(nReturn != QCBOR_SUCCESS) {
1347 goto Done;
1348 }
1349
1350#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1351#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1352#else
1353#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1354#endif
1355
1356 // Only pay attention to tags this code knows how to decode.
1357 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1358 case 0:
1359 // No tags at all or none we know about. Nothing to do.
1360 // This is the pass-through path of this function
1361 // that will mostly be taken when decoding any item.
1362 break;
1363
1364 case QCBOR_TAGFLAG_DATE_STRING:
1365 nReturn = DecodeDateString(pDecodedItem);
1366 break;
1367
1368 case QCBOR_TAGFLAG_DATE_EPOCH:
1369 nReturn = DecodeDateEpoch(pDecodedItem);
1370 break;
1371
1372 case QCBOR_TAGFLAG_POS_BIGNUM:
1373 case QCBOR_TAGFLAG_NEG_BIGNUM:
1374 nReturn = DecodeBigNum(pDecodedItem);
1375 break;
1376
1377#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1378 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1379 case QCBOR_TAGFLAG_BIGFLOAT:
1380 // For aggregate tagged types, what goes into pTags is only collected
1381 // from the surrounding data item, not the contents, so pTags is not
1382 // passed on here.
1383
1384 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1385 break;
1386#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1387
1388 default:
1389 // Encountering some mixed-up CBOR like something that
1390 // is tagged as both a string and integer date.
1391 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1392 }
1393
1394Done:
1395 if(nReturn != QCBOR_SUCCESS) {
1396 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1397 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1398 }
1399 return nReturn;
1400}
1401
1402
1403/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001404 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001405 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001406QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001407{
1408 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1409}
1410
1411
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001412/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301413 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301414 next one down. If a layer has no work to do for a particular item
1415 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001416
Laurence Lundblade59289e52019-12-30 13:44:37 -08001417 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1418 tagged data items, turning them into the local C representation.
1419 For the most simple it is just associating a QCBOR_TYPE with the data. For
1420 the complex ones that an aggregate of data items, there is some further
1421 decoding and a little bit of recursion.
1422
1423 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301424 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301425 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001426 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001427
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301428 - GetNext_MapEntry -- This handles the combining of two
1429 items, the label and the data, that make up a map entry.
1430 It only does work on maps. It combines the label and data
1431 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001432
Laurence Lundblade59289e52019-12-30 13:44:37 -08001433 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1434 tags into bit flags associated with the data item. No actual decoding
1435 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001436
Laurence Lundblade59289e52019-12-30 13:44:37 -08001437 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301438 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301439 string allocater to create contiguous space for the item. It
1440 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001441
Laurence Lundblade59289e52019-12-30 13:44:37 -08001442 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1443 atomic data item has a "major type", an integer "argument" and optionally
1444 some content. For text and byte strings, the content is the bytes
1445 that make up the string. These are the smallest data items that are
1446 considered to be well-formed. The content may also be other data items in
1447 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001448
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001449 Roughly this takes 300 bytes of stack for vars. Need to
1450 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001451
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301452 */
1453
1454
1455/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001456 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001457 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001458int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1459 const QCBORItem *pItem,
1460 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001461{
1462 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001463
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001464 uint8_t uTagBitIndex;
1465 // Do not care about errors in pCallerConfiguredTagMap here. They are
1466 // caught during GetNext() before this is called.
1467 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1468 return 0;
1469 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001470
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001471 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1472 return (uTagBit & pItem->uTagBits) != 0;
1473}
1474
1475
1476/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001477 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001478 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001479QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001480{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001481 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001482
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001483 // Error out if all the maps/arrays are not closed out
1484 if(DecodeNesting_IsNested(&(me->nesting))) {
1485 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1486 goto Done;
1487 }
1488
1489 // Error out if not all the bytes are consumed
1490 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1491 nReturn = QCBOR_ERR_EXTRA_BYTES;
1492 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001493
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001494Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301495 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001496 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001497 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001498
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001499 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001500}
1501
1502
1503
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001504/*
1505
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001506Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001507
Laurence Lundbladeee851742020-01-08 08:37:05 -08001508 - Hit end of input before it was expected while decoding type and
1509 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001510
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001511 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001512
Laurence Lundbladeee851742020-01-08 08:37:05 -08001513 - Hit end of input while decoding a text or byte string
1514 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001515
Laurence Lundbladeee851742020-01-08 08:37:05 -08001516 - Encountered conflicting tags -- e.g., an item is tagged both a date
1517 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001518
Laurence Lundbladeee851742020-01-08 08:37:05 -08001519 - Encontered an array or mapp that has too many items
1520 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001521
Laurence Lundbladeee851742020-01-08 08:37:05 -08001522 - Encountered array/map nesting that is too deep
1523 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001524
Laurence Lundbladeee851742020-01-08 08:37:05 -08001525 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1526 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001527
Laurence Lundbladeee851742020-01-08 08:37:05 -08001528 - The type of a map label is not a string or int
1529 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001531 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001532
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001533 */
1534
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001535
1536
Laurence Lundbladef6531662018-12-04 10:42:22 +09001537
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001538/* ===========================================================================
1539 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001541 This implements a simple sting allocator for indefinite length
1542 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1543 implements the function type QCBORStringAllocate and allows easy
1544 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001545
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001546 This particular allocator is built-in for convenience. The caller
1547 can implement their own. All of this following code will get
1548 dead-stripped if QCBORDecode_SetMemPool() is not called.
1549
1550 This is a very primitive memory allocator. It does not track
1551 individual allocations, only a high-water mark. A free or
1552 reallocation must be of the last chunk allocated.
1553
1554 The size of the pool and offset to free memory are packed into the
1555 first 8 bytes of the memory pool so we don't have to keep them in
1556 the decode context. Since the address of the pool may not be
1557 aligned, they have to be packed and unpacked as if they were
1558 serialized data of the wire or such.
1559
1560 The sizes packed in are uint32_t to be the same on all CPU types
1561 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001562 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001563
1564
Laurence Lundbladeee851742020-01-08 08:37:05 -08001565static inline int
1566MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001567{
1568 // Use of UsefulInputBuf is overkill, but it is convenient.
1569 UsefulInputBuf UIB;
1570
Laurence Lundbladeee851742020-01-08 08:37:05 -08001571 // Just assume the size here. It was checked during SetUp so
1572 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001573 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1574 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1575 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1576 return UsefulInputBuf_GetError(&UIB);
1577}
1578
1579
Laurence Lundbladeee851742020-01-08 08:37:05 -08001580static inline int
1581MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001582{
1583 // Use of UsefulOutBuf is overkill, but convenient. The
1584 // length check performed here is useful.
1585 UsefulOutBuf UOB;
1586
1587 UsefulOutBuf_Init(&UOB, Pool);
1588 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1589 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1590 return UsefulOutBuf_GetError(&UOB);
1591}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001592
1593
1594/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001595 Internal function for an allocation, reallocation free and destuct.
1596
1597 Having only one function rather than one each per mode saves space in
1598 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001599
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001600 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1601 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001602static UsefulBuf
1603MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001604{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001605 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001606
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001607 uint32_t uPoolSize;
1608 uint32_t uFreeOffset;
1609
1610 if(uNewSize > UINT32_MAX) {
1611 // This allocator is only good up to 4GB. This check should
1612 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1613 goto Done;
1614 }
1615 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1616
1617 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1618 goto Done;
1619 }
1620
1621 if(uNewSize) {
1622 if(pMem) {
1623 // REALLOCATION MODE
1624 // Calculate pointer to the end of the memory pool. It is
1625 // assumed that pPool + uPoolSize won't wrap around by
1626 // assuming the caller won't pass a pool buffer in that is
1627 // not in legitimate memory space.
1628 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1629
1630 // Check that the pointer for reallocation is in the range of the
1631 // pool. This also makes sure that pointer math further down
1632 // doesn't wrap under or over.
1633 if(pMem >= pPool && pMem < pPoolEnd) {
1634 // Offset to start of chunk for reallocation. This won't
1635 // wrap under because of check that pMem >= pPool. Cast
1636 // is safe because the pool is always less than UINT32_MAX
1637 // because of check in QCBORDecode_SetMemPool().
1638 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1639
1640 // Check to see if the allocation will fit. uPoolSize -
1641 // uMemOffset will not wrap under because of check that
1642 // pMem is in the range of the uPoolSize by check above.
1643 if(uNewSize <= uPoolSize - uMemOffset) {
1644 ReturnValue.ptr = pMem;
1645 ReturnValue.len = uNewSize;
1646
1647 // Addition won't wrap around over because uNewSize was
1648 // checked to be sure it is less than the pool size.
1649 uFreeOffset = uMemOffset + uNewSize32;
1650 }
1651 }
1652 } else {
1653 // ALLOCATION MODE
1654 // uPoolSize - uFreeOffset will not underflow because this
1655 // pool implementation makes sure uFreeOffset is always
1656 // smaller than uPoolSize through this check here and
1657 // reallocation case.
1658 if(uNewSize <= uPoolSize - uFreeOffset) {
1659 ReturnValue.len = uNewSize;
1660 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001661 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001662 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001663 }
1664 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001665 if(pMem) {
1666 // FREE MODE
1667 // Cast is safe because of limit on pool size in
1668 // QCBORDecode_SetMemPool()
1669 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1670 } else {
1671 // DESTRUCT MODE
1672 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001673 }
1674 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001675
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001676 UsefulBuf Pool = {pPool, uPoolSize};
1677 MemPool_Pack(Pool, uFreeOffset);
1678
1679Done:
1680 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001681}
1682
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001683
Laurence Lundbladef6531662018-12-04 10:42:22 +09001684/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001685 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001686 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001687QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1688 UsefulBuf Pool,
1689 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001690{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001691 // The pool size and free mem offset are packed into the beginning
1692 // of the pool memory. This compile time check make sure the
1693 // constant in the header is correct. This check should optimize
1694 // down to nothing.
1695 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001696 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001697 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001698
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001699 // The pool size and free offset packed in to the beginning of pool
1700 // memory are only 32-bits. This check will optimize out on 32-bit
1701 // machines.
1702 if(Pool.len > UINT32_MAX) {
1703 return QCBOR_ERR_BUFFER_TOO_LARGE;
1704 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001705
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001706 // This checks that the pool buffer given is big enough.
1707 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1708 return QCBOR_ERR_BUFFER_TOO_SMALL;
1709 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001710
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001711 pMe->StringAllocator.pfAllocator = MemPool_Function;
1712 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1713 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001714
Laurence Lundblade30816f22018-11-10 13:40:22 +07001715 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001716}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001717
1718
1719
1720
1721/*
1722 * Public function. See qcbor_util.h
1723 */
1724static QCBORError
1725ConsumeItem(QCBORDecodeContext *pMe,
1726 const QCBORItem *pItemToConsume,
1727 uint_fast8_t *puNextNestLevel)
1728{
1729 QCBORError nReturn;
1730 QCBORItem Item;
1731
1732 if(pItemToConsume->uDataType == QCBOR_TYPE_MAP ||
1733 pItemToConsume->uDataType == QCBOR_TYPE_ARRAY) {
1734 /* There is only real work to do for maps and arrays */
1735
1736 /* This works for definite and indefinite length
1737 * maps and arrays by using the nesting level
1738 */
1739 do {
1740 nReturn = QCBORDecode_GetNext(pMe, &Item);
1741 if(nReturn != QCBOR_SUCCESS) {
1742 goto Done;
1743 }
1744 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
1745
1746 if(puNextNestLevel != NULL) {
1747 *puNextNestLevel = Item.uNextNestLevel;
1748 }
1749 nReturn = QCBOR_SUCCESS;
1750
1751 } else {
1752 /* item_to_consume is not a map or array */
1753 if(puNextNestLevel != NULL) {
1754 /* Just pass the nesting level through */
1755 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1756 }
1757 nReturn = QCBOR_SUCCESS;
1758 }
1759
1760Done:
1761 return nReturn;
1762}
1763
1764
1765/*
1766 * Public function. qcbor_util.h
1767 */
1768QCBORError
1769GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset)
1770{
1771 QCBORItem *pIterator;
1772 QCBORError nReturn;
1773
1774 // TODO: check we are in map mode
1775
1776 /* Clear structure holding the items found */
1777 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1778 pIterator->uDataType = QCBOR_TYPE_NONE;
1779 }
1780
1781 // Save the cursor and such used for pre-order traversal
1782 const size_t uSave = UsefulInputBuf_Tell(&(pMe->InBuf));
1783 const uint16_t uSaveCount = pMe->nesting.pCurrent->uCount;
1784 const void *pSaveCurrent = pMe->nesting.pCurrent;
1785
1786 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1787 pMe->nesting.pCurrent->uCount = 0;
1788 }
1789
1790 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
1791
1792 /* Loop over all the items in the map. They could be
1793 * deeply nested and this should handle both definite
1794 * and indefinite length maps and arrays, so this
1795 * adds some complexity. */
1796 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
1797
1798 while(1) {
1799 QCBORItem Item;
1800
1801 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1802
1803 if((nReturn = QCBORDecode_GetNext(pMe, &Item)) != QCBOR_SUCCESS) {
1804 /* Got non-well-formed CBOR */
1805 goto Done;
1806 }
1807
1808 // Loop over all the items to check this item against
1809 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1810 if(Item.uLabelType == QCBOR_TYPE_INT64) {
1811 if(Item.label.int64 != pIterator->label.int64) {
1812 continue; // Label didn't match
1813 }
1814 } else if(Item.uLabelType == QCBOR_TYPE_TEXT_STRING) {
1815 if(UsefulBuf_Compare(Item.label.string, pIterator->label.string)) {
1816 continue; // Label didn't match
1817 }
1818 } else {
1819 // Some label type that isn't supported; ignore it
1820 continue;
1821 }
1822 // A label match has been found
1823 if(pIterator->uDataType != QCBOR_TYPE_NONE) {
1824 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
1825 goto Done;
1826 }
1827 *pIterator = Item;
1828 if(puOffset) {
1829 *puOffset = uOffset;
1830 }
1831 }
1832
1833 /* Only looking at top-level data items, so just consume any
1834 * map or array encountered.*/
1835 uint_fast8_t uNextNestLevel;
1836
1837 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
1838 if(nReturn) {
1839 goto Done;
1840 }
1841 if(uNextNestLevel < uMapNestLevel) {
1842 nReturn = QCBOR_SUCCESS;
1843 /* Got all the items in the map. This is the non-error exit
1844 * from the loop. */
1845 // Cast OK because encoded CBOR is limited to UINT32_MAX
1846 pMe->uMapEndOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
1847 // record the offset here for exit to save CPU time
1848 break;
1849 }
1850 }
1851
1852Done:
1853 // Restore cursor for pre-order traversal
1854 pMe->nesting.pCurrent = (struct nesting_decode_level *)pSaveCurrent;
1855 pMe->nesting.pCurrent->uCount = uSaveCount;
1856 UsefulInputBuf_Seek(&(pMe->InBuf), uSave);
1857
1858 return nReturn;
1859}
1860
1861void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
1862{
1863 size_t uEndOffset;
1864
1865 if(pMe->uMapEndOffset) {
1866 uEndOffset = pMe->uMapEndOffset;
1867 } else {
1868 /* Call qcbor_util_get_items_in_map to do the work. */
1869 QCBORItem Dummy;
1870
1871 Dummy.uDataType = QCBOR_TYPE_NONE;
1872
1873 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, &uEndOffset);
1874
1875 (void)nReturn; // TODO:
1876 }
1877 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
1878
1879 DecodeNesting_DecrementCount(&(pMe->nesting));
1880}
1881
1882
1883QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
1884 int64_t nLabel,
1885 uint8_t uQcborType,
1886 QCBORItem *pItem)
1887{
1888 /* Call qcbor_util_get_items_in_map to do the work. */
1889 QCBORItem One[2];
1890
1891 One[0].uDataType = QCBOR_TYPE_INT64;
1892 One[0].label.int64 = nLabel;
1893 One[1].uDataType = QCBOR_TYPE_NONE; // Indicates end of array
1894
1895 QCBORError nReturn = GetItemsInMap(pMe, One, NULL);
1896 if(nReturn) {
1897 return nReturn;
1898 }
1899
1900 if(One[0].uDataType == QCBOR_TYPE_NONE) {
1901 return QCBOR_ERR_NOT_FOUND;
1902 }
1903
1904 if(One[0].uDataType != uQcborType) {
1905 return QCBOR_ERR_UNEXPECTED_TYPE;
1906 }
1907
1908 *pItem = One[0];
1909
1910 return QCBOR_SUCCESS;
1911}
1912
1913
1914QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
1915 const char *szLabel,
1916 uint8_t uQcborType,
1917 QCBORItem *pItem)
1918{
1919 /* Call qcbor_util_get_items_in_map to do the work. */
1920 QCBORItem One[2];
1921
1922 One[0].uDataType = QCBOR_TYPE_TEXT_STRING;
1923 One[0].label.string = UsefulBuf_FromSZ(szLabel);
1924 One[1].uDataType = QCBOR_TYPE_NONE; // Indicates end of array
1925
1926 QCBORError nReturn = GetItemsInMap(pMe, One, NULL);
1927 if(nReturn) {
1928 return nReturn;
1929 }
1930
1931 if(One[0].uDataType == QCBOR_TYPE_NONE) {
1932 return QCBOR_ERR_NOT_FOUND;
1933 }
1934
1935 if(One[0].uDataType != uQcborType) {
1936 return QCBOR_ERR_UNEXPECTED_TYPE;
1937 }
1938
1939 *pItem = One[0];
1940
1941 return QCBOR_SUCCESS;
1942}
1943
1944
1945void QCBORDecode_GetBstrInMap(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
1946{
1947 // TODO: error handling
1948 QCBORItem Item;
1949 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
1950 *pBstr = Item.val.string;
1951}
1952
1953
1954QCBORError QCBORDecode_EnterMapInMap(QCBORDecodeContext *pMe, int64_t nLabel)
1955{
1956 QCBORItem One[2];
1957
1958 One[0].uDataType = QCBOR_TYPE_INT64;
1959 One[0].label.int64 = nLabel;
1960 One[1].uDataType = QCBOR_TYPE_NONE;
1961
1962 size_t uOffset;
1963
1964 QCBORError r = GetItemsInMap(pMe, One, &uOffset);
1965
1966 if(r) {
1967 return r;
1968 }
1969
1970 if(One[0].uDataType != QCBOR_TYPE_MAP) {
1971 return QCBOR_ERR_UNEXPECTED_TYPE;
1972 }
1973
1974 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1975
1976 DecodeNesting_Descend(&(pMe->nesting), &One[1]);
1977
1978 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
1979 pMe->nesting.pCurrent->uMapMode = 1;
1980
1981 return 0;
1982}
1983
1984
1985QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
1986{
1987 QCBORItem One[2];
1988
1989 One[0].uDataType = QCBOR_TYPE_TEXT_STRING;
1990 One[0].label.string = UsefulBuf_FromSZ(szLabel);
1991 One[1].uDataType = QCBOR_TYPE_NONE;
1992
1993 size_t uOffset;
1994
1995 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
1996
1997 if(nReturn) {
1998 return nReturn;
1999 }
2000
2001 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2002 return QCBOR_ERR_UNEXPECTED_TYPE;
2003 }
2004
2005 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2006
2007 DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2008
2009 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2010 pMe->nesting.pCurrent->uMapMode = 1;
2011
2012 return 0;
2013}
2014
2015
2016
2017/* Next item must be map or this generates an error */
2018QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2019{
2020 QCBORItem Item;
2021
2022 /* Get the data item that is the map that is being searched */
2023 QCBORDecode_GetNext(pMe, &Item);
2024 if(Item.uDataType != QCBOR_TYPE_MAP) {
2025 return QCBOR_ERR_UNEXPECTED_TYPE;
2026 }
2027
2028
2029 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2030 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2031 pMe->nesting.pCurrent->uMapMode = 1;
2032
2033
2034 return QCBOR_SUCCESS;
2035}
2036
2037
2038
2039QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2040{
2041 return GetItemsInMap(pCtx, pItemList, NULL);
2042}
2043
2044
2045void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2046{
2047 // TODO: error handling
2048 QCBORItem Item;
2049 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2050 *pInt = Item.val.int64;
2051}
2052
2053
2054void QCBORDecode_RewindMap(QCBORDecodeContext *pCtxt)
2055{
2056
2057
2058}