blob: 676ec323b1a33f4e138329486fc7f35823a3e9ab [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
878/*
879 Public function, see header qcbor.h file
880 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
882{
883 int nReturn;
884
Laurence Lundblade6de37062018-10-15 12:22:42 +0530885 nReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800886 if(nReturn) {
887 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700888 }
889
Laurence Lundblade6de37062018-10-15 12:22:42 +0530890 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
891 // Breaks are always processed at the end of this function
892 // They should never show up here.
893 nReturn = QCBOR_ERR_BAD_BREAK;
894 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530895 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896
Laurence Lundblade6de37062018-10-15 12:22:42 +0530897 // Record the nesting level for this data item before processing any of
898 // decrementing and descending
899 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
900
901 // Process the item just received for descent or decrement, and
902 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800903 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800904 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800905 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800906 // Maps and arrays do count in as items in the map/array that encloses
907 // them so a decrement needs to be done for them too, but that is done
908 // only when all the items in them have been processed, not when they
909 // are opened.
910 } else {
911 // Decrement the count of items in the enclosing map/array
912 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +0530913 // triggers a decrement in the map/array above that and
914 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800915 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916 }
Laurence Lundblade6de37062018-10-15 12:22:42 +0530917 if(nReturn) {
918 goto Done;
919 }
920
921 // For indefinite length maps/arrays, looking at any and
922 // all breaks that might terminate them. The equivalent
923 // for definite length maps/arrays happens in
924 // DecodeNesting_DecrementCount().
925 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
926 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
927 // Peek forward one item to see if it is a break.
928 QCBORItem Peek;
929 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
930 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
931 if(nReturn) {
932 goto Done;
933 }
934 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
935 // It is not a break, rewind so it can be processed normally.
936 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
937 break;
938 }
939 // It is a break. Ascend one nesting level.
940 // The break consumed.
941 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
942 if(nReturn) {
943 // break occured outside of an indefinite length array/map
944 goto Done;
945 }
946 }
947 }
948
949 // Tell the caller what level is next. This tells them what maps/arrays
950 // were closed out and makes it possible for them to reconstruct
951 // the tree with just the information returned by GetNext
952 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700953
954Done:
955 return nReturn;
956}
957
958
959/*
Laurence Lundblade6de37062018-10-15 12:22:42 +0530960 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530961 next one down. If a layer has no work to do for a particular item
962 it returns quickly.
963
964 - QCBORDecode_GetNext -- The top layer manages the beginnings and
965 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +0530966 out of maps/arrays. It processes all breaks that terminate
967 maps and arrays.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530968
969 - GetNext_MapEntry -- This handles the combining of two
970 items, the label and the data, that make up a map entry.
971 It only does work on maps. It combines the label and data
972 items into one labeled item.
973
974 - GetNext_TaggedItem -- This handles the type 6 tagged items.
975 It accumulates all the tags and combines them with the following
976 non-tagged item. If the tagged item is something that is understood
977 like a date, the decoding of that item is invoked.
978
979 - GetNext_FullItem -- This assembles the sub items that make up
980 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +0530981 string allocater to create contiguous space for the item. It
982 processes all breaks that are part of indefinite length strings.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530983
984 - GetNext_Item -- This gets and decodes the most atomic
985 item in CBOR, the thing with an initial byte containing
986 the major type.
987
988 */
989
990
991/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700992 Public function, see header qcbor.h file
993 */
994int QCBORDecode_Finish(QCBORDecodeContext *me)
995{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700996 int nReturn = QCBOR_SUCCESS;
997
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800998 // Error out if all the maps/arrays are not closed out
999 if(DecodeNesting_IsNested(&(me->nesting))) {
1000 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1001 goto Done;
1002 }
1003
1004 // Error out if not all the bytes are consumed
1005 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1006 nReturn = QCBOR_ERR_EXTRA_BYTES;
1007 }
1008
1009Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301010 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001011 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 if(me->pStringAllocator) {
1013 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1014 if(pAllocator->fDestructor) {
1015 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1016 }
1017 }
1018
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001020}
1021
1022
1023
Laurence Lundblade7023b952018-10-02 01:54:24 -07001024/*
1025
1026 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
1027
1028 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301029
Laurence Lundblade7023b952018-10-02 01:54:24 -07001030
1031 */
1032
1033
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001034/*
1035
1036Decoder errors handled in this file
1037
1038 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001040 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1041
1042 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1043
1044 - 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 +05301045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001046 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1047
1048 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1049
1050 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1051
1052 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1053
1054 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1055
1056 */
1057
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001058
1059
1060typedef struct {
1061 QCBORStringAllocator StringAllocator;
1062 uint8_t *pStart;
1063 uint8_t *pEnd;
1064 uint8_t *pFree;
1065} MemPool;
1066
1067
1068/*
1069 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1070 */
1071static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1072{
1073 MemPool *me = (MemPool *)ctx;
1074 void *pReturn = NULL;
1075
1076 if(pMem) {
1077 // Realloc case
1078 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001079 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1080 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 pReturn = pMem;
1082 }
1083 } else {
1084 // New chunk case
1085 if(me->pFree + uNewSize <= me->pEnd) {
1086 pReturn = me->pFree;
1087 me->pFree += uNewSize;
1088 }
1089 }
1090
1091 return (UsefulBuf){pReturn, uNewSize};
1092}
1093
1094
1095static void MemPool_Free(void *ctx, void *pOldMem)
1096{
1097 MemPool *me = (MemPool *)ctx;
1098 me->pFree = pOldMem;
1099}
1100
1101
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301102int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001103{
1104 if(Pool.len < sizeof(MemPool)+1) {
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301105 return 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106 }
1107
1108 MemPool *pMP = (MemPool *)Pool.ptr;
1109
1110 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1111 pMP->StringAllocator.fFree = MemPool_Free;
1112 pMP->StringAllocator.fDestructor = NULL;
1113
Laurence Lundblade570fab52018-10-13 18:28:27 +08001114 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001116 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001117 pMP->StringAllocator.pAllocaterContext = pMP;
1118
1119 me->pStringAllocator = pMP;
1120 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301121
1122 return 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001123}
1124
1125
1126