blob: f789d0a11594508e2c531dc9df2d4c70ad05daee [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;
174 // Empty indefinite length maps and arrays are handled elsewhere; TODO: where?
175 }
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 Lundblade041ffa52018-10-07 11:43:51 +0700284 case LEN_IS_INDEFINITE:
285 // Fall through to see what happens: TODO: check this.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700286
287 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700288 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700289 uTmpValue = uAdditionalInfo;
290 break;
291 }
292
293 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
294 // There is no harm in this. This following check takes care of catching all of
295 // these errors.
296
297 if(UsefulInputBuf_GetError(pUInBuf)) {
298 nReturn = QCBOR_ERR_HIT_END;
299 goto Done;
300 }
301
302 // All successful if we got here.
303 nReturn = QCBOR_SUCCESS;
304 *pnMajorType = uTmpMajorType;
305 *puNumber = uTmpValue;
306 *puAdditionalInfo = uAdditionalInfo;
307
308Done:
309 return nReturn;
310}
311
312
313/*
314 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
315 use it these days and the test vectors in the RFC are so. All integers in the CBOR
316 structure are positive and the major type indicates positive or negative.
317 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
318 and negative integers down to 2^x. Note that negative numbers can be one
319 more away from zero than positive.
320 Stdint, as far as I can tell, uses two's compliment to represent
321 negative integers.
322
323 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
324 used here in any way including in the interface
325 */
326inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
327{
328 int nReturn = QCBOR_SUCCESS;
329
330 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
331 if (uNumber <= INT64_MAX) {
332 pDecodedItem->val.int64 = (int64_t)uNumber;
333 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
334
335 } else {
336 pDecodedItem->val.uint64 = uNumber;
337 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
338
339 }
340 } else {
341 if(uNumber <= INT64_MAX) {
342 pDecodedItem->val.int64 = -uNumber-1;
343 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
344
345 } else {
346 // C can't represent a negative integer in this range
347 // so it is an error. todo -- test this condition
348 nReturn = QCBOR_ERR_INT_OVERFLOW;
349 }
350 }
351
352 return nReturn;
353}
354
355// Make sure #define value line up as DecodeSimple counts on this.
356#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
357#error QCBOR_TYPE_FALSE macro value wrong
358#endif
359
360#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
361#error QCBOR_TYPE_TRUE macro value wrong
362#endif
363
364#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
365#error QCBOR_TYPE_NULL macro value wrong
366#endif
367
368#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
369#error QCBOR_TYPE_UNDEF macro value wrong
370#endif
371
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700372#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
373#error QCBOR_TYPE_BREAK macro value wrong
374#endif
375
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700376#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
377#error QCBOR_TYPE_DOUBLE macro value wrong
378#endif
379
380#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
381#error QCBOR_TYPE_FLOAT macro value wrong
382#endif
383
384/*
385 Decode true, false, floats, break...
386 */
387
388inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
389{
390 int nReturn = QCBOR_SUCCESS;
391
392 // uAdditionalInfo is 5 bits from the initial byte
393 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
394 pDecodedItem->uDataType = uAdditionalInfo;
395
396 switch(uAdditionalInfo) {
397 case ADDINFO_RESERVED1: // 28
398 case ADDINFO_RESERVED2: // 29
399 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700400 nReturn = QCBOR_ERR_UNSUPPORTED;
401 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700402
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700403 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700404 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
405 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
406 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700407 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700408 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
409 break;
410 case DOUBLE_PREC_FLOAT:
411 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
412 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700413
414 case CBOR_SIMPLEV_FALSE: // 20
415 case CBOR_SIMPLEV_TRUE: // 21
416 case CBOR_SIMPLEV_NULL: // 22
417 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700418 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700419 break; // nothing to do
420
421 case CBOR_SIMPLEV_ONEBYTE: // 24
422 if(uNumber <= CBOR_SIMPLE_BREAK) {
423 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
424 nReturn = QCBOR_ERR_INVALID_CBOR;
425 goto Done;
426 }
427 // fall through intentionally
428
429 default: // 0-19
430 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
431 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
432 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
433 pDecodedItem->val.uSimple = (uint8_t)uNumber;
434 break;
435 }
436
437Done:
438 return nReturn;
439}
440
441
442
443/*
444 Decode text and byte strings
445 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700446inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
447{
448 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uNumber);
449
450 int nReturn = QCBOR_ERR_HIT_END;
451
452 if(!UsefulBuf_IsNULLC(Bytes)) {
453 if(pAlloc) {
454 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uNumber);
455 if(UsefulBuf_IsNULL(NewMem)) {
456 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
457 } else {
458 // TODO: failure
459 }
460 } else {
461 pDecodedItem->val.string = Bytes;
462 }
463 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
464 nReturn = QCBOR_SUCCESS;
465 }
466
467 return nReturn;
468}
469
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700470
471/*
472 Mostly just assign the right data type for the date string.
473 */
474inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
475{
476 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
477 return QCBOR_ERR_BAD_OPT_TAG;
478 }
479 pDecodedItem->val.dateString = Item.val.string;
480 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
481 pDecodedItem->uTagBits = Item.uTagBits;
482 pDecodedItem->uTag = Item.uTag;
483 return QCBOR_SUCCESS;
484}
485
486
487/*
488 Mostly just assign the right data type for the bignum.
489 */
490inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
491{
492 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
493 return QCBOR_ERR_BAD_OPT_TAG;
494 }
495 pDecodedItem->val.bigNum = Item.val.string;
496 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
497 pDecodedItem->uTagBits = Item.uTagBits;
498 pDecodedItem->uTag = Item.uTag;
499 return QCBOR_SUCCESS;
500}
501
502
503/*
504 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
505 */
506static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
507{
508 int nReturn = QCBOR_SUCCESS;
509
510 pDecodedItem->uTagBits = Item.uTagBits;
511 pDecodedItem->uTag = Item.uTag;
512 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
513 pDecodedItem->val.epochDate.fSecondsFraction = 0;
514
515 switch (Item.uDataType) {
516
517 case QCBOR_TYPE_INT64:
518 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
519 break;
520
521 case QCBOR_TYPE_UINT64:
522 if(Item.val.uint64 > INT64_MAX) {
523 nReturn = QCBOR_ERR_DATE_OVERFLOW;
524 goto Done;
525 }
526 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
527 break;
528
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800529 case QCBOR_TYPE_FLOAT:
530 // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
531 if(Item.val.fnum > INT64_MAX) {
532 nReturn = QCBOR_ERR_DATE_OVERFLOW;
533 goto Done;
534 }
535 pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
536 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
537 break;
538
539 case QCBOR_TYPE_DOUBLE:
540 if(Item.val.dfnum > INT64_MAX) {
541 nReturn = QCBOR_ERR_DATE_OVERFLOW;
542 goto Done;
543 }
544 pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
545 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
546 break;
547
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700548 default:
549 nReturn = QCBOR_ERR_BAD_OPT_TAG;
550 }
551
552Done:
553 return nReturn;
554}
555
556
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700557
558
559// Make sure the constants align as this is assumed by the GetAnItem() implementation
560#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
561#error QCBOR_TYPE_ARRAY value not lined up with major type
562#endif
563#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
564#error QCBOR_TYPE_MAP value not lined up with major type
565#endif
566
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700568 This gets a single data item and decodes it including preceding optional tagging. This does not
569 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
570 maps are handled at the next level up in GetNext().
571
572 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
573 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700575static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
576{
577 int nReturn;
578
579 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
580 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
581 int uMajorType;
582 uint64_t uNumber;
583 uint8_t uAdditionalInfo;
584
585 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
586
587 // Error out here if we got into trouble on the type and number.
588 // The code after this will not work if the type and number is not good.
589 if(nReturn)
590 goto Done;
591
592 pDecodedItem->uTagBits = 0;
593 pDecodedItem->uTag = 0;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530594 pDecodedItem->uDataAlloc = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700595
596 // At this point the major type and the value are valid. We've got the type and the number that
597 // starts every CBOR data item.
598 switch (uMajorType) {
599 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
600 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
601 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
602 break;
603
604 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
605 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
606 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
607 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
608 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; // TODO: SIZE_MAX this is OK, right?
609 } else {
610 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
611 }
612 break;
613
614 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
615 case CBOR_MAJOR_TYPE_MAP: // Major type 5
616 // Record the number of items in the array or map
617 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
618 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
619 goto Done;
620 }
621 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
622 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length; TODO: a better way?
623 } else {
624 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
625 }
626 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
627 break;
628
629 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
630 pDecodedItem->uTag = uNumber;
631 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
632 break;
633
634 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
635 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
636 break;
637
638 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
639 nReturn = QCBOR_ERR_UNSUPPORTED;
640 break;
641 }
642
643Done:
644 return nReturn;
645}
646
647
648
649/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800650 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530651 individual segment items together into one QCBORItem.
652
653 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700654 */
655static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
656{
657 int nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530658 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700659
660 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
661 if(nReturn) {
662 goto Done;
663 }
664
665 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530666 // code in this function from here down can be eliminated. Run tests, except
667 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700668
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800669 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700670 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
671 goto Done; // no need to do any work here on non-string types
672 }
673
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800674 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530675 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800676 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700677 }
678
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530679 // Can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700680 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700681 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
682 goto Done;
683 }
684
685 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800686 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700687 const uint8_t uStringType = pDecodedItem->uDataType;
688
689 // Loop getting segments of indefinite string
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530690 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700691 for(;;) {
692 // Get item for next segment
693 QCBORItem Item;
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530694 // NULL passed to never alloc segments of indefinite length strings
695 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700696 if(nReturn) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530697 break; // Error getting the next segment
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700698 }
699
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530700 // See if it is a marker at end of indefinite length string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700701 if(Item.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800702 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700703 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530704 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700705 break;
706 }
707
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530708 // Match data type of segment to type at beginning.
709 // Also catches error of other non-string types that don't belong.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700710 if(Item.uDataType != uStringType) {
711 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
712 break;
713 }
714
715 // Expand the buffer so it can fit
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530716 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
717 UNCONST_POINTER(FullString.ptr),
718 FullString.len + Item.val.string.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700719 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530720 // Allocation of memory for the string failed
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700721 nReturn = QCBOR_ERR_STRING_ALLOC;
722 break;
723 }
724
725 // Copy data to the end of it.
726 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
727 }
728
729Done:
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530730 if(pAlloc && nReturn && FullString.ptr) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700731 // Getting item failed, clean up the allocated memory
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530732 (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700733 }
734
735 return nReturn;
736}
737
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700738
739/*
740 Returns an error if there was something wrong with the optional item or it couldn't
741 be handled.
742 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700743static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700745 int nReturn;
746
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800747 // TODO: optimize loop below so there is only one call to GetNext_FullItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700748 nReturn = GetNext_FullItem(me, pDecodedItem);
749 if(nReturn) {
750 goto Done;
751 }
752
753 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
754 goto Done;
755 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756
757 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700758 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759
760 QCBORItem Item;
761
762 do {
763 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
764 uTagFlags |= 0x01LL << uTagToProcess;
765 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
766 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
767 }
768 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769 greater than 63. Ignoring tags that are not understoof
770 is allowed by the standard. Multiple tags are
771 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700773 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700774 if(nReturn) {
775 // Bail out of the whole item fetch on any sort of error here
776 goto Done;
777 }
778
779 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
780 break;
781 }
782
783 uTagToProcess = Item.uTag;
784 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700786
787 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 CBOR allows multiple tags on a data item. It also defines
789 a number of standard tag values, most of which are
790 less than 64. This code can deal with multiple tag
791 values that are less than 64 and the last tag of multiple
792 if the value is more than 64. Or said another way
793 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700794
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700795 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700797 At this point in this code. uTagFlags has all the flags
798 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700800 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700801 */
802
803 Item.uTagBits = uTagFlags;
804 Item.uTag = uTagToProcess;
805
806 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
807 case 0:
808 // No tags we know about. Pass them up
809 *pDecodedItem = Item;
810 break;
811
812 case QCBOR_TAGFLAG_DATE_STRING:
813 nReturn = DecodeDateString(Item, pDecodedItem);
814 break;
815
816 case QCBOR_TAGFLAG_DATE_EPOCH:
817 nReturn = DecodeDateEpoch(Item, pDecodedItem);
818 break;
819
820 case QCBOR_TAGFLAG_POS_BIGNUM:
821 case QCBOR_TAGFLAG_NEG_BIGNUM:
822 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
823 break;
824
825 default:
826 // Encountering some mixed up CBOR like something that
827 // is tagged as both a string and integer date.
828 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700829 }
830
831Done:
832 return nReturn;
833}
834
835
836/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800837 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700839static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700841 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700842 if(nReturn)
843 goto Done;
844
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800845 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
846 goto Done;
847 }
848
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700849 // If in a map and the right decoding mode, get the label
850 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
851 // In a map and caller wants maps decoded, not treated as arrays
852
853 // Get the next item which will be the real data; Item will be the label
854 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530855 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700856 if(nReturn)
857 goto Done;
858
859 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
860 // strings are always good labels
861 pDecodedItem->label.string = LabelItem.val.string;
862 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
863 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
864 // It's not a string and we only want strings, probably for easy translation to JSON
865 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
866 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700867 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700868 pDecodedItem->label.int64 = LabelItem.val.int64;
869 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
870 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
871 pDecodedItem->label.uint64 = LabelItem.val.uint64;
872 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
873 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
874 pDecodedItem->label.string = LabelItem.val.string;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530875 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700876 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
877 } else {
878 // label is not an int or a string. It is an arrray
879 // or a float or such and this implementation doesn't handle that.
880 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
881 goto Done;
882 }
883 }
884
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885Done:
886 return nReturn;
887}
888
889
890/*
891 Public function, see header qcbor.h file
892 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
894{
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530895 // The public entry point for fetching and parsing the next QCBORItem.
896 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897 int nReturn;
898
Laurence Lundblade6de37062018-10-15 12:22:42 +0530899 nReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800900 if(nReturn) {
901 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530903
904 // Break ending arrays/maps are always processed at the end of this function.
905 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530906 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +0530907 nReturn = QCBOR_ERR_BAD_BREAK;
908 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530909 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910
Laurence Lundblade6de37062018-10-15 12:22:42 +0530911 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530912 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530913 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
914
915 // Process the item just received for descent or decrement, and
916 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800917 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800918 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800919 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800920 // Maps and arrays do count in as items in the map/array that encloses
921 // them so a decrement needs to be done for them too, but that is done
922 // only when all the items in them have been processed, not when they
923 // are opened.
924 } else {
925 // Decrement the count of items in the enclosing map/array
926 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +0530927 // triggers a decrement in the map/array above that and
928 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800929 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930 }
Laurence Lundblade6de37062018-10-15 12:22:42 +0530931 if(nReturn) {
932 goto Done;
933 }
934
935 // For indefinite length maps/arrays, looking at any and
936 // all breaks that might terminate them. The equivalent
937 // for definite length maps/arrays happens in
938 // DecodeNesting_DecrementCount().
939 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
940 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
941 // Peek forward one item to see if it is a break.
942 QCBORItem Peek;
943 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
944 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
945 if(nReturn) {
946 goto Done;
947 }
948 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
949 // It is not a break, rewind so it can be processed normally.
950 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
951 break;
952 }
953 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530954 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530955 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
956 if(nReturn) {
957 // break occured outside of an indefinite length array/map
958 goto Done;
959 }
960 }
961 }
962
963 // Tell the caller what level is next. This tells them what maps/arrays
964 // were closed out and makes it possible for them to reconstruct
965 // the tree with just the information returned by GetNext
966 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700967
968Done:
969 return nReturn;
970}
971
972
973/*
Laurence Lundblade6de37062018-10-15 12:22:42 +0530974 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530975 next one down. If a layer has no work to do for a particular item
976 it returns quickly.
977
978 - QCBORDecode_GetNext -- The top layer manages the beginnings and
979 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +0530980 out of maps/arrays. It processes all breaks that terminate
981 maps and arrays.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530982
983 - GetNext_MapEntry -- This handles the combining of two
984 items, the label and the data, that make up a map entry.
985 It only does work on maps. It combines the label and data
986 items into one labeled item.
987
988 - GetNext_TaggedItem -- This handles the type 6 tagged items.
989 It accumulates all the tags and combines them with the following
990 non-tagged item. If the tagged item is something that is understood
991 like a date, the decoding of that item is invoked.
992
993 - GetNext_FullItem -- This assembles the sub items that make up
994 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +0530995 string allocater to create contiguous space for the item. It
996 processes all breaks that are part of indefinite length strings.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530997
998 - GetNext_Item -- This gets and decodes the most atomic
999 item in CBOR, the thing with an initial byte containing
1000 the major type.
1001
1002 */
1003
1004
1005/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001006 Public function, see header qcbor.h file
1007 */
1008int QCBORDecode_Finish(QCBORDecodeContext *me)
1009{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001010 int nReturn = QCBOR_SUCCESS;
1011
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001012 // Error out if all the maps/arrays are not closed out
1013 if(DecodeNesting_IsNested(&(me->nesting))) {
1014 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1015 goto Done;
1016 }
1017
1018 // Error out if not all the bytes are consumed
1019 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1020 nReturn = QCBOR_ERR_EXTRA_BYTES;
1021 }
1022
1023Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301024 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001025 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 if(me->pStringAllocator) {
1027 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1028 if(pAllocator->fDestructor) {
1029 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1030 }
1031 }
1032
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001034}
1035
1036
1037
Laurence Lundblade7023b952018-10-02 01:54:24 -07001038/*
1039
1040 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
1041
1042 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301043
Laurence Lundblade7023b952018-10-02 01:54:24 -07001044
1045 */
1046
1047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001048/*
1049
1050Decoder errors handled in this file
1051
1052 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001054 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1055
1056 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1057
1058 - 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 +05301059
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001060 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1061
1062 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1063
1064 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1065
1066 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1067
1068 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1069
1070 */
1071
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072
1073
1074typedef struct {
1075 QCBORStringAllocator StringAllocator;
1076 uint8_t *pStart;
1077 uint8_t *pEnd;
1078 uint8_t *pFree;
1079} MemPool;
1080
1081
1082/*
1083 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1084 */
1085static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1086{
1087 MemPool *me = (MemPool *)ctx;
1088 void *pReturn = NULL;
1089
1090 if(pMem) {
1091 // Realloc case
1092 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001093 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1094 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001095 pReturn = pMem;
1096 }
1097 } else {
1098 // New chunk case
1099 if(me->pFree + uNewSize <= me->pEnd) {
1100 pReturn = me->pFree;
1101 me->pFree += uNewSize;
1102 }
1103 }
1104
1105 return (UsefulBuf){pReturn, uNewSize};
1106}
1107
1108
1109static void MemPool_Free(void *ctx, void *pOldMem)
1110{
1111 MemPool *me = (MemPool *)ctx;
1112 me->pFree = pOldMem;
1113}
1114
1115
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301116int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001117{
1118 if(Pool.len < sizeof(MemPool)+1) {
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301119 return 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001120 }
1121
1122 MemPool *pMP = (MemPool *)Pool.ptr;
1123
1124 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1125 pMP->StringAllocator.fFree = MemPool_Free;
1126 pMP->StringAllocator.fDestructor = NULL;
1127
Laurence Lundblade570fab52018-10-13 18:28:27 +08001128 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001129 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001130 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001131 pMP->StringAllocator.pAllocaterContext = pMP;
1132
1133 me->pStringAllocator = pMP;
1134 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301135
1136 return 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001137}
1138
1139
1140