blob: ab8ce577fc8509043acfce4c4e8bba4a15d3a373 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
2Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28==============================================================================*/
29
Laurence Lundblade624405d2018-09-18 20:10:47 -070030/*==============================================================================
31 Modifications beyond the version released on CAF are under the MIT license:
32
33 Copyright 2018 Laurence Lundblade
34
35 Permission is hereby granted, free of charge, to any person obtaining
36 a copy of this software and associated documentation files (the
37 "Software"), to deal in the Software without restriction, including
38 without limitation the rights to use, copy, modify, merge, publish,
39 distribute, sublicense, and/or sell copies of the Software, and to
40 permit persons to whom the Software is furnished to do so, subject to
41 the following conditions:
42
43 The above copyright notice and this permission notice shall be included
44 in all copies or substantial portions of the Software.
45
46 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
50 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
51 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53 SOFTWARE.
54 ==============================================================================*/
55
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056/*===================================================================================
57 FILE: qcbor_decode.c
58
59 DESCRIPTION: This file contains the implementation of QCBOR.
60
61 EDIT HISTORY FOR FILE:
62
63 This section contains comments describing changes made to the module.
64 Notice that changes are listed in reverse chronological order.
65
66 when who what, where, why
67 -------- ---- ---------------------------------------------------
68 02/04/17 llundbla Work on CPUs that don's require pointer alignment
69 by making use of changes in UsefulBuf
70 03/01/17 llundbla More data types; decoding improvements and fixes
71 11/13/16 llundbla Integrate most TZ changes back into github version.
72 09/30/16 gkanike Porting to TZ.
73 03/15/16 llundbla Initial Version.
74
75 =====================================================================================*/
76
77#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070078#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070079
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070080
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053081/*
82 This casts away the const-ness of a pointer, usually so it can be
83 freed or realloced.
84 */
85#define UNCONST_POINTER(ptr) ((void *)(ptr))
86
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070087
88/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080089 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090 */
91
92inline static int IsMapOrArray(uint8_t uDataType)
93{
94 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
95}
96
97inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
98{
99 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
100}
101
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700102inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700103{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700104 return pNesting->pCurrent->uCount == UINT16_MAX;
105}
106
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800107inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
108{
109 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
110}
111
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
113{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700114 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700116 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700117
118 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
119}
120
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800121// Process a break. This will either ascend the nesting or error out
122inline static int DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700123{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800124 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800126 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700127 }
128
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800129 // breaks can only occur when the map/array is indefinite length
130 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
131 return QCBOR_ERR_BAD_BREAK;
132 }
133
134 // if all OK, the break reduces the level of nesting
135 pNesting->pCurrent--;
136
137 return QCBOR_SUCCESS;
138}
139
140// Called on every single item except breaks including the opening of a map/array
141inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
142{
143 if(!DecodeNesting_IsNested(pNesting)) {
144 // at top level where there is no tracking
145 return;
146 }
147
148 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
149 // There is no count for indefinite length arrays/maps
150 return;
151 }
152
153 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700155
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800156 // Pop up nesting levels if the counts at the levels are zero
157 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700158 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800159 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
160 pNesting->pCurrent->uCount--;
161 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700162 }
163}
164
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800165// Called on every map/array
166inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700167{
168 int nReturn = QCBOR_SUCCESS;
169
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800170 if(pItem->val.uCount == 0) {
171 // Nothing to do for empty definite lenth arrays. They are just are
172 // effectively the same as an item that is not a map or array
173 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530174 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800175 }
176
177 // Error out if arrays is too long to handle
178 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700179 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
180 goto Done;
181 }
182
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
185 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
186 goto Done;
187 }
188
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800189 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700190 pNesting->pCurrent++;
191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192 // Record a few details for this nesting level
193 pNesting->pCurrent->uMajorType = pItem->uDataType;
194 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700195
196Done:
197 return nReturn;;
198}
199
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700200inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
201{
202 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
203}
204
205
206
207
208/*
209 Public function, see header file
210 */
211void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
212{
213 memset(me, 0, sizeof(QCBORDecodeContext));
214 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
215 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
216 // if the default normal mode of 0 was set.
217 me->uDecodeMode = nDecodeMode;
218 DecodeNesting_Init(&(me->nesting));
219}
220
221
222/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700223 Public function, see header file
224 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700225void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700226{
227 pCtx->pStringAllocator = (void *)pAllocator;
228}
229
230
231/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700232 This decodes the fundamental part of a CBOR data item, the type and number
233
234 This is the Counterpart to InsertEncodedTypeAndNumber().
235
236 This does the network->host byte order conversion. The conversion here
237 also results in the conversion for floats in addition to that for
238 lengths, tags and integer values.
239
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700240 This returns:
241 pnMajorType -- the major type for the item
242 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
243 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700245 */
246inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
247{
248 int nReturn;
249
250 // Get the initial byte that every CBOR data item has
251 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
252
253 // Break down the initial byte
254 const uint8_t uTmpMajorType = InitialByte >> 5;
255 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
256
257 // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700258 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700259 uint64_t uTmpValue;
260 switch(uAdditionalInfo) {
261
262 case LEN_IS_ONE_BYTE:
263 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
264 break;
265
266 case LEN_IS_TWO_BYTES:
267 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
268 break;
269
270 case LEN_IS_FOUR_BYTES:
271 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
272 break;
273
274 case LEN_IS_EIGHT_BYTES:
275 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
276 break;
277
278 case ADDINFO_RESERVED1: // reserved by CBOR spec
279 case ADDINFO_RESERVED2: // reserved by CBOR spec
280 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281 nReturn = QCBOR_ERR_UNSUPPORTED;
282 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700283
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700284 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700285 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700286 uTmpValue = uAdditionalInfo;
287 break;
288 }
289
290 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
291 // There is no harm in this. This following check takes care of catching all of
292 // these errors.
293
294 if(UsefulInputBuf_GetError(pUInBuf)) {
295 nReturn = QCBOR_ERR_HIT_END;
296 goto Done;
297 }
298
299 // All successful if we got here.
300 nReturn = QCBOR_SUCCESS;
301 *pnMajorType = uTmpMajorType;
302 *puNumber = uTmpValue;
303 *puAdditionalInfo = uAdditionalInfo;
304
305Done:
306 return nReturn;
307}
308
309
310/*
311 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
312 use it these days and the test vectors in the RFC are so. All integers in the CBOR
313 structure are positive and the major type indicates positive or negative.
314 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
315 and negative integers down to 2^x. Note that negative numbers can be one
316 more away from zero than positive.
317 Stdint, as far as I can tell, uses two's compliment to represent
318 negative integers.
319
320 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
321 used here in any way including in the interface
322 */
323inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
324{
325 int nReturn = QCBOR_SUCCESS;
326
327 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
328 if (uNumber <= INT64_MAX) {
329 pDecodedItem->val.int64 = (int64_t)uNumber;
330 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
331
332 } else {
333 pDecodedItem->val.uint64 = uNumber;
334 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
335
336 }
337 } else {
338 if(uNumber <= INT64_MAX) {
339 pDecodedItem->val.int64 = -uNumber-1;
340 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
341
342 } else {
343 // C can't represent a negative integer in this range
344 // so it is an error. todo -- test this condition
345 nReturn = QCBOR_ERR_INT_OVERFLOW;
346 }
347 }
348
349 return nReturn;
350}
351
352// Make sure #define value line up as DecodeSimple counts on this.
353#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
354#error QCBOR_TYPE_FALSE macro value wrong
355#endif
356
357#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
358#error QCBOR_TYPE_TRUE macro value wrong
359#endif
360
361#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
362#error QCBOR_TYPE_NULL macro value wrong
363#endif
364
365#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
366#error QCBOR_TYPE_UNDEF macro value wrong
367#endif
368
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700369#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
370#error QCBOR_TYPE_BREAK macro value wrong
371#endif
372
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700373#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
374#error QCBOR_TYPE_DOUBLE macro value wrong
375#endif
376
377#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
378#error QCBOR_TYPE_FLOAT macro value wrong
379#endif
380
381/*
382 Decode true, false, floats, break...
383 */
384
385inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
386{
387 int nReturn = QCBOR_SUCCESS;
388
389 // uAdditionalInfo is 5 bits from the initial byte
390 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
391 pDecodedItem->uDataType = uAdditionalInfo;
392
393 switch(uAdditionalInfo) {
394 case ADDINFO_RESERVED1: // 28
395 case ADDINFO_RESERVED2: // 29
396 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700397 nReturn = QCBOR_ERR_UNSUPPORTED;
398 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700399
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700400 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700401 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
402 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
403 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700404 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700405 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
406 break;
407 case DOUBLE_PREC_FLOAT:
408 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
409 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700410
411 case CBOR_SIMPLEV_FALSE: // 20
412 case CBOR_SIMPLEV_TRUE: // 21
413 case CBOR_SIMPLEV_NULL: // 22
414 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700415 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700416 break; // nothing to do
417
418 case CBOR_SIMPLEV_ONEBYTE: // 24
419 if(uNumber <= CBOR_SIMPLE_BREAK) {
420 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
421 nReturn = QCBOR_ERR_INVALID_CBOR;
422 goto Done;
423 }
424 // fall through intentionally
425
426 default: // 0-19
427 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
428 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
429 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
430 pDecodedItem->val.uSimple = (uint8_t)uNumber;
431 break;
432 }
433
434Done:
435 return nReturn;
436}
437
438
439
440/*
441 Decode text and byte strings
442 */
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530443inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700444{
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530445 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700446
447 int nReturn = QCBOR_ERR_HIT_END;
448
449 if(!UsefulBuf_IsNULLC(Bytes)) {
450 if(pAlloc) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530451 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen);
452 if(!UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700453 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
454 } else {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530455 return QCBOR_ERR_STRING_ALLOC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700456 }
457 } else {
458 pDecodedItem->val.string = Bytes;
459 }
460 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
461 nReturn = QCBOR_SUCCESS;
462 }
463
464 return nReturn;
465}
466
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467
468/*
469 Mostly just assign the right data type for the date string.
470 */
471inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
472{
473 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
474 return QCBOR_ERR_BAD_OPT_TAG;
475 }
476 pDecodedItem->val.dateString = Item.val.string;
477 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
478 pDecodedItem->uTagBits = Item.uTagBits;
479 pDecodedItem->uTag = Item.uTag;
480 return QCBOR_SUCCESS;
481}
482
483
484/*
485 Mostly just assign the right data type for the bignum.
486 */
487inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
488{
489 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
490 return QCBOR_ERR_BAD_OPT_TAG;
491 }
492 pDecodedItem->val.bigNum = Item.val.string;
493 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
494 pDecodedItem->uTagBits = Item.uTagBits;
495 pDecodedItem->uTag = Item.uTag;
496 return QCBOR_SUCCESS;
497}
498
499
500/*
501 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
502 */
503static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
504{
505 int nReturn = QCBOR_SUCCESS;
506
507 pDecodedItem->uTagBits = Item.uTagBits;
508 pDecodedItem->uTag = Item.uTag;
509 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
510 pDecodedItem->val.epochDate.fSecondsFraction = 0;
511
512 switch (Item.uDataType) {
513
514 case QCBOR_TYPE_INT64:
515 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
516 break;
517
518 case QCBOR_TYPE_UINT64:
519 if(Item.val.uint64 > INT64_MAX) {
520 nReturn = QCBOR_ERR_DATE_OVERFLOW;
521 goto Done;
522 }
523 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
524 break;
525
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800526 case QCBOR_TYPE_FLOAT:
527 // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
528 if(Item.val.fnum > INT64_MAX) {
529 nReturn = QCBOR_ERR_DATE_OVERFLOW;
530 goto Done;
531 }
532 pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
533 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
534 break;
535
536 case QCBOR_TYPE_DOUBLE:
537 if(Item.val.dfnum > INT64_MAX) {
538 nReturn = QCBOR_ERR_DATE_OVERFLOW;
539 goto Done;
540 }
541 pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
542 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
543 break;
544
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545 default:
546 nReturn = QCBOR_ERR_BAD_OPT_TAG;
547 }
548
549Done:
550 return nReturn;
551}
552
553
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700554
555
556// Make sure the constants align as this is assumed by the GetAnItem() implementation
557#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
558#error QCBOR_TYPE_ARRAY value not lined up with major type
559#endif
560#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
561#error QCBOR_TYPE_MAP value not lined up with major type
562#endif
563
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700565 This gets a single data item and decodes it including preceding optional tagging. This does not
566 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
567 maps are handled at the next level up in GetNext().
568
569 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
570 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700571 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700572static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
573{
574 int nReturn;
575
576 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
577 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
578 int uMajorType;
579 uint64_t uNumber;
580 uint8_t uAdditionalInfo;
581
582 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
583
584 // Error out here if we got into trouble on the type and number.
585 // The code after this will not work if the type and number is not good.
586 if(nReturn)
587 goto Done;
588
589 pDecodedItem->uTagBits = 0;
590 pDecodedItem->uTag = 0;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530591 pDecodedItem->uDataAlloc = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700592
593 // At this point the major type and the value are valid. We've got the type and the number that
594 // starts every CBOR data item.
595 switch (uMajorType) {
596 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
597 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
598 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
599 break;
600
601 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
602 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
603 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
604 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530605 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700606 } else {
607 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
608 }
609 break;
610
611 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
612 case CBOR_MAJOR_TYPE_MAP: // Major type 5
613 // Record the number of items in the array or map
614 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
615 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
616 goto Done;
617 }
618 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530619 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700620 } else {
621 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
622 }
623 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
624 break;
625
626 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
627 pDecodedItem->uTag = uNumber;
628 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
629 break;
630
631 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
632 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
633 break;
634
635 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
636 nReturn = QCBOR_ERR_UNSUPPORTED;
637 break;
638 }
639
640Done:
641 return nReturn;
642}
643
644
645
646/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800647 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530648 individual segment items together into one QCBORItem.
649
650 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700651 */
652static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
653{
654 int nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530655 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700656
657 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
658 if(nReturn) {
659 goto Done;
660 }
661
662 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530663 // code in this function from here down can be eliminated. Run tests, except
664 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700665
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800666 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700667 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
668 goto Done; // no need to do any work here on non-string types
669 }
670
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800671 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530672 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800673 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700674 }
675
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530676 // Can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700677 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700678 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
679 goto Done;
680 }
681
682 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800683 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700684 const uint8_t uStringType = pDecodedItem->uDataType;
685
686 // Loop getting segments of indefinite string
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530687 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700688 for(;;) {
689 // Get item for next segment
690 QCBORItem Item;
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530691 // NULL passed to never alloc segments of indefinite length strings
692 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700693 if(nReturn) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530694 break; // Error getting the next segment
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700695 }
696
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530697 // See if it is a marker at end of indefinite length string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700698 if(Item.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800699 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700700 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530701 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700702 break;
703 }
704
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530705 // Match data type of segment to type at beginning.
706 // Also catches error of other non-string types that don't belong.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700707 if(Item.uDataType != uStringType) {
708 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
709 break;
710 }
711
712 // Expand the buffer so it can fit
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530713 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
714 UNCONST_POINTER(FullString.ptr),
715 FullString.len + Item.val.string.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700716 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530717 // Allocation of memory for the string failed
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700718 nReturn = QCBOR_ERR_STRING_ALLOC;
719 break;
720 }
721
722 // Copy data to the end of it.
723 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
724 }
725
726Done:
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530727 if(pAlloc && nReturn && FullString.ptr) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700728 // Getting item failed, clean up the allocated memory
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530729 (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700730 }
731
732 return nReturn;
733}
734
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735
736/*
737 Returns an error if there was something wrong with the optional item or it couldn't
738 be handled.
739 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700740static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700741{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700742 int nReturn;
743
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530744 // TODO: optimize loop below so there is only one call to GetNext_FullItem?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700745 nReturn = GetNext_FullItem(me, pDecodedItem);
746 if(nReturn) {
747 goto Done;
748 }
749
750 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
751 goto Done;
752 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700753
754 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756
757 QCBORItem Item;
758
759 do {
760 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
761 uTagFlags |= 0x01LL << uTagToProcess;
762 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
763 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
764 }
765 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700766 greater than 63. Ignoring tags that are not understoof
767 is allowed by the standard. Multiple tags are
768 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700769
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700770 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700771 if(nReturn) {
772 // Bail out of the whole item fetch on any sort of error here
773 goto Done;
774 }
775
776 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
777 break;
778 }
779
780 uTagToProcess = Item.uTag;
781 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783
784 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 CBOR allows multiple tags on a data item. It also defines
786 a number of standard tag values, most of which are
787 less than 64. This code can deal with multiple tag
788 values that are less than 64 and the last tag of multiple
789 if the value is more than 64. Or said another way
790 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 At this point in this code. uTagFlags has all the flags
795 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700797 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 */
799
800 Item.uTagBits = uTagFlags;
801 Item.uTag = uTagToProcess;
802
803 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
804 case 0:
805 // No tags we know about. Pass them up
806 *pDecodedItem = Item;
807 break;
808
809 case QCBOR_TAGFLAG_DATE_STRING:
810 nReturn = DecodeDateString(Item, pDecodedItem);
811 break;
812
813 case QCBOR_TAGFLAG_DATE_EPOCH:
814 nReturn = DecodeDateEpoch(Item, pDecodedItem);
815 break;
816
817 case QCBOR_TAGFLAG_POS_BIGNUM:
818 case QCBOR_TAGFLAG_NEG_BIGNUM:
819 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
820 break;
821
822 default:
823 // Encountering some mixed up CBOR like something that
824 // is tagged as both a string and integer date.
825 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826 }
827
828Done:
829 return nReturn;
830}
831
832
833/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800834 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700836static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700838 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839 if(nReturn)
840 goto Done;
841
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800842 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
843 goto Done;
844 }
845
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846 // If in a map and the right decoding mode, get the label
847 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
848 // In a map and caller wants maps decoded, not treated as arrays
849
850 // Get the next item which will be the real data; Item will be the label
851 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530852 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700853 if(nReturn)
854 goto Done;
855
856 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
857 // strings are always good labels
858 pDecodedItem->label.string = LabelItem.val.string;
859 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
860 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
861 // It's not a string and we only want strings, probably for easy translation to JSON
862 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
863 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700865 pDecodedItem->label.int64 = LabelItem.val.int64;
866 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
867 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
868 pDecodedItem->label.uint64 = LabelItem.val.uint64;
869 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
870 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
871 pDecodedItem->label.string = LabelItem.val.string;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530872 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700873 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
874 } else {
875 // label is not an int or a string. It is an arrray
876 // or a float or such and this implementation doesn't handle that.
877 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
878 goto Done;
879 }
880 }
881
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882Done:
883 return nReturn;
884}
885
886
887/*
888 Public function, see header qcbor.h file
889 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
891{
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530892 // The public entry point for fetching and parsing the next QCBORItem.
893 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894 int nReturn;
895
Laurence Lundblade6de37062018-10-15 12:22:42 +0530896 nReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800897 if(nReturn) {
898 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530900
901 // Break ending arrays/maps are always processed at the end of this function.
902 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530903 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +0530904 nReturn = QCBOR_ERR_BAD_BREAK;
905 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530906 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907
Laurence Lundblade6de37062018-10-15 12:22:42 +0530908 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530909 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530910 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
911
912 // Process the item just received for descent or decrement, and
913 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800914 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800915 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800916 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800917 // Maps and arrays do count in as items in the map/array that encloses
918 // them so a decrement needs to be done for them too, but that is done
919 // only when all the items in them have been processed, not when they
920 // are opened.
921 } else {
922 // Decrement the count of items in the enclosing map/array
923 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +0530924 // triggers a decrement in the map/array above that and
925 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800926 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927 }
Laurence Lundblade6de37062018-10-15 12:22:42 +0530928 if(nReturn) {
929 goto Done;
930 }
931
932 // For indefinite length maps/arrays, looking at any and
933 // all breaks that might terminate them. The equivalent
934 // for definite length maps/arrays happens in
935 // DecodeNesting_DecrementCount().
936 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
937 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
938 // Peek forward one item to see if it is a break.
939 QCBORItem Peek;
940 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
941 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
942 if(nReturn) {
943 goto Done;
944 }
945 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
946 // It is not a break, rewind so it can be processed normally.
947 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
948 break;
949 }
950 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530951 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530952 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
953 if(nReturn) {
954 // break occured outside of an indefinite length array/map
955 goto Done;
956 }
957 }
958 }
959
960 // Tell the caller what level is next. This tells them what maps/arrays
961 // were closed out and makes it possible for them to reconstruct
962 // the tree with just the information returned by GetNext
963 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700964
965Done:
966 return nReturn;
967}
968
969
970/*
Laurence Lundblade6de37062018-10-15 12:22:42 +0530971 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530972 next one down. If a layer has no work to do for a particular item
973 it returns quickly.
974
975 - QCBORDecode_GetNext -- The top layer manages the beginnings and
976 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +0530977 out of maps/arrays. It processes all breaks that terminate
978 maps and arrays.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530979
980 - GetNext_MapEntry -- This handles the combining of two
981 items, the label and the data, that make up a map entry.
982 It only does work on maps. It combines the label and data
983 items into one labeled item.
984
985 - GetNext_TaggedItem -- This handles the type 6 tagged items.
986 It accumulates all the tags and combines them with the following
987 non-tagged item. If the tagged item is something that is understood
988 like a date, the decoding of that item is invoked.
989
990 - GetNext_FullItem -- This assembles the sub items that make up
991 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +0530992 string allocater to create contiguous space for the item. It
993 processes all breaks that are part of indefinite length strings.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530994
995 - GetNext_Item -- This gets and decodes the most atomic
996 item in CBOR, the thing with an initial byte containing
997 the major type.
998
999 */
1000
1001
1002/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001003 Public function, see header qcbor.h file
1004 */
1005int QCBORDecode_Finish(QCBORDecodeContext *me)
1006{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 int nReturn = QCBOR_SUCCESS;
1008
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001009 // Error out if all the maps/arrays are not closed out
1010 if(DecodeNesting_IsNested(&(me->nesting))) {
1011 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1012 goto Done;
1013 }
1014
1015 // Error out if not all the bytes are consumed
1016 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1017 nReturn = QCBOR_ERR_EXTRA_BYTES;
1018 }
1019
1020Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301021 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001022 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 if(me->pStringAllocator) {
1024 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1025 if(pAllocator->fDestructor) {
1026 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1027 }
1028 }
1029
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001031}
1032
1033
1034
Laurence Lundblade7023b952018-10-02 01:54:24 -07001035/*
1036
1037 Use the 64-bit map. 48 8-bit tags built in, 1 16 bit tag, 15 64-bit tags can be assigned as of interest
1038
1039 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301040
Laurence Lundblade7023b952018-10-02 01:54:24 -07001041
1042 */
1043
1044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001045/*
1046
1047Decoder errors handled in this file
1048
1049 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001051 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1052
1053 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1054
1055 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301056
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001057 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1058
1059 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1060
1061 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1062
1063 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1064
1065 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1066
1067 */
1068
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001069
1070
1071typedef struct {
1072 QCBORStringAllocator StringAllocator;
1073 uint8_t *pStart;
1074 uint8_t *pEnd;
1075 uint8_t *pFree;
1076} MemPool;
1077
1078
1079/*
1080 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1081 */
1082static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1083{
1084 MemPool *me = (MemPool *)ctx;
1085 void *pReturn = NULL;
1086
1087 if(pMem) {
1088 // Realloc case
1089 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001090 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1091 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001092 pReturn = pMem;
1093 }
1094 } else {
1095 // New chunk case
1096 if(me->pFree + uNewSize <= me->pEnd) {
1097 pReturn = me->pFree;
1098 me->pFree += uNewSize;
1099 }
1100 }
1101
1102 return (UsefulBuf){pReturn, uNewSize};
1103}
1104
1105
1106static void MemPool_Free(void *ctx, void *pOldMem)
1107{
1108 MemPool *me = (MemPool *)ctx;
1109 me->pFree = pOldMem;
1110}
1111
1112
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301113int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001114{
1115 if(Pool.len < sizeof(MemPool)+1) {
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301116 return 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001117 }
1118
1119 MemPool *pMP = (MemPool *)Pool.ptr;
1120
1121 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1122 pMP->StringAllocator.fFree = MemPool_Free;
1123 pMP->StringAllocator.fDestructor = NULL;
1124
Laurence Lundblade570fab52018-10-13 18:28:27 +08001125 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001127 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001128 pMP->StringAllocator.pAllocaterContext = pMP;
1129
1130 me->pStringAllocator = pMP;
1131 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301132
1133 return 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001134}
1135
1136
1137