blob: a34afe120d6794b02f7c7ca47d3b239a63850526 [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
81
82/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080083 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070084 */
85
86inline static int IsMapOrArray(uint8_t uDataType)
87{
88 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
89}
90
91inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
92{
93 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
94}
95
Laurence Lundblade041ffa52018-10-07 11:43:51 +070096inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070097{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070098 return pNesting->pCurrent->uCount == UINT16_MAX;
99}
100
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800101inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
102{
103 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
104}
105
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700106inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
107{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700108 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700109 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700110 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700111
112 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
113}
114
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800115// Process a break. This will either ascend the nesting or error out
116inline static int DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700117{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800118 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700119 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800120 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700121 }
122
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800123 // breaks can only occur when the map/array is indefinite length
124 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
125 return QCBOR_ERR_BAD_BREAK;
126 }
127
128 // if all OK, the break reduces the level of nesting
129 pNesting->pCurrent--;
130
131 return QCBOR_SUCCESS;
132}
133
134// Called on every single item except breaks including the opening of a map/array
135inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
136{
137 if(!DecodeNesting_IsNested(pNesting)) {
138 // at top level where there is no tracking
139 return;
140 }
141
142 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
143 // There is no count for indefinite length arrays/maps
144 return;
145 }
146
147 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700149
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800150 // Pop up nesting levels if the counts at the levels are zero
151 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800153 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
154 pNesting->pCurrent->uCount--;
155 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156 }
157}
158
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800159// Called on every map/array
160inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700161{
162 int nReturn = QCBOR_SUCCESS;
163
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800164 if(pItem->val.uCount == 0) {
165 // Nothing to do for empty definite lenth arrays. They are just are
166 // effectively the same as an item that is not a map or array
167 goto Done;
168 // Empty indefinite length maps and arrays are handled elsewhere; TODO: where?
169 }
170
171 // Error out if arrays is too long to handle
172 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700173 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
174 goto Done;
175 }
176
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800177 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700178 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
179 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
180 goto Done;
181 }
182
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 pNesting->pCurrent++;
185
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800186 // Record a few details for this nesting level
187 pNesting->pCurrent->uMajorType = pItem->uDataType;
188 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189
190Done:
191 return nReturn;;
192}
193
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700194inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
195{
196 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
197}
198
199
200
201
202/*
203 Public function, see header file
204 */
205void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
206{
207 memset(me, 0, sizeof(QCBORDecodeContext));
208 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
209 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
210 // if the default normal mode of 0 was set.
211 me->uDecodeMode = nDecodeMode;
212 DecodeNesting_Init(&(me->nesting));
213}
214
215
216/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700217 Public function, see header file
218 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700219void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700220{
221 pCtx->pStringAllocator = (void *)pAllocator;
222}
223
224
225/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700226 This decodes the fundamental part of a CBOR data item, the type and number
227
228 This is the Counterpart to InsertEncodedTypeAndNumber().
229
230 This does the network->host byte order conversion. The conversion here
231 also results in the conversion for floats in addition to that for
232 lengths, tags and integer values.
233
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700234 This returns:
235 pnMajorType -- the major type for the item
236 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
237 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
238
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700239 */
240inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
241{
242 int nReturn;
243
244 // Get the initial byte that every CBOR data item has
245 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
246
247 // Break down the initial byte
248 const uint8_t uTmpMajorType = InitialByte >> 5;
249 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
250
251 // 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 +0700252 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700253 uint64_t uTmpValue;
254 switch(uAdditionalInfo) {
255
256 case LEN_IS_ONE_BYTE:
257 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
258 break;
259
260 case LEN_IS_TWO_BYTES:
261 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
262 break;
263
264 case LEN_IS_FOUR_BYTES:
265 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
266 break;
267
268 case LEN_IS_EIGHT_BYTES:
269 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
270 break;
271
272 case ADDINFO_RESERVED1: // reserved by CBOR spec
273 case ADDINFO_RESERVED2: // reserved by CBOR spec
274 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275 nReturn = QCBOR_ERR_UNSUPPORTED;
276 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700277
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700278 case LEN_IS_INDEFINITE:
279 // Fall through to see what happens: TODO: check this.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700280
281 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700282 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700283 uTmpValue = uAdditionalInfo;
284 break;
285 }
286
287 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
288 // There is no harm in this. This following check takes care of catching all of
289 // these errors.
290
291 if(UsefulInputBuf_GetError(pUInBuf)) {
292 nReturn = QCBOR_ERR_HIT_END;
293 goto Done;
294 }
295
296 // All successful if we got here.
297 nReturn = QCBOR_SUCCESS;
298 *pnMajorType = uTmpMajorType;
299 *puNumber = uTmpValue;
300 *puAdditionalInfo = uAdditionalInfo;
301
302Done:
303 return nReturn;
304}
305
306
307/*
308 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
309 use it these days and the test vectors in the RFC are so. All integers in the CBOR
310 structure are positive and the major type indicates positive or negative.
311 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
312 and negative integers down to 2^x. Note that negative numbers can be one
313 more away from zero than positive.
314 Stdint, as far as I can tell, uses two's compliment to represent
315 negative integers.
316
317 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
318 used here in any way including in the interface
319 */
320inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
321{
322 int nReturn = QCBOR_SUCCESS;
323
324 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
325 if (uNumber <= INT64_MAX) {
326 pDecodedItem->val.int64 = (int64_t)uNumber;
327 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
328
329 } else {
330 pDecodedItem->val.uint64 = uNumber;
331 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
332
333 }
334 } else {
335 if(uNumber <= INT64_MAX) {
336 pDecodedItem->val.int64 = -uNumber-1;
337 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
338
339 } else {
340 // C can't represent a negative integer in this range
341 // so it is an error. todo -- test this condition
342 nReturn = QCBOR_ERR_INT_OVERFLOW;
343 }
344 }
345
346 return nReturn;
347}
348
349// Make sure #define value line up as DecodeSimple counts on this.
350#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
351#error QCBOR_TYPE_FALSE macro value wrong
352#endif
353
354#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
355#error QCBOR_TYPE_TRUE macro value wrong
356#endif
357
358#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
359#error QCBOR_TYPE_NULL macro value wrong
360#endif
361
362#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
363#error QCBOR_TYPE_UNDEF macro value wrong
364#endif
365
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700366#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
367#error QCBOR_TYPE_BREAK macro value wrong
368#endif
369
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700370#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
371#error QCBOR_TYPE_DOUBLE macro value wrong
372#endif
373
374#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
375#error QCBOR_TYPE_FLOAT macro value wrong
376#endif
377
378/*
379 Decode true, false, floats, break...
380 */
381
382inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
383{
384 int nReturn = QCBOR_SUCCESS;
385
386 // uAdditionalInfo is 5 bits from the initial byte
387 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
388 pDecodedItem->uDataType = uAdditionalInfo;
389
390 switch(uAdditionalInfo) {
391 case ADDINFO_RESERVED1: // 28
392 case ADDINFO_RESERVED2: // 29
393 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700394 nReturn = QCBOR_ERR_UNSUPPORTED;
395 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700396
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700397 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700398 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
399 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
400 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700401 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700402 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
403 break;
404 case DOUBLE_PREC_FLOAT:
405 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
406 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700407
408 case CBOR_SIMPLEV_FALSE: // 20
409 case CBOR_SIMPLEV_TRUE: // 21
410 case CBOR_SIMPLEV_NULL: // 22
411 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700412 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700413 break; // nothing to do
414
415 case CBOR_SIMPLEV_ONEBYTE: // 24
416 if(uNumber <= CBOR_SIMPLE_BREAK) {
417 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
418 nReturn = QCBOR_ERR_INVALID_CBOR;
419 goto Done;
420 }
421 // fall through intentionally
422
423 default: // 0-19
424 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
425 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
426 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
427 pDecodedItem->val.uSimple = (uint8_t)uNumber;
428 break;
429 }
430
431Done:
432 return nReturn;
433}
434
435
436
437/*
438 Decode text and byte strings
439 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700440inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
441{
442 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uNumber);
443
444 int nReturn = QCBOR_ERR_HIT_END;
445
446 if(!UsefulBuf_IsNULLC(Bytes)) {
447 if(pAlloc) {
448 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uNumber);
449 if(UsefulBuf_IsNULL(NewMem)) {
450 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
451 } else {
452 // TODO: failure
453 }
454 } else {
455 pDecodedItem->val.string = Bytes;
456 }
457 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
458 nReturn = QCBOR_SUCCESS;
459 }
460
461 return nReturn;
462}
463
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700464
465/*
466 Mostly just assign the right data type for the date string.
467 */
468inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
469{
470 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
471 return QCBOR_ERR_BAD_OPT_TAG;
472 }
473 pDecodedItem->val.dateString = Item.val.string;
474 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
475 pDecodedItem->uTagBits = Item.uTagBits;
476 pDecodedItem->uTag = Item.uTag;
477 return QCBOR_SUCCESS;
478}
479
480
481/*
482 Mostly just assign the right data type for the bignum.
483 */
484inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
485{
486 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
487 return QCBOR_ERR_BAD_OPT_TAG;
488 }
489 pDecodedItem->val.bigNum = Item.val.string;
490 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
491 pDecodedItem->uTagBits = Item.uTagBits;
492 pDecodedItem->uTag = Item.uTag;
493 return QCBOR_SUCCESS;
494}
495
496
497/*
498 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
499 */
500static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
501{
502 int nReturn = QCBOR_SUCCESS;
503
504 pDecodedItem->uTagBits = Item.uTagBits;
505 pDecodedItem->uTag = Item.uTag;
506 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
507 pDecodedItem->val.epochDate.fSecondsFraction = 0;
508
509 switch (Item.uDataType) {
510
511 case QCBOR_TYPE_INT64:
512 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
513 break;
514
515 case QCBOR_TYPE_UINT64:
516 if(Item.val.uint64 > INT64_MAX) {
517 nReturn = QCBOR_ERR_DATE_OVERFLOW;
518 goto Done;
519 }
520 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
521 break;
522
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800523 case QCBOR_TYPE_FLOAT:
524 // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
525 if(Item.val.fnum > INT64_MAX) {
526 nReturn = QCBOR_ERR_DATE_OVERFLOW;
527 goto Done;
528 }
529 pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
530 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
531 break;
532
533 case QCBOR_TYPE_DOUBLE:
534 if(Item.val.dfnum > INT64_MAX) {
535 nReturn = QCBOR_ERR_DATE_OVERFLOW;
536 goto Done;
537 }
538 pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
539 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
540 break;
541
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542 default:
543 nReturn = QCBOR_ERR_BAD_OPT_TAG;
544 }
545
546Done:
547 return nReturn;
548}
549
550
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700551
552
553// Make sure the constants align as this is assumed by the GetAnItem() implementation
554#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
555#error QCBOR_TYPE_ARRAY value not lined up with major type
556#endif
557#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
558#error QCBOR_TYPE_MAP value not lined up with major type
559#endif
560
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700562 This gets a single data item and decodes it including preceding optional tagging. This does not
563 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
564 maps are handled at the next level up in GetNext().
565
566 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
567 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700569
570static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
571{
572 int nReturn;
573
574 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
575 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
576 int uMajorType;
577 uint64_t uNumber;
578 uint8_t uAdditionalInfo;
579
580 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
581
582 // Error out here if we got into trouble on the type and number.
583 // The code after this will not work if the type and number is not good.
584 if(nReturn)
585 goto Done;
586
587 pDecodedItem->uTagBits = 0;
588 pDecodedItem->uTag = 0;
589 pDecodedItem->uAllocated = 0;
590
591 // At this point the major type and the value are valid. We've got the type and the number that
592 // starts every CBOR data item.
593 switch (uMajorType) {
594 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
595 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
596 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
597 break;
598
599 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
600 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
601 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
602 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
603 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; // TODO: SIZE_MAX this is OK, right?
604 } else {
605 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
606 }
607 break;
608
609 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
610 case CBOR_MAJOR_TYPE_MAP: // Major type 5
611 // Record the number of items in the array or map
612 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
613 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
614 goto Done;
615 }
616 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
617 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length; TODO: a better way?
618 } else {
619 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
620 }
621 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
622 break;
623
624 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
625 pDecodedItem->uTag = uNumber;
626 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
627 break;
628
629 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
630 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
631 break;
632
633 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
634 nReturn = QCBOR_ERR_UNSUPPORTED;
635 break;
636 }
637
638Done:
639 return nReturn;
640}
641
642
643
644/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800645 This layer deals with indefinite length strings. It pulls all the
646 individual segment items together into one QCBORItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700647 */
648static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
649{
650 int nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530651 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700652
653 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
654 if(nReturn) {
655 goto Done;
656 }
657
658 // To reduce code size by removing support for indefinite length strings, the
659 // code in this function from here down can be eliminated. Run tests to be sure
660 // all is OK if you remove this.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700661
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800662 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700663 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
664 goto Done; // no need to do any work here on non-string types
665 }
666
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800667 // Is this a string with an indefinite length?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700668 if(pDecodedItem->val.string.len != SIZE_MAX) { // TODO: is this right? Is there a better way to mark this?
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800669 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700670 }
671
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800672 // can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700673 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700674 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
675 goto Done;
676 }
677
678 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800679 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700680 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530681 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700682
683 // Loop getting segments of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700684 for(;;) {
685 // Get item for next segment
686 QCBORItem Item;
687 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL); // Never alloc segments of indefinite length strings
688 if(nReturn) {
689 // Error getting the next segment
690 break;
691 }
692
693 // See if it is marker at end of indefinite length string
694 if(Item.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800695 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700696 pDecodedItem->val.string = FullString;
697 pDecodedItem->uAllocated = 1;
698 break;
699 }
700
701 // Match data type of segment to type at beginning
702 if(Item.uDataType != uStringType) {
703 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
704 break;
705 }
706
707 // Expand the buffer so it can fit
708 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, (void *)FullString.ptr, FullString.len + Item.val.string.len);
709 if(UsefulBuf_IsNULL(NewMem)) {
710 nReturn = QCBOR_ERR_STRING_ALLOC;
711 break;
712 }
713
714 // Copy data to the end of it.
715 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
716 }
717
718Done:
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530719 if(pAlloc && nReturn && FullString.ptr) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700720 // Getting item failed, clean up the allocated memory
721 (pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
722 }
723
724 return nReturn;
725}
726
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727
728/*
729 Returns an error if there was something wrong with the optional item or it couldn't
730 be handled.
731 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700732static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700734 int nReturn;
735
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800736 // TODO: optimize loop below so there is only one call to GetNext_FullItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700737 nReturn = GetNext_FullItem(me, pDecodedItem);
738 if(nReturn) {
739 goto Done;
740 }
741
742 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
743 goto Done;
744 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745
746 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700747 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748
749 QCBORItem Item;
750
751 do {
752 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
753 uTagFlags |= 0x01LL << uTagToProcess;
754 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
755 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
756 }
757 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700758 greater than 63. Ignoring tags that are not understoof
759 is allowed by the standard. Multiple tags are
760 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700761
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700762 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763 if(nReturn) {
764 // Bail out of the whole item fetch on any sort of error here
765 goto Done;
766 }
767
768 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
769 break;
770 }
771
772 uTagToProcess = Item.uTag;
773 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700774
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700775
776 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 CBOR allows multiple tags on a data item. It also defines
778 a number of standard tag values, most of which are
779 less than 64. This code can deal with multiple tag
780 values that are less than 64 and the last tag of multiple
781 if the value is more than 64. Or said another way
782 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700784 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700786 At this point in this code. uTagFlags has all the flags
787 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 */
791
792 Item.uTagBits = uTagFlags;
793 Item.uTag = uTagToProcess;
794
795 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
796 case 0:
797 // No tags we know about. Pass them up
798 *pDecodedItem = Item;
799 break;
800
801 case QCBOR_TAGFLAG_DATE_STRING:
802 nReturn = DecodeDateString(Item, pDecodedItem);
803 break;
804
805 case QCBOR_TAGFLAG_DATE_EPOCH:
806 nReturn = DecodeDateEpoch(Item, pDecodedItem);
807 break;
808
809 case QCBOR_TAGFLAG_POS_BIGNUM:
810 case QCBOR_TAGFLAG_NEG_BIGNUM:
811 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
812 break;
813
814 default:
815 // Encountering some mixed up CBOR like something that
816 // is tagged as both a string and integer date.
817 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818 }
819
820Done:
821 return nReturn;
822}
823
824
825/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800826 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700828static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700829{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700830 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831 if(nReturn)
832 goto Done;
833
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800834 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
835 goto Done;
836 }
837
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838 // If in a map and the right decoding mode, get the label
839 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
840 // In a map and caller wants maps decoded, not treated as arrays
841
842 // Get the next item which will be the real data; Item will be the label
843 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 nReturn = GetNext_TaggedItem(me, pDecodedItem); // TODO: test indefinite length string labels
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845 if(nReturn)
846 goto Done;
847
848 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
849 // strings are always good labels
850 pDecodedItem->label.string = LabelItem.val.string;
851 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
852 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
853 // It's not a string and we only want strings, probably for easy translation to JSON
854 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
855 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700856 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 pDecodedItem->label.int64 = LabelItem.val.int64;
858 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
859 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
860 pDecodedItem->label.uint64 = LabelItem.val.uint64;
861 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
862 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
863 pDecodedItem->label.string = LabelItem.val.string;
864 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
865 } else {
866 // label is not an int or a string. It is an arrray
867 // or a float or such and this implementation doesn't handle that.
868 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
869 goto Done;
870 }
871 }
872
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700873Done:
874 return nReturn;
875}
876
877
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800878/* Loops processing breaks until a non-break is encountered
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530879 or an error is encountered.
880
881 Case 1) data ends correctly in a break
882
883 Case 2) data is short a break
884
885 Case 3) data is short other than a break
886
887 Case 4) extra break
888
889 Case 5) other extra stuff
890
891
892 Can stop when nesting is exhausted, possibly returning a break
893
894 Can stop when getting to a non-break or to end of data
895 return error on end of data or return no error on end of data
896
897 All getnexts either return an item or an error so far
898
899
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800900 */
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800901static int GetNext_GetNonBreak(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800902{
903 int nReturn = QCBOR_SUCCESS;
904
905 do {
906 nReturn = GetNext_MapEntry(me, pDecodedItem);
907 if(nReturn) {
908 goto Done;
909 }
910
911 if(pDecodedItem->uDataType != QCBOR_TYPE_BREAK) {
912 break;
913 }
914
915 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
916 if(nReturn) {
917 goto Done;
918 }
919 } while (DecodeNesting_IsNested(&(me->nesting)));
920Done:
921 return nReturn;
922}
923
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924/*
925 Public function, see header qcbor.h file
926 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700927int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
928{
929 int nReturn;
930
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800931 // Loop getting items until one that is not a break is fetched
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800932 nReturn = GetNext_GetNonBreak(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800933 if(nReturn) {
934 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700935 }
936
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800937 // Now have the next item that is not a break, the one that is going to be returned
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800939 // Record the nesting level for this data item before processing any of
940 // decrementing and decsending
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530942#if 0
943 // Maybe peek at next item here.
944 {
945 // Only need to do this is current item is indefinite length
946 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
947 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
948 QCBORItem Peek;
949 GetNext_Item(&(me->InBuf), &Peek, NULL);
950 if(Peek.uDataType == 99) { // TODO:
951 // Mark current item as end of array / map
952 }
953 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
954 }
955 }
956#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700957
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800958 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800959 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800960 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800961 // Maps and arrays do count in as items in the map/array that encloses
962 // them so a decrement needs to be done for them too, but that is done
963 // only when all the items in them have been processed, not when they
964 // are opened.
965 } else {
966 // Decrement the count of items in the enclosing map/array
967 // If the count in the enclosing map/array goes to zero, that
968 // triggers a decrement for in the map/array above that and
969 // and ascend in mnesting level.
970 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700971 }
972
973Done:
974 return nReturn;
975}
976
977
978/*
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530979 Decoding items is done in 6 layered functions, one calling the
980 next one down. If a layer has no work to do for a particular item
981 it returns quickly.
982
983 - QCBORDecode_GetNext -- The top layer manages the beginnings and
984 ends of maps and arrays. It tracks descending into and ascending
985 out of maps/arrays.
986
987 - GetNext_GetNonBreak -- This handles the "break" items that
988 terminate indefinite length arrays and maps. It's job is to
989 loop over one or more breaks.
990
991 - GetNext_MapEntry -- This handles the combining of two
992 items, the label and the data, that make up a map entry.
993 It only does work on maps. It combines the label and data
994 items into one labeled item.
995
996 - GetNext_TaggedItem -- This handles the type 6 tagged items.
997 It accumulates all the tags and combines them with the following
998 non-tagged item. If the tagged item is something that is understood
999 like a date, the decoding of that item is invoked.
1000
1001 - GetNext_FullItem -- This assembles the sub items that make up
1002 an indefinte length string into one string item. It uses the
1003 string allocater to create contiguous space for the item.
1004
1005 - GetNext_Item -- This gets and decodes the most atomic
1006 item in CBOR, the thing with an initial byte containing
1007 the major type.
1008
1009 */
1010
1011
1012/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001013 Public function, see header qcbor.h file
1014 */
1015int QCBORDecode_Finish(QCBORDecodeContext *me)
1016{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 int nReturn = QCBOR_SUCCESS;
1018
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001019 // Consume any last breaks ending indefinite length arrays or maps here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 // Definite length arrays and maps get closed off above when they
1021 // the last item in them is consumed; they are not handled here.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001022 if(DecodeNesting_IsNested(&(me->nesting))) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 QCBORItem Item;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001024 nReturn = GetNext_GetNonBreak(me, &Item);
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001025 if(nReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001026 goto Done;
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001027 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001028 }
1029
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001030 // Error out if all the maps/arrays are not closed out
1031 if(DecodeNesting_IsNested(&(me->nesting))) {
1032 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1033 goto Done;
1034 }
1035
1036 // Error out if not all the bytes are consumed
1037 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1038 nReturn = QCBOR_ERR_EXTRA_BYTES;
1039 }
1040
1041Done:
1042 // Call the destructor for the string allocator if there is one
1043 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001044 if(me->pStringAllocator) {
1045 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1046 if(pAllocator->fDestructor) {
1047 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1048 }
1049 }
1050
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001051 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001052}
1053
1054
1055
Laurence Lundblade7023b952018-10-02 01:54:24 -07001056/*
1057
1058 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
1059
1060 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301061
Laurence Lundblade7023b952018-10-02 01:54:24 -07001062
1063 */
1064
1065
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001066/*
1067
1068Decoder errors handled in this file
1069
1070 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001072 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1073
1074 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1075
1076 - 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 +05301077
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001078 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1079
1080 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1081
1082 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1083
1084 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1085
1086 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1087
1088 */
1089
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001090
1091
1092typedef struct {
1093 QCBORStringAllocator StringAllocator;
1094 uint8_t *pStart;
1095 uint8_t *pEnd;
1096 uint8_t *pFree;
1097} MemPool;
1098
1099
1100/*
1101 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1102 */
1103static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1104{
1105 MemPool *me = (MemPool *)ctx;
1106 void *pReturn = NULL;
1107
1108 if(pMem) {
1109 // Realloc case
1110 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001111 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1112 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 pReturn = pMem;
1114 }
1115 } else {
1116 // New chunk case
1117 if(me->pFree + uNewSize <= me->pEnd) {
1118 pReturn = me->pFree;
1119 me->pFree += uNewSize;
1120 }
1121 }
1122
1123 return (UsefulBuf){pReturn, uNewSize};
1124}
1125
1126
1127static void MemPool_Free(void *ctx, void *pOldMem)
1128{
1129 MemPool *me = (MemPool *)ctx;
1130 me->pFree = pOldMem;
1131}
1132
1133
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301134int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135{
1136 if(Pool.len < sizeof(MemPool)+1) {
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301137 return 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 }
1139
1140 MemPool *pMP = (MemPool *)Pool.ptr;
1141
1142 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1143 pMP->StringAllocator.fFree = MemPool_Free;
1144 pMP->StringAllocator.fDestructor = NULL;
1145
Laurence Lundblade570fab52018-10-13 18:28:27 +08001146 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001148 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001149 pMP->StringAllocator.pAllocaterContext = pMP;
1150
1151 me->pStringAllocator = pMP;
1152 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301153
1154 return 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155}
1156
1157
1158