blob: d12f732adf3613c2320eb8600b6b4357aa90bdd3 [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 Lundblade3f9ef042020-04-14 13:15:51 -070065inline static bool
66DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
67{
68 if(!DecodeNesting_IsNested(pNesting)){
69 // Always at end if at the top level of nesting
70 return true;
71 }
72
73 if(!pNesting->pCurrent->uMapMode) {
74 // If not in map mode then it is as IsNested says
75 return false;
76 }
77
78 // In map mode at the current nesting level. In this
79 // mode we are at the end of a pre-order traversal
80 // if the count is zero
81 // TODO: what about indefinite length maps & arrays?
82 return pNesting->pCurrent->uCount == 0;
83}
84
85
Laurence Lundbladeee851742020-01-08 08:37:05 -080086inline static int
87DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070088{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070089 return pNesting->pCurrent->uCount == UINT16_MAX;
90}
91
Laurence Lundbladeee851742020-01-08 08:37:05 -080092inline static uint8_t
93DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +080094{
Laurence Lundbladec5fef682020-01-25 11:38:45 -080095 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -070096 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -080097 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +080098}
99
Laurence Lundbladeee851742020-01-08 08:37:05 -0800100inline static int
101DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700103 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700105 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800106
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700107 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
108}
109
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800110// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800111inline static QCBORError
112DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700113{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800114 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800116 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700117 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800119 // breaks can only occur when the map/array is indefinite length
120 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
121 return QCBOR_ERR_BAD_BREAK;
122 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800123
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800124 // if all OK, the break reduces the level of nesting
125 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800126
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800127 return QCBOR_SUCCESS;
128}
129
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700130// Called on every single item except breaks including decode of a map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800131inline static void
132DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800133{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700134 while(!DecodeNesting_AtEnd(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700135 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800137 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700138 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800139 pNesting->pCurrent->uCount--;
140 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700141
142 if(pNesting->pCurrent->uCount != 0) {
143 // Did not close out an array or map, so nothing further
144 break;
145 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700146
147 if(pNesting->pCurrent->uMapMode) {
148 // In map mode the level-up must be done explicitly
149 break;
150 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700151
152 // Closed out an array or map so level up
153 pNesting->pCurrent--;
154
155 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156 }
157}
158
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800159// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800160inline static QCBORError
161DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700162{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700163 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800164
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800165 if(pItem->val.uCount == 0) {
166 // Nothing to do for empty definite lenth arrays. They are just are
167 // effectively the same as an item that is not a map or array
168 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530169 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800170 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800171
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172 // Error out if arrays is too long to handle
173 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
175 goto Done;
176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800177
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700179 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
180 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
181 goto Done;
182 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800183
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800184 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700185 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800186
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800187 // Record a few details for this nesting level
188 pNesting->pCurrent->uMajorType = pItem->uDataType;
189 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800190
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700191Done:
192 return nReturn;;
193}
194
Laurence Lundbladeee851742020-01-08 08:37:05 -0800195inline static void
196DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197{
198 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
199}
200
201
202
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700203/*
204 This list of built-in tags. Only add tags here that are
205 clearly established and useful. Once a tag is added here
206 it can't be taken out as that would break backwards compatibility.
207 There are only 48 slots available forever.
208 */
209static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800210 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
211 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
212 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
213 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
214 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
215 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700216 CBOR_TAG_COSE_ENCRYPTO,
217 CBOR_TAG_COSE_MAC0,
218 CBOR_TAG_COSE_SIGN1,
219 CBOR_TAG_ENC_AS_B64URL,
220 CBOR_TAG_ENC_AS_B64,
221 CBOR_TAG_ENC_AS_B16,
222 CBOR_TAG_CBOR,
223 CBOR_TAG_URI,
224 CBOR_TAG_B64URL,
225 CBOR_TAG_B64,
226 CBOR_TAG_REGEX,
227 CBOR_TAG_MIME,
228 CBOR_TAG_BIN_UUID,
229 CBOR_TAG_CWT,
230 CBOR_TAG_ENCRYPT,
231 CBOR_TAG_MAC,
232 CBOR_TAG_SIGN,
233 CBOR_TAG_GEO_COORD,
234 CBOR_TAG_CBOR_MAGIC
235};
236
237// This is used in a bit of cleverness in GetNext_TaggedItem() to
238// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800239// these types. This will break if the first six items in
240// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
241// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
242#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
243#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
244#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
245#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
246#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
247#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700248
Laurence Lundblade59289e52019-12-30 13:44:37 -0800249#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
250 QCBOR_TAGFLAG_DATE_EPOCH |\
251 QCBOR_TAGFLAG_POS_BIGNUM |\
252 QCBOR_TAGFLAG_NEG_BIGNUM |\
253 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
254 QCBOR_TAGFLAG_BIGFLOAT)
255
256#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
257 QCBOR_TAGFLAG_DATE_EPOCH |\
258 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700259 QCBOR_TAGFLAG_NEG_BIGNUM)
260
261#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
262#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
263#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
264
265static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
266{
267 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800268 /*
269 This is a cross-check to make sure the above array doesn't
270 accidentally get made too big. In normal conditions the above
271 test should optimize out as all the values are known at compile
272 time.
273 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700274 return -1;
275 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800276
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700277 if(uTag > UINT16_MAX) {
278 // This tag map works only on 16-bit tags
279 return -1;
280 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800281
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700282 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
283 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
284 return nTagBitIndex;
285 }
286 }
287 return -1; // Indicates no match
288}
289
290static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
291{
292 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
293 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
294 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
295 }
296 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800297
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700298 return -1; // Indicates no match
299}
300
301/*
302 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800303
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700304 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700306 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800307static QCBORError
308TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
309 uint64_t uTag,
310 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700311{
312 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
313 if(nTagBitIndex >= 0) {
314 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
315 *puTagBitIndex = (uint8_t)nTagBitIndex;
316 return QCBOR_SUCCESS;
317 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800318
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700319 if(pCallerConfiguredTagMap) {
320 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
321 return QCBOR_ERR_TOO_MANY_TAGS;
322 }
323 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
324 if(nTagBitIndex >= 0) {
325 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
326
327 *puTagBitIndex = (uint8_t)nTagBitIndex;
328 return QCBOR_SUCCESS;
329 }
330 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800331
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700332 return QCBOR_ERR_BAD_OPT_TAG;
333}
334
335
336
Laurence Lundbladeee851742020-01-08 08:37:05 -0800337/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800338 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
339
340 The following four functions are pretty wrappers for invocation of
341 the string allocator supplied by the caller.
342
Laurence Lundbladeee851742020-01-08 08:37:05 -0800343 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800344
Laurence Lundbladeee851742020-01-08 08:37:05 -0800345static inline void
346StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800347{
348 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
349}
350
Laurence Lundbladeee851742020-01-08 08:37:05 -0800351// StringAllocator_Reallocate called with pMem NULL is
352// equal to StringAllocator_Allocate()
353static inline UsefulBuf
354StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
355 void *pMem,
356 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800357{
358 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
359}
360
Laurence Lundbladeee851742020-01-08 08:37:05 -0800361static inline UsefulBuf
362StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800363{
364 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
365}
366
Laurence Lundbladeee851742020-01-08 08:37:05 -0800367static inline void
368StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800369{
370 if(pMe->pfAllocator) {
371 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
372 }
373}
374
375
376
Laurence Lundbladeee851742020-01-08 08:37:05 -0800377/*===========================================================================
378 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700379
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800380 See qcbor/qcbor_decode.h for definition of the object
381 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800382 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700383/*
384 Public function, see header file
385 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800386void QCBORDecode_Init(QCBORDecodeContext *me,
387 UsefulBufC EncodedCBOR,
388 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700389{
390 memset(me, 0, sizeof(QCBORDecodeContext));
391 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800392 // Don't bother with error check on decode mode. If a bad value is
393 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700394 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395 DecodeNesting_Init(&(me->nesting));
396}
397
398
399/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700400 Public function, see header file
401 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800402void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
403 QCBORStringAllocate pfAllocateFunction,
404 void *pAllocateContext,
405 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700406{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800407 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
408 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
409 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700410}
411
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800412
413/*
414 Public function, see header file
415 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800416void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
417 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700418{
419 me->pCallerConfiguredTagList = pTagList;
420}
421
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700422
423/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800424 This decodes the fundamental part of a CBOR data item, the type and
425 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800426
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700427 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800428
Laurence Lundbladeee851742020-01-08 08:37:05 -0800429 This does the network->host byte order conversion. The conversion
430 here also results in the conversion for floats in addition to that
431 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800432
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700433 This returns:
434 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800435
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800436 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800437 tags and floats and length for strings and arrays
438
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800439 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800441
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800442 The int type is preferred to uint8_t for some variables as this
443 avoids integer promotions, can reduce code size and makes
444 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700445 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800446inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
447 int *pnMajorType,
448 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800449 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700450{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700451 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800452
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700453 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800454 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800455
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700456 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800457 const int nTmpMajorType = nInitialByte >> 5;
458 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800460 // Where the number or argument accumulates
461 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800462
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800463 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464 // Need to get 1,2,4 or 8 additional argument bytes Map
465 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800466 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800467
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800468 // Loop getting all the bytes in the argument
469 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800470 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800471 // This shift and add gives the endian conversion
472 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
473 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800474 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800475 // The reserved and thus-far unused additional info values
476 nReturn = QCBOR_ERR_UNSUPPORTED;
477 goto Done;
478 } else {
479 // Less than 24, additional info is argument or 31, an indefinite length
480 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800483
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700484 if(UsefulInputBuf_GetError(pUInBuf)) {
485 nReturn = QCBOR_ERR_HIT_END;
486 goto Done;
487 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800488
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700489 // All successful if we got here.
490 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800491 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800492 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800493 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495Done:
496 return nReturn;
497}
498
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800499
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700500/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800501 CBOR doesn't explicitly specify two's compliment for integers but all
502 CPUs use it these days and the test vectors in the RFC are so. All
503 integers in the CBOR structure are positive and the major type
504 indicates positive or negative. CBOR can express positive integers
505 up to 2^x - 1 where x is the number of bits and negative integers
506 down to 2^x. Note that negative numbers can be one more away from
507 zero than positive. Stdint, as far as I can tell, uses two's
508 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800509
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700510 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800511 used carefully here, and in particular why it isn't used in the interface.
512 Also see
513 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
514
515 Int is used for values that need less than 16-bits and would be subject
516 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518inline static QCBORError
519DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700521 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800522
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700523 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
524 if (uNumber <= INT64_MAX) {
525 pDecodedItem->val.int64 = (int64_t)uNumber;
526 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800527
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528 } else {
529 pDecodedItem->val.uint64 = uNumber;
530 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532 }
533 } else {
534 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800535 // CBOR's representation of negative numbers lines up with the
536 // two-compliment representation. A negative integer has one
537 // more in range than a positive integer. INT64_MIN is
538 // equal to (-INT64_MAX) - 1.
539 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800541
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542 } else {
543 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000544 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545 nReturn = QCBOR_ERR_INT_OVERFLOW;
546 }
547 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549 return nReturn;
550}
551
552// Make sure #define value line up as DecodeSimple counts on this.
553#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
554#error QCBOR_TYPE_FALSE macro value wrong
555#endif
556
557#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
558#error QCBOR_TYPE_TRUE macro value wrong
559#endif
560
561#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
562#error QCBOR_TYPE_NULL macro value wrong
563#endif
564
565#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
566#error QCBOR_TYPE_UNDEF macro value wrong
567#endif
568
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700569#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
570#error QCBOR_TYPE_BREAK macro value wrong
571#endif
572
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700573#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
574#error QCBOR_TYPE_DOUBLE macro value wrong
575#endif
576
577#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
578#error QCBOR_TYPE_FLOAT macro value wrong
579#endif
580
581/*
582 Decode true, false, floats, break...
583 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800584inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800585DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700587 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800588
Laurence Lundbladeee851742020-01-08 08:37:05 -0800589 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800590 // above make sure uAdditionalInfo values line up with uDataType values.
591 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
592 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800593
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800594 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800595 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
596 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800597
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700598 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700599 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
600 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700601 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700602 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700603 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
604 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700605 break;
606 case DOUBLE_PREC_FLOAT:
607 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700608 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700609 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700611 case CBOR_SIMPLEV_FALSE: // 20
612 case CBOR_SIMPLEV_TRUE: // 21
613 case CBOR_SIMPLEV_NULL: // 22
614 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700615 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700618 case CBOR_SIMPLEV_ONEBYTE: // 24
619 if(uNumber <= CBOR_SIMPLE_BREAK) {
620 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700621 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622 goto Done;
623 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800624 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 default: // 0-19
628 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 /*
630 DecodeTypeAndNumber will make uNumber equal to
631 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
632 safe because the 2, 4 and 8 byte lengths of uNumber are in
633 the double/float cases above
634 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 pDecodedItem->val.uSimple = (uint8_t)uNumber;
636 break;
637 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639Done:
640 return nReturn;
641}
642
643
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530645 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800647inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
648 int nMajorType,
649 uint64_t uStrLen,
650 UsefulInputBuf *pUInBuf,
651 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700652{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700653 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800654
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800655 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
656 // This check makes the casts to size_t below safe.
657
658 // 4 bytes less than the largest sizeof() so this can be tested by
659 // putting a SIZE_MAX length in the CBOR test input (no one will
660 // care the limit on strings is 4 bytes shorter).
661 if(uStrLen > SIZE_MAX-4) {
662 nReturn = QCBOR_ERR_STRING_TOO_LONG;
663 goto Done;
664 }
665
666 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530667 if(UsefulBuf_IsNULLC(Bytes)) {
668 // Failed to get the bytes for this string item
669 nReturn = QCBOR_ERR_HIT_END;
670 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700671 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530672
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800673 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530674 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530676 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700677 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530678 goto Done;
679 }
680 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800681 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530682 } else {
683 // Normal case with no string allocator
684 pDecodedItem->val.string = Bytes;
685 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800686 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687 // Cast because ternary operator causes promotion to integer
688 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
689 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530691Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700692 return nReturn;
693}
694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697
698
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700699
700
Laurence Lundbladeee851742020-01-08 08:37:05 -0800701// Make sure the constants align as this is assumed by
702// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700703#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
704#error QCBOR_TYPE_ARRAY value not lined up with major type
705#endif
706#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
707#error QCBOR_TYPE_MAP value not lined up with major type
708#endif
709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800711 This gets a single data item and decodes it including preceding
712 optional tagging. This does not deal with arrays and maps and nesting
713 except to decode the data item introducing them. Arrays and maps are
714 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800715
Laurence Lundbladeee851742020-01-08 08:37:05 -0800716 Errors detected here include: an array that is too long to decode,
717 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800719static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
720 QCBORItem *pDecodedItem,
721 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700722{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700723 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800724
Laurence Lundbladeee851742020-01-08 08:37:05 -0800725 /*
726 Get the major type and the number. Number could be length of more
727 bytes or the value depending on the major type nAdditionalInfo is
728 an encoding of the length of the uNumber and is needed to decode
729 floats and doubles
730 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800731 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700732 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800734
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700735 memset(pDecodedItem, 0, sizeof(QCBORItem));
736
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800737 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800738
Laurence Lundbladeee851742020-01-08 08:37:05 -0800739 // Error out here if we got into trouble on the type and number. The
740 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700741 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700742 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700743 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundbladeee851742020-01-08 08:37:05 -0800745 // At this point the major type and the value are valid. We've got
746 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700748 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
749 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700751 nReturn = QCBOR_ERR_BAD_INT;
752 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700754 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800756
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700757 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
758 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800759 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
760 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
761 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
762 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530763 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800765 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700766 }
767 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
770 case CBOR_MAJOR_TYPE_MAP: // Major type 5
771 // Record the number of items in the array or map
772 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
773 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
774 goto Done;
775 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530777 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700778 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800779 // type conversion OK because of check above
780 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800782 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800783 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
784 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800786
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700787 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800788 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700789 nReturn = QCBOR_ERR_BAD_INT;
790 } else {
791 pDecodedItem->val.uTagV = uNumber;
792 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
793 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800795
Laurence Lundbladeee851742020-01-08 08:37:05 -0800796 case CBOR_MAJOR_TYPE_SIMPLE:
797 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800798 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801 default:
802 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700803 nReturn = QCBOR_ERR_UNSUPPORTED;
804 break;
805 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700807Done:
808 return nReturn;
809}
810
811
812
813/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800814 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800815 individual chunk items together into one QCBORItem using the string
816 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530818 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700819 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800820static inline QCBORError
821GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700822{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700823 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700824 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800825 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
826 &(me->StringAllocator) :
827 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530828 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800829
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800830 nReturn = GetNext_Item(&(me->InBuf),
831 pDecodedItem,
832 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833 if(nReturn) {
834 goto Done;
835 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700837 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530838 // code in this function from here down can be eliminated. Run tests, except
839 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800841 // Only do indefinite length processing on strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800842 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING &&
843 pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 goto Done; // no need to do any work here on non-string types
845 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800847 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530848 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800849 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700850 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800851
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530852 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800853 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700854 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
855 goto Done;
856 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800857
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700858 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800859 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700862 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700864 // Get item for next chunk
865 QCBORItem StringChunkItem;
866 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800867 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700868 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700869 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700870 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530872 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700873 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800874 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700875 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530876 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700877 break;
878 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800879
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700880 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530881 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700882 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800883 if(StringChunkItem.uDataType != uStringType ||
884 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700885 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700886 break;
887 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800888
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530889 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800890 // The first time throurgh FullString.ptr is NULL and this is
891 // equivalent to StringAllocator_Allocate()
892 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
893 UNCONST_POINTER(FullString.ptr),
894 FullString.len + StringChunkItem.val.string.len);
895
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700896 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530897 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700898 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 break;
900 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800901
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700902 // Copy new string chunk at the end of string so far.
903 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800907 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
908 // Getting the item failed, clean up the allocated memory
909 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800911
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700912 return nReturn;
913}
914
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700915
916/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800917 Gets all optional tag data items preceding a data item that is not an
918 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700919 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800920static QCBORError
921GetNext_TaggedItem(QCBORDecodeContext *me,
922 QCBORItem *pDecodedItem,
923 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700925 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700926 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700927 uint64_t uTagBits = 0;
928 if(pTags) {
929 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700931
Laurence Lundblade59289e52019-12-30 13:44:37 -0800932 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700933 for(;;) {
934 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700935 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700936 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700937 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700939 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
940 // Successful exit from loop; maybe got some tags, maybe not
941 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700942 break;
943 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700945 uint8_t uTagBitIndex;
946 // Tag was mapped, tag was not mapped, error with tag list
947 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800948
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700949 case QCBOR_SUCCESS:
950 // Successfully mapped the tag
951 uTagBits |= 0x01ULL << uTagBitIndex;
952 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700954 case QCBOR_ERR_BAD_OPT_TAG:
955 // Tag is not recognized. Do nothing
956 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700958 default:
959 // Error Condition
960 goto Done;
961 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800962
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700963 if(pTags) {
964 // Caller wants all tags recorded in the provided buffer
965 if(pTags->uNumUsed >= pTags->uNumAllocated) {
966 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
967 goto Done;
968 }
969 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
970 pTags->uNumUsed++;
971 }
972 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800973
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700974Done:
975 return nReturn;
976}
977
978
979/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800980 This layer takes care of map entries. It combines the label and data
981 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700982 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800983static inline QCBORError
984GetNext_MapEntry(QCBORDecodeContext *me,
985 QCBORItem *pDecodedItem,
986 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700987{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700988 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +0700989 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700990 if(nReturn)
991 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800993 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700994 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800995 goto Done;
996 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800997
Laurence Lundbladed61cbf32018-12-09 11:42:21 -0800998 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
999 // In a map and caller wants maps decoded, not treated as arrays
1000
1001 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1002 // If in a map and the right decoding mode, get the label
1003
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004 // Save label in pDecodedItem and get the next which will
1005 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001006 QCBORItem LabelItem = *pDecodedItem;
1007 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1008 if(nReturn)
1009 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301011 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001012
1013 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1014 // strings are always good labels
1015 pDecodedItem->label.string = LabelItem.val.string;
1016 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1017 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001018 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001019 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1020 goto Done;
1021 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1022 pDecodedItem->label.int64 = LabelItem.val.int64;
1023 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1024 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1025 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1026 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1027 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1028 pDecodedItem->label.string = LabelItem.val.string;
1029 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1030 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1031 } else {
1032 // label is not an int or a string. It is an arrray
1033 // or a float or such and this implementation doesn't handle that.
1034 // Also, tags on labels are ignored.
1035 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1036 goto Done;
1037 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001038 }
1039 } else {
1040 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001041 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1042 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1043 goto Done;
1044 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001045 // Decoding a map as an array
1046 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001047 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1048 // Cast is needed because of integer promotion
1049 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001050 }
1051 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001052
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053Done:
1054 return nReturn;
1055}
1056
1057
1058/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001059 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001060 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001062QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1063 QCBORItem *pDecodedItem,
1064 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001066 // Stack ptr/int: 2, QCBORItem : 64
1067
Laurence Lundblade30816f22018-11-10 13:40:22 +07001068 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001069
Laurence Lundblade1341c592020-04-11 14:19:05 -07001070 // Check if there are an TODO: incomplete comment
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001071 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1072 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1073 goto Done;
1074 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001075
1076 // This is to handle map and array mode
1077 if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
1078 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1079 goto Done;
1080 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001081
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001082 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001083 if(nReturn) {
1084 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301086
1087 // Break ending arrays/maps are always processed at the end of this function.
1088 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301089 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301090 nReturn = QCBOR_ERR_BAD_BREAK;
1091 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301092 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001093
Laurence Lundblade6de37062018-10-15 12:22:42 +05301094 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301095 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301096 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundblade6de37062018-10-15 12:22:42 +05301098 // Process the item just received for descent or decrement, and
1099 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001100 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001101 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001102 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001103 // Maps and arrays do count in as items in the map/array that encloses
1104 // them so a decrement needs to be done for them too, but that is done
1105 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001106 // are opened with the exception of an empty map or array.
1107 if(pDecodedItem->val.uCount == 0) {
1108 DecodeNesting_DecrementCount(&(me->nesting));
1109 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001110 } else {
1111 // Decrement the count of items in the enclosing map/array
1112 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301113 // triggers a decrement in the map/array above that and
1114 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001115 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001116 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301117 if(nReturn) {
1118 goto Done;
1119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundblade6de37062018-10-15 12:22:42 +05301121 // For indefinite length maps/arrays, looking at any and
1122 // all breaks that might terminate them. The equivalent
1123 // for definite length maps/arrays happens in
1124 // DecodeNesting_DecrementCount().
1125 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1126 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1127 // Peek forward one item to see if it is a break.
1128 QCBORItem Peek;
1129 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1130 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1131 if(nReturn) {
1132 goto Done;
1133 }
1134 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1135 // It is not a break, rewind so it can be processed normally.
1136 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1137 break;
1138 }
1139 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301140 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301141 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1142 if(nReturn) {
1143 // break occured outside of an indefinite length array/map
1144 goto Done;
1145 }
1146 }
1147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundblade6de37062018-10-15 12:22:42 +05301149 // Tell the caller what level is next. This tells them what maps/arrays
1150 // were closed out and makes it possible for them to reconstruct
1151 // the tree with just the information returned by GetNext
1152 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001153
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001154Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001155 if(nReturn != QCBOR_SUCCESS) {
1156 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1157 memset(pDecodedItem, 0, sizeof(QCBORItem));
1158 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001159 return nReturn;
1160}
1161
1162
Laurence Lundblade59289e52019-12-30 13:44:37 -08001163/*
1164 Mostly just assign the right data type for the date string.
1165 */
1166inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1167{
1168 // Stack Use: UsefulBuf 1 16
1169 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1170 return QCBOR_ERR_BAD_OPT_TAG;
1171 }
1172
1173 const UsefulBufC Temp = pDecodedItem->val.string;
1174 pDecodedItem->val.dateString = Temp;
1175 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1176 return QCBOR_SUCCESS;
1177}
1178
1179
1180/*
1181 Mostly just assign the right data type for the bignum.
1182 */
1183inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1184{
1185 // Stack Use: UsefulBuf 1 -- 16
1186 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1187 return QCBOR_ERR_BAD_OPT_TAG;
1188 }
1189 const UsefulBufC Temp = pDecodedItem->val.string;
1190 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001191 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001192 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1193 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001194 return QCBOR_SUCCESS;
1195}
1196
1197
1198/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001199 The epoch formatted date. Turns lots of different forms of encoding
1200 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001201 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001202static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001203{
1204 // Stack usage: 1
1205 QCBORError nReturn = QCBOR_SUCCESS;
1206
1207 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1208
1209 switch (pDecodedItem->uDataType) {
1210
1211 case QCBOR_TYPE_INT64:
1212 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1213 break;
1214
1215 case QCBOR_TYPE_UINT64:
1216 if(pDecodedItem->val.uint64 > INT64_MAX) {
1217 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1218 goto Done;
1219 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001220 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001221 break;
1222
1223 case QCBOR_TYPE_DOUBLE:
1224 {
1225 // This comparison needs to be done as a float before
1226 // conversion to an int64_t to be able to detect doubles
1227 // that are too large to fit into an int64_t. A double
1228 // has 52 bits of preceision. An int64_t has 63. Casting
1229 // INT64_MAX to a double actually causes a round up which
1230 // is bad and wrong for the comparison because it will
1231 // allow conversion of doubles that can't fit into a
1232 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1233 // the cutoff point as if that rounds up in conversion to
1234 // double it will still be less than INT64_MAX. 0x7ff is
1235 // picked because it has 11 bits set.
1236 //
1237 // INT64_MAX seconds is on the order of 10 billion years,
1238 // and the earth is less than 5 billion years old, so for
1239 // most uses this conversion error won't occur even though
1240 // doubles can go much larger.
1241 //
1242 // Without the 0x7ff there is a ~30 minute range of time
1243 // values 10 billion years in the past and in the future
1244 // where this this code would go wrong.
1245 const double d = pDecodedItem->val.dfnum;
1246 if(d > (double)(INT64_MAX - 0x7ff)) {
1247 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1248 goto Done;
1249 }
1250 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1251 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1252 }
1253 break;
1254
1255 default:
1256 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1257 goto Done;
1258 }
1259 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1260
1261Done:
1262 return nReturn;
1263}
1264
1265
1266#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1267/*
1268 Decode decimal fractions and big floats.
1269
1270 When called pDecodedItem must be the array that is tagged as a big
1271 float or decimal fraction, the array that has the two members, the
1272 exponent and mantissa.
1273
1274 This will fetch and decode the exponent and mantissa and put the
1275 result back into pDecodedItem.
1276 */
1277inline static QCBORError
1278QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1279{
1280 QCBORError nReturn;
1281
1282 // --- Make sure it is an array; track nesting level of members ---
1283 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1284 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1285 goto Done;
1286 }
1287
1288 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001289 // definite length arrays, but not for indefnite. Instead remember
1290 // the nesting level the two integers must be at, which is one
1291 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001292 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1293
1294 // --- Is it a decimal fraction or a bigfloat? ---
1295 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1296 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1297
1298 // --- Get the exponent ---
1299 QCBORItem exponentItem;
1300 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1301 if(nReturn != QCBOR_SUCCESS) {
1302 goto Done;
1303 }
1304 if(exponentItem.uNestingLevel != nNestLevel) {
1305 // Array is empty or a map/array encountered when expecting an int
1306 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1307 goto Done;
1308 }
1309 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1310 // Data arriving as an unsigned int < INT64_MAX has been converted
1311 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1312 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1313 // will be too large for this to handle and thus an error that will
1314 // get handled in the next else.
1315 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1316 } else {
1317 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1318 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1319 goto Done;
1320 }
1321
1322 // --- Get the mantissa ---
1323 QCBORItem mantissaItem;
1324 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1325 if(nReturn != QCBOR_SUCCESS) {
1326 goto Done;
1327 }
1328 if(mantissaItem.uNestingLevel != nNestLevel) {
1329 // Mantissa missing or map/array encountered when expecting number
1330 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1331 goto Done;
1332 }
1333 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1334 // Data arriving as an unsigned int < INT64_MAX has been converted
1335 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1336 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1337 // will be too large for this to handle and thus an error that
1338 // will get handled in an else below.
1339 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1340 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1341 // Got a good big num mantissa
1342 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1343 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001344 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1345 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1346 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001347 } else {
1348 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1349 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1350 goto Done;
1351 }
1352
1353 // --- Check that array only has the two numbers ---
1354 if(mantissaItem.uNextNestLevel == nNestLevel) {
1355 // Extra items in the decimal fraction / big num
1356 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1357 goto Done;
1358 }
1359
1360Done:
1361
1362 return nReturn;
1363}
1364#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1365
1366
1367/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001368 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001369 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001370QCBORError
1371QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1372 QCBORItem *pDecodedItem,
1373 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001374{
1375 QCBORError nReturn;
1376
1377 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1378 if(nReturn != QCBOR_SUCCESS) {
1379 goto Done;
1380 }
1381
1382#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1383#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1384#else
1385#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1386#endif
1387
1388 // Only pay attention to tags this code knows how to decode.
1389 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1390 case 0:
1391 // No tags at all or none we know about. Nothing to do.
1392 // This is the pass-through path of this function
1393 // that will mostly be taken when decoding any item.
1394 break;
1395
1396 case QCBOR_TAGFLAG_DATE_STRING:
1397 nReturn = DecodeDateString(pDecodedItem);
1398 break;
1399
1400 case QCBOR_TAGFLAG_DATE_EPOCH:
1401 nReturn = DecodeDateEpoch(pDecodedItem);
1402 break;
1403
1404 case QCBOR_TAGFLAG_POS_BIGNUM:
1405 case QCBOR_TAGFLAG_NEG_BIGNUM:
1406 nReturn = DecodeBigNum(pDecodedItem);
1407 break;
1408
1409#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1410 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1411 case QCBOR_TAGFLAG_BIGFLOAT:
1412 // For aggregate tagged types, what goes into pTags is only collected
1413 // from the surrounding data item, not the contents, so pTags is not
1414 // passed on here.
1415
1416 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1417 break;
1418#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1419
1420 default:
1421 // Encountering some mixed-up CBOR like something that
1422 // is tagged as both a string and integer date.
1423 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1424 }
1425
1426Done:
1427 if(nReturn != QCBOR_SUCCESS) {
1428 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1429 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1430 }
1431 return nReturn;
1432}
1433
1434
1435/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001436 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001437 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001438QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001439{
1440 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1441}
1442
1443
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001444/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301445 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301446 next one down. If a layer has no work to do for a particular item
1447 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001448
Laurence Lundblade59289e52019-12-30 13:44:37 -08001449 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1450 tagged data items, turning them into the local C representation.
1451 For the most simple it is just associating a QCBOR_TYPE with the data. For
1452 the complex ones that an aggregate of data items, there is some further
1453 decoding and a little bit of recursion.
1454
1455 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301456 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301457 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001458 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001459
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301460 - GetNext_MapEntry -- This handles the combining of two
1461 items, the label and the data, that make up a map entry.
1462 It only does work on maps. It combines the label and data
1463 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001464
Laurence Lundblade59289e52019-12-30 13:44:37 -08001465 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1466 tags into bit flags associated with the data item. No actual decoding
1467 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001468
Laurence Lundblade59289e52019-12-30 13:44:37 -08001469 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301470 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301471 string allocater to create contiguous space for the item. It
1472 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001473
Laurence Lundblade59289e52019-12-30 13:44:37 -08001474 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1475 atomic data item has a "major type", an integer "argument" and optionally
1476 some content. For text and byte strings, the content is the bytes
1477 that make up the string. These are the smallest data items that are
1478 considered to be well-formed. The content may also be other data items in
1479 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001480
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001481 Roughly this takes 300 bytes of stack for vars. Need to
1482 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001483
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301484 */
1485
1486
1487/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001488 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001489 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001490int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1491 const QCBORItem *pItem,
1492 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001493{
1494 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001495
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001496 uint8_t uTagBitIndex;
1497 // Do not care about errors in pCallerConfiguredTagMap here. They are
1498 // caught during GetNext() before this is called.
1499 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1500 return 0;
1501 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001502
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001503 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1504 return (uTagBit & pItem->uTagBits) != 0;
1505}
1506
1507
1508/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001509 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001510 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001511QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001512{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001513 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001514
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001515 // Error out if all the maps/arrays are not closed out
1516 if(DecodeNesting_IsNested(&(me->nesting))) {
1517 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1518 goto Done;
1519 }
1520
1521 // Error out if not all the bytes are consumed
1522 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1523 nReturn = QCBOR_ERR_EXTRA_BYTES;
1524 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001525
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001526Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301527 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001528 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001529 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001530
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001531 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001532}
1533
1534
1535
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001536/*
1537
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001538Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001539
Laurence Lundbladeee851742020-01-08 08:37:05 -08001540 - Hit end of input before it was expected while decoding type and
1541 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001542
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001543 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001544
Laurence Lundbladeee851742020-01-08 08:37:05 -08001545 - Hit end of input while decoding a text or byte string
1546 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001547
Laurence Lundbladeee851742020-01-08 08:37:05 -08001548 - Encountered conflicting tags -- e.g., an item is tagged both a date
1549 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001550
Laurence Lundbladeee851742020-01-08 08:37:05 -08001551 - Encontered an array or mapp that has too many items
1552 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001553
Laurence Lundbladeee851742020-01-08 08:37:05 -08001554 - Encountered array/map nesting that is too deep
1555 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001556
Laurence Lundbladeee851742020-01-08 08:37:05 -08001557 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1558 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001559
Laurence Lundbladeee851742020-01-08 08:37:05 -08001560 - The type of a map label is not a string or int
1561 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001562
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001563 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001564
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001565 */
1566
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001567
1568
Laurence Lundbladef6531662018-12-04 10:42:22 +09001569
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001570/* ===========================================================================
1571 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001572
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001573 This implements a simple sting allocator for indefinite length
1574 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1575 implements the function type QCBORStringAllocate and allows easy
1576 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001577
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001578 This particular allocator is built-in for convenience. The caller
1579 can implement their own. All of this following code will get
1580 dead-stripped if QCBORDecode_SetMemPool() is not called.
1581
1582 This is a very primitive memory allocator. It does not track
1583 individual allocations, only a high-water mark. A free or
1584 reallocation must be of the last chunk allocated.
1585
1586 The size of the pool and offset to free memory are packed into the
1587 first 8 bytes of the memory pool so we don't have to keep them in
1588 the decode context. Since the address of the pool may not be
1589 aligned, they have to be packed and unpacked as if they were
1590 serialized data of the wire or such.
1591
1592 The sizes packed in are uint32_t to be the same on all CPU types
1593 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001594 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001595
1596
Laurence Lundbladeee851742020-01-08 08:37:05 -08001597static inline int
1598MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001599{
1600 // Use of UsefulInputBuf is overkill, but it is convenient.
1601 UsefulInputBuf UIB;
1602
Laurence Lundbladeee851742020-01-08 08:37:05 -08001603 // Just assume the size here. It was checked during SetUp so
1604 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001605 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1606 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1607 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1608 return UsefulInputBuf_GetError(&UIB);
1609}
1610
1611
Laurence Lundbladeee851742020-01-08 08:37:05 -08001612static inline int
1613MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001614{
1615 // Use of UsefulOutBuf is overkill, but convenient. The
1616 // length check performed here is useful.
1617 UsefulOutBuf UOB;
1618
1619 UsefulOutBuf_Init(&UOB, Pool);
1620 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1621 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1622 return UsefulOutBuf_GetError(&UOB);
1623}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001624
1625
1626/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001627 Internal function for an allocation, reallocation free and destuct.
1628
1629 Having only one function rather than one each per mode saves space in
1630 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001631
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001632 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1633 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001634static UsefulBuf
1635MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001636{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001637 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001638
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001639 uint32_t uPoolSize;
1640 uint32_t uFreeOffset;
1641
1642 if(uNewSize > UINT32_MAX) {
1643 // This allocator is only good up to 4GB. This check should
1644 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1645 goto Done;
1646 }
1647 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1648
1649 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1650 goto Done;
1651 }
1652
1653 if(uNewSize) {
1654 if(pMem) {
1655 // REALLOCATION MODE
1656 // Calculate pointer to the end of the memory pool. It is
1657 // assumed that pPool + uPoolSize won't wrap around by
1658 // assuming the caller won't pass a pool buffer in that is
1659 // not in legitimate memory space.
1660 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1661
1662 // Check that the pointer for reallocation is in the range of the
1663 // pool. This also makes sure that pointer math further down
1664 // doesn't wrap under or over.
1665 if(pMem >= pPool && pMem < pPoolEnd) {
1666 // Offset to start of chunk for reallocation. This won't
1667 // wrap under because of check that pMem >= pPool. Cast
1668 // is safe because the pool is always less than UINT32_MAX
1669 // because of check in QCBORDecode_SetMemPool().
1670 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1671
1672 // Check to see if the allocation will fit. uPoolSize -
1673 // uMemOffset will not wrap under because of check that
1674 // pMem is in the range of the uPoolSize by check above.
1675 if(uNewSize <= uPoolSize - uMemOffset) {
1676 ReturnValue.ptr = pMem;
1677 ReturnValue.len = uNewSize;
1678
1679 // Addition won't wrap around over because uNewSize was
1680 // checked to be sure it is less than the pool size.
1681 uFreeOffset = uMemOffset + uNewSize32;
1682 }
1683 }
1684 } else {
1685 // ALLOCATION MODE
1686 // uPoolSize - uFreeOffset will not underflow because this
1687 // pool implementation makes sure uFreeOffset is always
1688 // smaller than uPoolSize through this check here and
1689 // reallocation case.
1690 if(uNewSize <= uPoolSize - uFreeOffset) {
1691 ReturnValue.len = uNewSize;
1692 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001693 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001694 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001695 }
1696 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001697 if(pMem) {
1698 // FREE MODE
1699 // Cast is safe because of limit on pool size in
1700 // QCBORDecode_SetMemPool()
1701 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1702 } else {
1703 // DESTRUCT MODE
1704 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001705 }
1706 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001707
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001708 UsefulBuf Pool = {pPool, uPoolSize};
1709 MemPool_Pack(Pool, uFreeOffset);
1710
1711Done:
1712 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001713}
1714
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001715
Laurence Lundbladef6531662018-12-04 10:42:22 +09001716/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001717 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001718 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001719QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1720 UsefulBuf Pool,
1721 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001722{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001723 // The pool size and free mem offset are packed into the beginning
1724 // of the pool memory. This compile time check make sure the
1725 // constant in the header is correct. This check should optimize
1726 // down to nothing.
1727 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001728 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001729 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001730
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001731 // The pool size and free offset packed in to the beginning of pool
1732 // memory are only 32-bits. This check will optimize out on 32-bit
1733 // machines.
1734 if(Pool.len > UINT32_MAX) {
1735 return QCBOR_ERR_BUFFER_TOO_LARGE;
1736 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001737
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001738 // This checks that the pool buffer given is big enough.
1739 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1740 return QCBOR_ERR_BUFFER_TOO_SMALL;
1741 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001742
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001743 pMe->StringAllocator.pfAllocator = MemPool_Function;
1744 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1745 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001746
Laurence Lundblade30816f22018-11-10 13:40:22 +07001747 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001748}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001749
Laurence Lundblade1341c592020-04-11 14:19:05 -07001750#include <stdio.h>
1751void printdecode(QCBORDecodeContext *pMe, const char *szName)
1752{
1753 printf("---%s---\nLevel Count Type Offset SaveCount\n", szName);
1754 for(int i = 0; i < 4 /*QCBOR_MAX_ARRAY_NESTING*/; i++) {
1755 const char *szX = (i == DecodeNesting_GetLevel(&(pMe->nesting))) ? "->" : " ";
1756 printf("%s %2d %5d %2d %6u %2d\n",
1757 szX,
1758 i,
1759 pMe->nesting.pMapsAndArrays[i].uCount,
1760 pMe->nesting.pMapsAndArrays[i].uMajorType,
1761 pMe->nesting.pMapsAndArrays[i].uOffset,
1762 pMe->nesting.pMapsAndArrays[i].uSaveCount
1763 );
1764 }
1765 printf("\n");
1766}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001767
1768
1769/*
1770 * Public function. See qcbor_util.h
1771 */
1772static QCBORError
1773ConsumeItem(QCBORDecodeContext *pMe,
1774 const QCBORItem *pItemToConsume,
1775 uint_fast8_t *puNextNestLevel)
1776{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001777 QCBORError nReturn;
1778 QCBORItem Item;
1779
1780 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001781
Laurence Lundblade1341c592020-04-11 14:19:05 -07001782 if(pItemToConsume->uDataType == QCBOR_TYPE_MAP ||
1783 pItemToConsume->uDataType == QCBOR_TYPE_ARRAY) {
1784 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001785
Laurence Lundblade1341c592020-04-11 14:19:05 -07001786 /* This works for definite and indefinite length
1787 * maps and arrays by using the nesting level
1788 */
1789 do {
1790 nReturn = QCBORDecode_GetNext(pMe, &Item);
1791 if(nReturn != QCBOR_SUCCESS) {
1792 goto Done;
1793 }
1794 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001795
Laurence Lundblade1341c592020-04-11 14:19:05 -07001796 if(puNextNestLevel != NULL) {
1797 *puNextNestLevel = Item.uNextNestLevel;
1798 }
1799 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001800
Laurence Lundblade1341c592020-04-11 14:19:05 -07001801 } else {
1802 /* item_to_consume is not a map or array */
1803 if(puNextNestLevel != NULL) {
1804 /* Just pass the nesting level through */
1805 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1806 }
1807 nReturn = QCBOR_SUCCESS;
1808 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001809
1810Done:
1811 return nReturn;
1812}
1813
1814
Laurence Lundblade1341c592020-04-11 14:19:05 -07001815/* Return true if the labels in Item1 and Item2 are the same.
1816 Works only for integer and string labels. Returns false
1817 for any other type. */
1818static inline bool
1819MatchLabel(QCBORItem Item1, QCBORItem Item2)
1820{
1821 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1822 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1823 return true;
1824 }
1825 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
1826 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1827 return true;
1828 }
1829 }
1830 /* Other label types are never matched */
1831 return false;
1832}
1833
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001834/*
1835 * Public function. qcbor_util.h
1836 */
1837QCBORError
1838GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset)
1839{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001840 QCBORItem *pIterator;
1841 QCBORError nReturn;
1842
1843
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001844
Laurence Lundblade1341c592020-04-11 14:19:05 -07001845 printdecode(pMe, "GetItemsInMapStart");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001846
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001847
Laurence Lundblade1341c592020-04-11 14:19:05 -07001848 // TODO: check we are in map mode
1849
1850 /* Clear structure holding the items found */
1851 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1852 pIterator->uDataType = QCBOR_TYPE_NONE;
1853 }
1854
1855 // Save the cursor and such used for pre-order traversal
1856/* const size_t uSave = UsefulInputBuf_Tell(&(pMe->InBuf));
1857 const uint16_t uSaveCount = pMe->nesting.pCurrent->uCount;
1858 struct nesting_decode_level *pSaveCurrent = pMe->nesting.pCurrent;
1859*/
1860 QCBORDecodeNesting N = pMe->nesting;
1861
1862 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1863 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
1864 }
1865
1866 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
1867
1868 /* Loop over all the items in the map. They could be
1869 * deeply nested and this should handle both definite
1870 * and indefinite length maps and arrays, so this
1871 * adds some complexity. */
1872 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
1873
1874 while(1) {
1875 QCBORItem Item;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001876
Laurence Lundblade1341c592020-04-11 14:19:05 -07001877 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001878
Laurence Lundblade1341c592020-04-11 14:19:05 -07001879 printdecode(pMe, "GetItemsInMapMid1");
1880
1881 if((nReturn = QCBORDecode_GetNext(pMe, &Item)) != QCBOR_SUCCESS) {
1882 /* Got non-well-formed CBOR */
1883 goto Done;
1884 }
1885
1886 printdecode(pMe, "GetItemsInMapMid2");
1887
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001888
Laurence Lundblade1341c592020-04-11 14:19:05 -07001889 // Loop over all the items to check this item against
1890 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1891 if(MatchLabel(Item, *pIterator)) {
1892 // A label match has been found
1893 if(pIterator->uDataType != QCBOR_TYPE_NONE) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001894 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
1895 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001896 }
1897
1898 /* Successful match. Return the item. */
1899 *pIterator = Item;
1900 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001901 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001902 }
1903 }
1904 }
1905
1906 /* Still have to consume the item that did or didn't match.
1907 The item could be a deeply nested array or map. */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001908
1909 /* Only looking at top-level data items, so just consume any
1910 * map or array encountered.*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07001911 uint_fast8_t uNextNestLevel;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001912
Laurence Lundblade1341c592020-04-11 14:19:05 -07001913 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
1914 if(nReturn) {
1915 goto Done;
1916 }
1917 if(uNextNestLevel < uMapNestLevel) {
1918 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001919 /* Got all the items in the map. This is the non-error exit
1920 * from the loop. */
1921 // Cast OK because encoded CBOR is limited to UINT32_MAX
Laurence Lundblade1341c592020-04-11 14:19:05 -07001922 pMe->uMapEndOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001923 // record the offset here for exit to save CPU time
Laurence Lundblade1341c592020-04-11 14:19:05 -07001924 break;
1925 }
1926 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001927
1928Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07001929 printdecode(pMe, "GetItemsInMapBeforeDone");
1930
1931
1932 // Restore cursor for pre-order traversal
1933 /*
1934 pMe->nesting.pCurrent = pSaveCurrent;
1935 pMe->nesting.pCurrent->uCount = uSaveCount;
1936 UsefulInputBuf_Seek(&(pMe->InBuf), uSave);
1937 */
1938 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001939
Laurence Lundblade1341c592020-04-11 14:19:05 -07001940 printdecode(pMe, "GetItemsInMapEnd");
1941
1942 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001943}
1944
1945void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
1946{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001947 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001948
Laurence Lundblade1341c592020-04-11 14:19:05 -07001949 if(pMe->uMapEndOffset) {
1950 uEndOffset = pMe->uMapEndOffset;
1951 // It is only valid once.
1952 pMe->uMapEndOffset = 0;
1953 } else {
1954 QCBORItem Dummy;
1955
1956 Dummy.uLabelType = QCBOR_TYPE_NONE;
1957
1958 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, &uEndOffset);
1959
1960 (void)nReturn; // TODO:
1961 }
1962
1963 printdecode(pMe, "start exit");
1964 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
1965
1966 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1967 pMe->nesting.pCurrent->uCount = 1;
1968 }
1969 DecodeNesting_DecrementCount(&(pMe->nesting));
1970 printdecode(pMe, "end exit");
1971
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001972}
1973
1974
1975QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07001976 int64_t nLabel,
1977 uint8_t uQcborType,
1978 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001979{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001980 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001981
Laurence Lundblade1341c592020-04-11 14:19:05 -07001982 One[0].uLabelType = QCBOR_TYPE_INT64;
1983 One[0].label.int64 = nLabel;
1984 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
1985
1986 QCBORError nReturn = GetItemsInMap(pMe, One, NULL);
1987 if(nReturn) {
1988 return nReturn;
1989 }
1990
1991 if(One[0].uDataType == QCBOR_TYPE_NONE) {
1992 return QCBOR_ERR_NOT_FOUND;
1993 }
1994
1995 if(One[0].uDataType != uQcborType) {
1996 return QCBOR_ERR_UNEXPECTED_TYPE;
1997 }
1998
1999 *pItem = One[0];
2000
2001 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002002}
2003
2004
2005QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07002006 const char *szLabel,
2007 uint8_t uQcborType,
2008 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002009{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002010 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002011
Laurence Lundblade1341c592020-04-11 14:19:05 -07002012 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2013 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2014 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2015
2016 QCBORError nReturn = GetItemsInMap(pMe, One, NULL);
2017 if(nReturn) {
2018 return nReturn;
2019 }
2020
2021 if(One[0].uDataType == QCBOR_TYPE_NONE) {
2022 return QCBOR_ERR_NOT_FOUND;
2023 }
2024
2025 if(One[0].uDataType != uQcborType) {
2026 return QCBOR_ERR_UNEXPECTED_TYPE;
2027 }
2028
2029 *pItem = One[0];
2030
2031 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002032}
2033
2034
2035void QCBORDecode_GetBstrInMap(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2036{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002037 // TODO: error handling
2038 QCBORItem Item;
2039 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2040 *pBstr = Item.val.string;
2041}
2042
2043void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2044{
2045 // TODO: error handling
2046 QCBORItem Item;
2047 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2048 *pBstr = Item.val.string;
2049}
2050
2051void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2052{
2053 // TODO: error handling
2054 QCBORItem Item;
2055 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2056 *pBstr = Item.val.string;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002057}
2058
2059
2060QCBORError QCBORDecode_EnterMapInMap(QCBORDecodeContext *pMe, int64_t nLabel)
2061{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002062 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002063
Laurence Lundblade1341c592020-04-11 14:19:05 -07002064 One[0].uLabelType = QCBOR_TYPE_INT64;
2065 One[0].label.int64 = nLabel;
2066 One[1].uLabelType = QCBOR_TYPE_NONE;
2067
2068 size_t uOffset;
2069
2070 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
2071
2072 if(nReturn) {
2073 return nReturn;
2074 }
2075
2076 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2077 return QCBOR_ERR_UNEXPECTED_TYPE;
2078 }
2079
2080 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2081
2082 DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2083
2084 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2085 pMe->nesting.pCurrent->uMapMode = 1;
2086
2087 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002088}
2089
2090
2091QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2092{
2093 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002094
Laurence Lundblade1341c592020-04-11 14:19:05 -07002095 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2096 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2097 One[1].uLabelType = QCBOR_TYPE_NONE;
2098
2099 size_t uOffset;
2100
2101 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
2102
2103 if(nReturn) {
2104 return nReturn;
2105 }
2106
2107 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2108 return QCBOR_ERR_UNEXPECTED_TYPE;
2109 }
2110
2111 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2112
2113 QCBORItem MapToEnter;
2114 QCBORDecode_GetNext(pMe, &MapToEnter);
2115
2116
2117 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2118
2119 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2120 pMe->nesting.pCurrent->uMapMode = 1;
2121 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2122
2123 printdecode(pMe, "Entered Map in Map");
2124
2125 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002126}
2127
2128
2129
Laurence Lundblade1341c592020-04-11 14:19:05 -07002130
2131QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2132{
2133 QCBORItem One[2];
2134
2135 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2136 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2137 One[1].uLabelType = QCBOR_TYPE_NONE;
2138
2139 size_t uOffset;
2140
2141 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset);
2142
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002143 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002144 return nReturn;
2145 }
2146
2147 if(One[0].uDataType != QCBOR_TYPE_ARRAY) {
2148 return QCBOR_ERR_UNEXPECTED_TYPE;
2149 }
2150
2151 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2152
2153 QCBORItem ArrayToEnter;
2154 QCBORDecode_GetNext(pMe, &ArrayToEnter);
2155
2156
2157 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2158
2159 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2160 pMe->nesting.pCurrent->uMapMode = 1;
2161 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2162
2163 printdecode(pMe, "Entered Array in Map");
2164
2165 return 0;
2166}
2167
2168
2169
2170
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002171/* Next item must be map or this generates an error */
2172QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2173{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002174 QCBORItem Item;
2175 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002176
2177 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002178 nReturn = QCBORDecode_GetNext(pMe, &Item);
2179 if(nReturn != QCBOR_SUCCESS) {
2180 return nReturn;
2181 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002182 if(Item.uDataType != QCBOR_TYPE_MAP) {
2183 return QCBOR_ERR_UNEXPECTED_TYPE;
2184 }
2185
2186 printdecode(pMe, "EnterMap");
2187
2188 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2189 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2190 pMe->nesting.pCurrent->uMapMode = 1;
2191 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002192
2193
Laurence Lundblade1341c592020-04-11 14:19:05 -07002194 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002195}
2196
2197
2198
2199QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2200{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002201 return GetItemsInMap(pCtx, pItemList, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002202}
2203
2204
2205void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2206{
2207 // TODO: error handling
2208 QCBORItem Item;
2209 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2210 *pInt = Item.val.int64;
2211}
2212
2213
Laurence Lundblade1341c592020-04-11 14:19:05 -07002214void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002215{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002216 // TODO: check for map mode
2217 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2218 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2219}
2220
2221
2222QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2223{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002224 QCBORItem Item;
2225 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002226
2227 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002228 nReturn = QCBORDecode_GetNext(pMe, &Item);
2229 if(nReturn != QCBOR_SUCCESS) {
2230 return nReturn;
2231 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002232 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2233 return QCBOR_ERR_UNEXPECTED_TYPE;
2234 }
2235
2236 printdecode(pMe, "EnterArray");
2237
2238 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2239 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2240 pMe->nesting.pCurrent->uMapMode = 1;
2241 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2242
2243
2244 return QCBOR_SUCCESS;
2245}
2246
2247
2248void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2249{
2250 // TODO: make sure we have entered an array
2251 // TODO: combine with code for map? It is the same so far.
2252 size_t uEndOffset;
2253
2254 if(pMe->uMapEndOffset) {
2255 uEndOffset = pMe->uMapEndOffset;
2256 // It is only valid once.
2257 pMe->uMapEndOffset = 0;
2258 } else {
2259 QCBORItem Dummy;
2260
2261 Dummy.uLabelType = QCBOR_TYPE_NONE;
2262
2263 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, &uEndOffset);
2264
2265 (void)nReturn; // TODO:
2266 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002267
Laurence Lundblade1341c592020-04-11 14:19:05 -07002268 printdecode(pMe, "start exit");
2269 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2270
2271 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2272 pMe->nesting.pCurrent->uCount = 1;
2273 }
2274 DecodeNesting_DecrementCount(&(pMe->nesting));
2275 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002276}