blob: 7189c20666801475adf6cd54784c8b1d4d39c67b [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--;
153 }
154}
155
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800156// Called on every map/array
157inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700158{
159 int nReturn = QCBOR_SUCCESS;
160
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800161 if(pItem->val.uCount == 0) {
162 // Nothing to do for empty definite lenth arrays. They are just are
163 // effectively the same as an item that is not a map or array
164 goto Done;
165 // Empty indefinite length maps and arrays are handled elsewhere; TODO: where?
166 }
167
168 // Error out if arrays is too long to handle
169 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
171 goto Done;
172 }
173
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800174 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
176 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
177 goto Done;
178 }
179
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800180 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700181 pNesting->pCurrent++;
182
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183 // Record a few details for this nesting level
184 pNesting->pCurrent->uMajorType = pItem->uDataType;
185 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186
187Done:
188 return nReturn;;
189}
190
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700191inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
192{
193 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
194}
195
196
197
198
199/*
200 Public function, see header file
201 */
202void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
203{
204 memset(me, 0, sizeof(QCBORDecodeContext));
205 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
206 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
207 // if the default normal mode of 0 was set.
208 me->uDecodeMode = nDecodeMode;
209 DecodeNesting_Init(&(me->nesting));
210}
211
212
213/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700214 Public function, see header file
215 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700216void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700217{
218 pCtx->pStringAllocator = (void *)pAllocator;
219}
220
221
222/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700223 This decodes the fundamental part of a CBOR data item, the type and number
224
225 This is the Counterpart to InsertEncodedTypeAndNumber().
226
227 This does the network->host byte order conversion. The conversion here
228 also results in the conversion for floats in addition to that for
229 lengths, tags and integer values.
230
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700231 This returns:
232 pnMajorType -- the major type for the item
233 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
234 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
235
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700236 */
237inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
238{
239 int nReturn;
240
241 // Get the initial byte that every CBOR data item has
242 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
243
244 // Break down the initial byte
245 const uint8_t uTmpMajorType = InitialByte >> 5;
246 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
247
248 // 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 +0700249 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700250 uint64_t uTmpValue;
251 switch(uAdditionalInfo) {
252
253 case LEN_IS_ONE_BYTE:
254 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
255 break;
256
257 case LEN_IS_TWO_BYTES:
258 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
259 break;
260
261 case LEN_IS_FOUR_BYTES:
262 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
263 break;
264
265 case LEN_IS_EIGHT_BYTES:
266 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
267 break;
268
269 case ADDINFO_RESERVED1: // reserved by CBOR spec
270 case ADDINFO_RESERVED2: // reserved by CBOR spec
271 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700272 nReturn = QCBOR_ERR_UNSUPPORTED;
273 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700274
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700275 case LEN_IS_INDEFINITE:
276 // Fall through to see what happens: TODO: check this.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700277
278 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700279 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700280 uTmpValue = uAdditionalInfo;
281 break;
282 }
283
284 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
285 // There is no harm in this. This following check takes care of catching all of
286 // these errors.
287
288 if(UsefulInputBuf_GetError(pUInBuf)) {
289 nReturn = QCBOR_ERR_HIT_END;
290 goto Done;
291 }
292
293 // All successful if we got here.
294 nReturn = QCBOR_SUCCESS;
295 *pnMajorType = uTmpMajorType;
296 *puNumber = uTmpValue;
297 *puAdditionalInfo = uAdditionalInfo;
298
299Done:
300 return nReturn;
301}
302
303
304/*
305 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
306 use it these days and the test vectors in the RFC are so. All integers in the CBOR
307 structure are positive and the major type indicates positive or negative.
308 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
309 and negative integers down to 2^x. Note that negative numbers can be one
310 more away from zero than positive.
311 Stdint, as far as I can tell, uses two's compliment to represent
312 negative integers.
313
314 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
315 used here in any way including in the interface
316 */
317inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
318{
319 int nReturn = QCBOR_SUCCESS;
320
321 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
322 if (uNumber <= INT64_MAX) {
323 pDecodedItem->val.int64 = (int64_t)uNumber;
324 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
325
326 } else {
327 pDecodedItem->val.uint64 = uNumber;
328 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
329
330 }
331 } else {
332 if(uNumber <= INT64_MAX) {
333 pDecodedItem->val.int64 = -uNumber-1;
334 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
335
336 } else {
337 // C can't represent a negative integer in this range
338 // so it is an error. todo -- test this condition
339 nReturn = QCBOR_ERR_INT_OVERFLOW;
340 }
341 }
342
343 return nReturn;
344}
345
346// Make sure #define value line up as DecodeSimple counts on this.
347#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
348#error QCBOR_TYPE_FALSE macro value wrong
349#endif
350
351#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
352#error QCBOR_TYPE_TRUE macro value wrong
353#endif
354
355#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
356#error QCBOR_TYPE_NULL macro value wrong
357#endif
358
359#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
360#error QCBOR_TYPE_UNDEF macro value wrong
361#endif
362
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700363#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
364#error QCBOR_TYPE_BREAK macro value wrong
365#endif
366
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700367#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
368#error QCBOR_TYPE_DOUBLE macro value wrong
369#endif
370
371#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
372#error QCBOR_TYPE_FLOAT macro value wrong
373#endif
374
375/*
376 Decode true, false, floats, break...
377 */
378
379inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
380{
381 int nReturn = QCBOR_SUCCESS;
382
383 // uAdditionalInfo is 5 bits from the initial byte
384 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
385 pDecodedItem->uDataType = uAdditionalInfo;
386
387 switch(uAdditionalInfo) {
388 case ADDINFO_RESERVED1: // 28
389 case ADDINFO_RESERVED2: // 29
390 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700391 nReturn = QCBOR_ERR_UNSUPPORTED;
392 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700393
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700394 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700395 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
396 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
397 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700398 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700399 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
400 break;
401 case DOUBLE_PREC_FLOAT:
402 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
403 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700404
405 case CBOR_SIMPLEV_FALSE: // 20
406 case CBOR_SIMPLEV_TRUE: // 21
407 case CBOR_SIMPLEV_NULL: // 22
408 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700409 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700410 break; // nothing to do
411
412 case CBOR_SIMPLEV_ONEBYTE: // 24
413 if(uNumber <= CBOR_SIMPLE_BREAK) {
414 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
415 nReturn = QCBOR_ERR_INVALID_CBOR;
416 goto Done;
417 }
418 // fall through intentionally
419
420 default: // 0-19
421 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
422 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
423 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
424 pDecodedItem->val.uSimple = (uint8_t)uNumber;
425 break;
426 }
427
428Done:
429 return nReturn;
430}
431
432
433
434/*
435 Decode text and byte strings
436 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700437inline static int DecodeBytesOld(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700438{
439 const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
440
441 int nReturn = QCBOR_ERR_HIT_END;
442
443 if(pBytes != NULL) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700444 pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
445 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700446 nReturn = QCBOR_SUCCESS;
447 }
448
449 return nReturn;
450}
451
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700452inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
453{
454 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uNumber);
455
456 int nReturn = QCBOR_ERR_HIT_END;
457
458 if(!UsefulBuf_IsNULLC(Bytes)) {
459 if(pAlloc) {
460 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uNumber);
461 if(UsefulBuf_IsNULL(NewMem)) {
462 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
463 } else {
464 // TODO: failure
465 }
466 } else {
467 pDecodedItem->val.string = Bytes;
468 }
469 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
470 nReturn = QCBOR_SUCCESS;
471 }
472
473 return nReturn;
474}
475
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700476
477/*
478 Mostly just assign the right data type for the date string.
479 */
480inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
481{
482 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
483 return QCBOR_ERR_BAD_OPT_TAG;
484 }
485 pDecodedItem->val.dateString = Item.val.string;
486 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
487 pDecodedItem->uTagBits = Item.uTagBits;
488 pDecodedItem->uTag = Item.uTag;
489 return QCBOR_SUCCESS;
490}
491
492
493/*
494 Mostly just assign the right data type for the bignum.
495 */
496inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
497{
498 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
499 return QCBOR_ERR_BAD_OPT_TAG;
500 }
501 pDecodedItem->val.bigNum = Item.val.string;
502 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
503 pDecodedItem->uTagBits = Item.uTagBits;
504 pDecodedItem->uTag = Item.uTag;
505 return QCBOR_SUCCESS;
506}
507
508
509/*
510 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
511 */
512static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
513{
514 int nReturn = QCBOR_SUCCESS;
515
516 pDecodedItem->uTagBits = Item.uTagBits;
517 pDecodedItem->uTag = Item.uTag;
518 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
519 pDecodedItem->val.epochDate.fSecondsFraction = 0;
520
521 switch (Item.uDataType) {
522
523 case QCBOR_TYPE_INT64:
524 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
525 break;
526
527 case QCBOR_TYPE_UINT64:
528 if(Item.val.uint64 > INT64_MAX) {
529 nReturn = QCBOR_ERR_DATE_OVERFLOW;
530 goto Done;
531 }
532 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
533 break;
534
535 default:
536 nReturn = QCBOR_ERR_BAD_OPT_TAG;
537 }
538
539Done:
540 return nReturn;
541}
542
543
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700544
545
546// Make sure the constants align as this is assumed by the GetAnItem() implementation
547#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
548#error QCBOR_TYPE_ARRAY value not lined up with major type
549#endif
550#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
551#error QCBOR_TYPE_MAP value not lined up with major type
552#endif
553
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700554/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700555 This gets a single data item and decodes it including preceding optional tagging. This does not
556 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
557 maps are handled at the next level up in GetNext().
558
559 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
560 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700562
563static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
564{
565 int nReturn;
566
567 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
568 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
569 int uMajorType;
570 uint64_t uNumber;
571 uint8_t uAdditionalInfo;
572
573 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
574
575 // Error out here if we got into trouble on the type and number.
576 // The code after this will not work if the type and number is not good.
577 if(nReturn)
578 goto Done;
579
580 pDecodedItem->uTagBits = 0;
581 pDecodedItem->uTag = 0;
582 pDecodedItem->uAllocated = 0;
583
584 // At this point the major type and the value are valid. We've got the type and the number that
585 // starts every CBOR data item.
586 switch (uMajorType) {
587 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
588 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
589 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
590 break;
591
592 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
593 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
594 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
595 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
596 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; // TODO: SIZE_MAX this is OK, right?
597 } else {
598 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
599 }
600 break;
601
602 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
603 case CBOR_MAJOR_TYPE_MAP: // Major type 5
604 // Record the number of items in the array or map
605 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
606 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
607 goto Done;
608 }
609 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
610 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length; TODO: a better way?
611 } else {
612 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
613 }
614 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
615 break;
616
617 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
618 pDecodedItem->uTag = uNumber;
619 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
620 break;
621
622 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
623 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
624 break;
625
626 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
627 nReturn = QCBOR_ERR_UNSUPPORTED;
628 break;
629 }
630
631Done:
632 return nReturn;
633}
634
635
636
637/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800638 This layer deals with indefinite length strings. It pulls all the
639 individual segment items together into one QCBORItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700640 */
641static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
642{
643 int nReturn;
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800644 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700645 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
646
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800647 // TODO: can this call to GetNext_Item go in the loop below so there is only
648 // one call to it so it can inline?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700649 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
650 if(nReturn) {
651 goto Done;
652 }
653
654 // To reduce code size by removing support for indefinite length strings, the
655 // code in this function from here down can be eliminated. Run tests to be sure
656 // all is OK if you remove this.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700657
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800658 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700659 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
660 goto Done; // no need to do any work here on non-string types
661 }
662
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800663 // Is this a string with an indefinite length?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700664 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 +0800665 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700666 }
667
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800668 // can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700669 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700670 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
671 goto Done;
672 }
673
674 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800675 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700676 const uint8_t uStringType = pDecodedItem->uDataType;
677
678 // Loop getting segments of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700679 for(;;) {
680 // Get item for next segment
681 QCBORItem Item;
682 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL); // Never alloc segments of indefinite length strings
683 if(nReturn) {
684 // Error getting the next segment
685 break;
686 }
687
688 // See if it is marker at end of indefinite length string
689 if(Item.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800690 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700691 pDecodedItem->val.string = FullString;
692 pDecodedItem->uAllocated = 1;
693 break;
694 }
695
696 // Match data type of segment to type at beginning
697 if(Item.uDataType != uStringType) {
698 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
699 break;
700 }
701
702 // Expand the buffer so it can fit
703 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, (void *)FullString.ptr, FullString.len + Item.val.string.len);
704 if(UsefulBuf_IsNULL(NewMem)) {
705 nReturn = QCBOR_ERR_STRING_ALLOC;
706 break;
707 }
708
709 // Copy data to the end of it.
710 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
711 }
712
713Done:
714 if(nReturn && FullString.ptr) {
715 // Getting item failed, clean up the allocated memory
716 (pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
717 }
718
719 return nReturn;
720}
721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722
723/*
724 Returns an error if there was something wrong with the optional item or it couldn't
725 be handled.
726 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700727static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700729 int nReturn;
730
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800731 // TODO: optimize loop below so there is only one call to GetNext_FullItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700732 nReturn = GetNext_FullItem(me, pDecodedItem);
733 if(nReturn) {
734 goto Done;
735 }
736
737 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
738 goto Done;
739 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740
741 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700742 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743
744 QCBORItem Item;
745
746 do {
747 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
748 uTagFlags |= 0x01LL << uTagToProcess;
749 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
750 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
751 }
752 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700753 greater than 63. Ignoring tags that are not understoof
754 is allowed by the standard. Multiple tags are
755 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700757 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700758 if(nReturn) {
759 // Bail out of the whole item fetch on any sort of error here
760 goto Done;
761 }
762
763 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
764 break;
765 }
766
767 uTagToProcess = Item.uTag;
768 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770
771 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700772 CBOR allows multiple tags on a data item. It also defines
773 a number of standard tag values, most of which are
774 less than 64. This code can deal with multiple tag
775 values that are less than 64 and the last tag of multiple
776 if the value is more than 64. Or said another way
777 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781 At this point in this code. uTagFlags has all the flags
782 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700784 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700785 */
786
787 Item.uTagBits = uTagFlags;
788 Item.uTag = uTagToProcess;
789
790 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
791 case 0:
792 // No tags we know about. Pass them up
793 *pDecodedItem = Item;
794 break;
795
796 case QCBOR_TAGFLAG_DATE_STRING:
797 nReturn = DecodeDateString(Item, pDecodedItem);
798 break;
799
800 case QCBOR_TAGFLAG_DATE_EPOCH:
801 nReturn = DecodeDateEpoch(Item, pDecodedItem);
802 break;
803
804 case QCBOR_TAGFLAG_POS_BIGNUM:
805 case QCBOR_TAGFLAG_NEG_BIGNUM:
806 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
807 break;
808
809 default:
810 // Encountering some mixed up CBOR like something that
811 // is tagged as both a string and integer date.
812 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813 }
814
815Done:
816 return nReturn;
817}
818
819
820/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800821 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700823static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700824{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700825 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826 if(nReturn)
827 goto Done;
828
829 // If in a map and the right decoding mode, get the label
830 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
831 // In a map and caller wants maps decoded, not treated as arrays
832
833 // Get the next item which will be the real data; Item will be the label
834 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700835 nReturn = GetNext_TaggedItem(me, pDecodedItem); // TODO: test indefinite length string labels
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836 if(nReturn)
837 goto Done;
838
839 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
840 // strings are always good labels
841 pDecodedItem->label.string = LabelItem.val.string;
842 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
843 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
844 // It's not a string and we only want strings, probably for easy translation to JSON
845 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
846 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700847 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700848 pDecodedItem->label.int64 = LabelItem.val.int64;
849 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
850 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
851 pDecodedItem->label.uint64 = LabelItem.val.uint64;
852 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
853 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
854 pDecodedItem->label.string = LabelItem.val.string;
855 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
856 } else {
857 // label is not an int or a string. It is an arrray
858 // or a float or such and this implementation doesn't handle that.
859 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
860 goto Done;
861 }
862 }
863
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864Done:
865 return nReturn;
866}
867
868
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800869/* Loops processing breaks until a non-break is encountered
870 or an error is encountered
871 */
872static int LoopOverBreaks(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
873{
874 int nReturn = QCBOR_SUCCESS;
875
876 do {
877 nReturn = GetNext_MapEntry(me, pDecodedItem);
878 if(nReturn) {
879 goto Done;
880 }
881
882 if(pDecodedItem->uDataType != QCBOR_TYPE_BREAK) {
883 break;
884 }
885
886 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
887 if(nReturn) {
888 goto Done;
889 }
890 } while (DecodeNesting_IsNested(&(me->nesting)));
891Done:
892 return nReturn;
893}
894
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700895/*
896 Public function, see header qcbor.h file
897 */
898/*
899 Decoding items is done in layers:
900 - This top layer takes care of tracking for decsending into and
901 ascending out of maps and arrays GetNext()
902 - The next layer takes care of map entries that are made up
903 of a label and a data item. They are returned as one. GetNextMap() GetNext_MapEntry()
904 - The next layer takes care of tagging and tagged types GetNext_TaggedItem()
905 - The next layer takes care of indefinite length strings GetFullItem() GetNext_FullItem()
906 - The next layer does the main decoding of the non-compound GetAnItem() GetNext_Item()
907 items, all the different types of them
908
909 */
910int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
911{
912 int nReturn;
913
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800914 // Loop getting items until one that is not a break is fetched
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800915 nReturn = LoopOverBreaks(me, pDecodedItem);
916 if(nReturn) {
917 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700918 }
919
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800920 // 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 +0700921
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800922 // Record the nesting level for this data item before processing any of
923 // decrementing and decsending
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
925
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800926 // Always decrement the count at the current level no matter what type
927 // except for breaks as breaks are always processed above
928 DecodeNesting_DecrementCount(&(me->nesting));
929
930 // If the new item is array or map, the nesting level descends
931 if(IsMapOrArray(pDecodedItem->uDataType)) {
932 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700933 }
934
935Done:
936 return nReturn;
937}
938
939
940/*
941 Public function, see header qcbor.h file
942 */
943int QCBORDecode_Finish(QCBORDecodeContext *me)
944{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700945 int nReturn = QCBOR_SUCCESS;
946
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800947 // Consume any last breaks ending indefinite length arrays or maps here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 // Definite length arrays and maps get closed off above when they
949 // the last item in them is consumed; they are not handled here.
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800950 if(DecodeNesting_IsNested(&(me->nesting))) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 QCBORItem Item;
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800952 nReturn = LoopOverBreaks(me, &Item);
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800953 if(nReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800954 goto Done;
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800955 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 }
957
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800958 // Error out if all the maps/arrays are not closed out
959 if(DecodeNesting_IsNested(&(me->nesting))) {
960 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
961 goto Done;
962 }
963
964 // Error out if not all the bytes are consumed
965 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
966 nReturn = QCBOR_ERR_EXTRA_BYTES;
967 }
968
969Done:
970 // Call the destructor for the string allocator if there is one
971 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700972 if(me->pStringAllocator) {
973 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
974 if(pAllocator->fDestructor) {
975 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
976 }
977 }
978
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700980}
981
982
983
Laurence Lundblade7023b952018-10-02 01:54:24 -0700984/*
985
986 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
987
988 There is a tag map.
989
990 TODO: how does tinyCBOR do it?
991
992
993
994
995
996 */
997
998
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700999/*
1000
1001Decoder errors handled in this file
1002
1003 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001005 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1006
1007 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1008
1009 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
1010
1011 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
1012
1013 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1014
1015 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1016
1017 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1018
1019 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1020
1021 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1022
1023 */
1024
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025
1026
1027typedef struct {
1028 QCBORStringAllocator StringAllocator;
1029 uint8_t *pStart;
1030 uint8_t *pEnd;
1031 uint8_t *pFree;
1032} MemPool;
1033
1034
1035/*
1036 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1037 */
1038static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1039{
1040 MemPool *me = (MemPool *)ctx;
1041 void *pReturn = NULL;
1042
1043 if(pMem) {
1044 // Realloc case
1045 // TODO: review this pointer math
1046 if((uint8_t *)pMem + uNewSize <= me->pEnd && (uint8_t *)pMem > me->pStart) {
1047 me->pFree = pMem + uNewSize;
1048 pReturn = pMem;
1049 }
1050 } else {
1051 // New chunk case
1052 if(me->pFree + uNewSize <= me->pEnd) {
1053 pReturn = me->pFree;
1054 me->pFree += uNewSize;
1055 }
1056 }
1057
1058 return (UsefulBuf){pReturn, uNewSize};
1059}
1060
1061
1062static void MemPool_Free(void *ctx, void *pOldMem)
1063{
1064 MemPool *me = (MemPool *)ctx;
1065 me->pFree = pOldMem;
1066}
1067
1068
1069void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
1070{
1071 if(Pool.len < sizeof(MemPool)+1) {
1072 return; // Failure will happen when first string needs to be allocated
1073 }
1074
1075 MemPool *pMP = (MemPool *)Pool.ptr;
1076
1077 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1078 pMP->StringAllocator.fFree = MemPool_Free;
1079 pMP->StringAllocator.fDestructor = NULL;
1080
1081 pMP->pStart = Pool.ptr + sizeof(MemPool);
1082 pMP->pFree = pMP->pStart;
1083 pMP->pEnd = Pool.ptr + Pool.len;
1084 pMP->StringAllocator.pAllocaterContext = pMP;
1085
1086 me->pStringAllocator = pMP;
1087 me->bStringAllocateAll = bAllStrings;
1088}
1089
1090
1091