blob: 2ec7a68d59cf705a2c1f7f582565bfd9960ba549 [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 Lundblade3a760b02018-10-08 13:46:03 +0800651 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700652 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
653
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800654 // TODO: can this call to GetNext_Item go in the loop below so there is only
655 // one call to it so it can inline?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700656 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
657 if(nReturn) {
658 goto Done;
659 }
660
661 // To reduce code size by removing support for indefinite length strings, the
662 // code in this function from here down can be eliminated. Run tests to be sure
663 // all is OK if you remove this.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700664
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800665 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700666 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
667 goto Done; // no need to do any work here on non-string types
668 }
669
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800670 // Is this a string with an indefinite length?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700671 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 +0800672 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700673 }
674
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800675 // can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700676 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700677 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
678 goto Done;
679 }
680
681 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800682 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700683 const uint8_t uStringType = pDecodedItem->uDataType;
684
685 // Loop getting segments of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700686 for(;;) {
687 // Get item for next segment
688 QCBORItem Item;
689 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL); // Never alloc segments of indefinite length strings
690 if(nReturn) {
691 // Error getting the next segment
692 break;
693 }
694
695 // See if it is marker at end of indefinite length string
696 if(Item.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800697 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700698 pDecodedItem->val.string = FullString;
699 pDecodedItem->uAllocated = 1;
700 break;
701 }
702
703 // Match data type of segment to type at beginning
704 if(Item.uDataType != uStringType) {
705 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
706 break;
707 }
708
709 // Expand the buffer so it can fit
710 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, (void *)FullString.ptr, FullString.len + Item.val.string.len);
711 if(UsefulBuf_IsNULL(NewMem)) {
712 nReturn = QCBOR_ERR_STRING_ALLOC;
713 break;
714 }
715
716 // Copy data to the end of it.
717 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
718 }
719
720Done:
721 if(nReturn && FullString.ptr) {
722 // Getting item failed, clean up the allocated memory
723 (pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
724 }
725
726 return nReturn;
727}
728
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729
730/*
731 Returns an error if there was something wrong with the optional item or it couldn't
732 be handled.
733 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700734static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700736 int nReturn;
737
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800738 // TODO: optimize loop below so there is only one call to GetNext_FullItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700739 nReturn = GetNext_FullItem(me, pDecodedItem);
740 if(nReturn) {
741 goto Done;
742 }
743
744 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
745 goto Done;
746 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700747
748 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700749 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750
751 QCBORItem Item;
752
753 do {
754 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
755 uTagFlags |= 0x01LL << uTagToProcess;
756 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
757 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
758 }
759 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700760 greater than 63. Ignoring tags that are not understoof
761 is allowed by the standard. Multiple tags are
762 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700765 if(nReturn) {
766 // Bail out of the whole item fetch on any sort of error here
767 goto Done;
768 }
769
770 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
771 break;
772 }
773
774 uTagToProcess = Item.uTag;
775 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700776
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700777
778 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 CBOR allows multiple tags on a data item. It also defines
780 a number of standard tag values, most of which are
781 less than 64. This code can deal with multiple tag
782 values that are less than 64 and the last tag of multiple
783 if the value is more than 64. Or said another way
784 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700786 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700787
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 At this point in this code. uTagFlags has all the flags
789 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700791 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792 */
793
794 Item.uTagBits = uTagFlags;
795 Item.uTag = uTagToProcess;
796
797 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
798 case 0:
799 // No tags we know about. Pass them up
800 *pDecodedItem = Item;
801 break;
802
803 case QCBOR_TAGFLAG_DATE_STRING:
804 nReturn = DecodeDateString(Item, pDecodedItem);
805 break;
806
807 case QCBOR_TAGFLAG_DATE_EPOCH:
808 nReturn = DecodeDateEpoch(Item, pDecodedItem);
809 break;
810
811 case QCBOR_TAGFLAG_POS_BIGNUM:
812 case QCBOR_TAGFLAG_NEG_BIGNUM:
813 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
814 break;
815
816 default:
817 // Encountering some mixed up CBOR like something that
818 // is tagged as both a string and integer date.
819 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 }
821
822Done:
823 return nReturn;
824}
825
826
827/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800828 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700829 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700830static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700832 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700833 if(nReturn)
834 goto Done;
835
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800836 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
837 goto Done;
838 }
839
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840 // If in a map and the right decoding mode, get the label
841 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
842 // In a map and caller wants maps decoded, not treated as arrays
843
844 // Get the next item which will be the real data; Item will be the label
845 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700846 nReturn = GetNext_TaggedItem(me, pDecodedItem); // TODO: test indefinite length string labels
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 if(nReturn)
848 goto Done;
849
850 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
851 // strings are always good labels
852 pDecodedItem->label.string = LabelItem.val.string;
853 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
854 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
855 // It's not a string and we only want strings, probably for easy translation to JSON
856 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
857 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700858 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700859 pDecodedItem->label.int64 = LabelItem.val.int64;
860 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
861 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
862 pDecodedItem->label.uint64 = LabelItem.val.uint64;
863 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
864 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
865 pDecodedItem->label.string = LabelItem.val.string;
866 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
867 } else {
868 // label is not an int or a string. It is an arrray
869 // or a float or such and this implementation doesn't handle that.
870 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
871 goto Done;
872 }
873 }
874
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700875Done:
876 return nReturn;
877}
878
879
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800880/* Loops processing breaks until a non-break is encountered
881 or an error is encountered
882 */
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800883static int GetNext_GetNonBreak(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800884{
885 int nReturn = QCBOR_SUCCESS;
886
887 do {
888 nReturn = GetNext_MapEntry(me, pDecodedItem);
889 if(nReturn) {
890 goto Done;
891 }
892
893 if(pDecodedItem->uDataType != QCBOR_TYPE_BREAK) {
894 break;
895 }
896
897 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
898 if(nReturn) {
899 goto Done;
900 }
901 } while (DecodeNesting_IsNested(&(me->nesting)));
902Done:
903 return nReturn;
904}
905
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906/*
907 Public function, see header qcbor.h file
908 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700909int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
910{
911 int nReturn;
912
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800913 // Loop getting items until one that is not a break is fetched
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800914 nReturn = GetNext_GetNonBreak(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800915 if(nReturn) {
916 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700917 }
918
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800919 // 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 +0700920
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800921 // Record the nesting level for this data item before processing any of
922 // decrementing and decsending
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700923 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
924
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800925 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800926 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800927 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800928 // Maps and arrays do count in as items in the map/array that encloses
929 // them so a decrement needs to be done for them too, but that is done
930 // only when all the items in them have been processed, not when they
931 // are opened.
932 } else {
933 // Decrement the count of items in the enclosing map/array
934 // If the count in the enclosing map/array goes to zero, that
935 // triggers a decrement for in the map/array above that and
936 // and ascend in mnesting level.
937 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700938 }
939
940Done:
941 return nReturn;
942}
943
944
945/*
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530946 Decoding items is done in 6 layered functions, one calling the
947 next one down. If a layer has no work to do for a particular item
948 it returns quickly.
949
950 - QCBORDecode_GetNext -- The top layer manages the beginnings and
951 ends of maps and arrays. It tracks descending into and ascending
952 out of maps/arrays.
953
954 - GetNext_GetNonBreak -- This handles the "break" items that
955 terminate indefinite length arrays and maps. It's job is to
956 loop over one or more breaks.
957
958 - GetNext_MapEntry -- This handles the combining of two
959 items, the label and the data, that make up a map entry.
960 It only does work on maps. It combines the label and data
961 items into one labeled item.
962
963 - GetNext_TaggedItem -- This handles the type 6 tagged items.
964 It accumulates all the tags and combines them with the following
965 non-tagged item. If the tagged item is something that is understood
966 like a date, the decoding of that item is invoked.
967
968 - GetNext_FullItem -- This assembles the sub items that make up
969 an indefinte length string into one string item. It uses the
970 string allocater to create contiguous space for the item.
971
972 - GetNext_Item -- This gets and decodes the most atomic
973 item in CBOR, the thing with an initial byte containing
974 the major type.
975
976 */
977
978
979/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700980 Public function, see header qcbor.h file
981 */
982int QCBORDecode_Finish(QCBORDecodeContext *me)
983{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984 int nReturn = QCBOR_SUCCESS;
985
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800986 // Consume any last breaks ending indefinite length arrays or maps here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 // Definite length arrays and maps get closed off above when they
988 // the last item in them is consumed; they are not handled here.
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800989 if(DecodeNesting_IsNested(&(me->nesting))) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 QCBORItem Item;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800991 nReturn = GetNext_GetNonBreak(me, &Item);
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800992 if(nReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800993 goto Done;
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800994 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 }
996
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800997 // Error out if all the maps/arrays are not closed out
998 if(DecodeNesting_IsNested(&(me->nesting))) {
999 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1000 goto Done;
1001 }
1002
1003 // Error out if not all the bytes are consumed
1004 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1005 nReturn = QCBOR_ERR_EXTRA_BYTES;
1006 }
1007
1008Done:
1009 // Call the destructor for the string allocator if there is one
1010 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 if(me->pStringAllocator) {
1012 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1013 if(pAllocator->fDestructor) {
1014 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1015 }
1016 }
1017
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001019}
1020
1021
1022
Laurence Lundblade7023b952018-10-02 01:54:24 -07001023/*
1024
1025 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
1026
1027 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301028
Laurence Lundblade7023b952018-10-02 01:54:24 -07001029
1030 */
1031
1032
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001033/*
1034
1035Decoder errors handled in this file
1036
1037 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001039 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1040
1041 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1042
1043 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
1044
1045 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
1046
1047 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1048
1049 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1050
1051 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1052
1053 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1054
1055 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1056
1057 */
1058
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001059
1060
1061typedef struct {
1062 QCBORStringAllocator StringAllocator;
1063 uint8_t *pStart;
1064 uint8_t *pEnd;
1065 uint8_t *pFree;
1066} MemPool;
1067
1068
1069/*
1070 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1071 */
1072static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1073{
1074 MemPool *me = (MemPool *)ctx;
1075 void *pReturn = NULL;
1076
1077 if(pMem) {
1078 // Realloc case
1079 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001080 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1081 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001082 pReturn = pMem;
1083 }
1084 } else {
1085 // New chunk case
1086 if(me->pFree + uNewSize <= me->pEnd) {
1087 pReturn = me->pFree;
1088 me->pFree += uNewSize;
1089 }
1090 }
1091
1092 return (UsefulBuf){pReturn, uNewSize};
1093}
1094
1095
1096static void MemPool_Free(void *ctx, void *pOldMem)
1097{
1098 MemPool *me = (MemPool *)ctx;
1099 me->pFree = pOldMem;
1100}
1101
1102
1103void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
1104{
1105 if(Pool.len < sizeof(MemPool)+1) {
1106 return; // Failure will happen when first string needs to be allocated
1107 }
1108
1109 MemPool *pMP = (MemPool *)Pool.ptr;
1110
1111 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1112 pMP->StringAllocator.fFree = MemPool_Free;
1113 pMP->StringAllocator.fDestructor = NULL;
1114
Laurence Lundblade570fab52018-10-13 18:28:27 +08001115 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001116 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001117 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001118 pMP->StringAllocator.pAllocaterContext = pMP;
1119
1120 me->pStringAllocator = pMP;
1121 me->bStringAllocateAll = bAllStrings;
1122}
1123
1124
1125