blob: 410af462566625e3398969c77c0c7ddf0a5947cc [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 DecodeBytesOld(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700441{
442 const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
443
444 int nReturn = QCBOR_ERR_HIT_END;
445
446 if(pBytes != NULL) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700447 pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
448 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700449 nReturn = QCBOR_SUCCESS;
450 }
451
452 return nReturn;
453}
454
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700455inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
456{
457 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uNumber);
458
459 int nReturn = QCBOR_ERR_HIT_END;
460
461 if(!UsefulBuf_IsNULLC(Bytes)) {
462 if(pAlloc) {
463 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uNumber);
464 if(UsefulBuf_IsNULL(NewMem)) {
465 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
466 } else {
467 // TODO: failure
468 }
469 } else {
470 pDecodedItem->val.string = Bytes;
471 }
472 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
473 nReturn = QCBOR_SUCCESS;
474 }
475
476 return nReturn;
477}
478
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700479
480/*
481 Mostly just assign the right data type for the date string.
482 */
483inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
484{
485 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
486 return QCBOR_ERR_BAD_OPT_TAG;
487 }
488 pDecodedItem->val.dateString = Item.val.string;
489 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
490 pDecodedItem->uTagBits = Item.uTagBits;
491 pDecodedItem->uTag = Item.uTag;
492 return QCBOR_SUCCESS;
493}
494
495
496/*
497 Mostly just assign the right data type for the bignum.
498 */
499inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
500{
501 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
502 return QCBOR_ERR_BAD_OPT_TAG;
503 }
504 pDecodedItem->val.bigNum = Item.val.string;
505 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
506 pDecodedItem->uTagBits = Item.uTagBits;
507 pDecodedItem->uTag = Item.uTag;
508 return QCBOR_SUCCESS;
509}
510
511
512/*
513 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
514 */
515static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
516{
517 int nReturn = QCBOR_SUCCESS;
518
519 pDecodedItem->uTagBits = Item.uTagBits;
520 pDecodedItem->uTag = Item.uTag;
521 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
522 pDecodedItem->val.epochDate.fSecondsFraction = 0;
523
524 switch (Item.uDataType) {
525
526 case QCBOR_TYPE_INT64:
527 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
528 break;
529
530 case QCBOR_TYPE_UINT64:
531 if(Item.val.uint64 > INT64_MAX) {
532 nReturn = QCBOR_ERR_DATE_OVERFLOW;
533 goto Done;
534 }
535 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
536 break;
537
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800538 case QCBOR_TYPE_FLOAT:
539 // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
540 if(Item.val.fnum > INT64_MAX) {
541 nReturn = QCBOR_ERR_DATE_OVERFLOW;
542 goto Done;
543 }
544 pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
545 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
546 break;
547
548 case QCBOR_TYPE_DOUBLE:
549 if(Item.val.dfnum > INT64_MAX) {
550 nReturn = QCBOR_ERR_DATE_OVERFLOW;
551 goto Done;
552 }
553 pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
554 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
555 break;
556
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557 default:
558 nReturn = QCBOR_ERR_BAD_OPT_TAG;
559 }
560
561Done:
562 return nReturn;
563}
564
565
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700566
567
568// Make sure the constants align as this is assumed by the GetAnItem() implementation
569#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
570#error QCBOR_TYPE_ARRAY value not lined up with major type
571#endif
572#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
573#error QCBOR_TYPE_MAP value not lined up with major type
574#endif
575
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700576/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700577 This gets a single data item and decodes it including preceding optional tagging. This does not
578 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
579 maps are handled at the next level up in GetNext().
580
581 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
582 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700583 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700584
585static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
586{
587 int nReturn;
588
589 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
590 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
591 int uMajorType;
592 uint64_t uNumber;
593 uint8_t uAdditionalInfo;
594
595 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
596
597 // Error out here if we got into trouble on the type and number.
598 // The code after this will not work if the type and number is not good.
599 if(nReturn)
600 goto Done;
601
602 pDecodedItem->uTagBits = 0;
603 pDecodedItem->uTag = 0;
604 pDecodedItem->uAllocated = 0;
605
606 // At this point the major type and the value are valid. We've got the type and the number that
607 // starts every CBOR data item.
608 switch (uMajorType) {
609 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
610 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
611 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
612 break;
613
614 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
615 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
616 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
617 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
618 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; // TODO: SIZE_MAX this is OK, right?
619 } else {
620 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
621 }
622 break;
623
624 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
625 case CBOR_MAJOR_TYPE_MAP: // Major type 5
626 // Record the number of items in the array or map
627 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
628 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
629 goto Done;
630 }
631 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
632 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length; TODO: a better way?
633 } else {
634 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
635 }
636 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
637 break;
638
639 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
640 pDecodedItem->uTag = uNumber;
641 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
642 break;
643
644 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
645 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
646 break;
647
648 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
649 nReturn = QCBOR_ERR_UNSUPPORTED;
650 break;
651 }
652
653Done:
654 return nReturn;
655}
656
657
658
659/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800660 This layer deals with indefinite length strings. It pulls all the
661 individual segment items together into one QCBORItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700662 */
663static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
664{
665 int nReturn;
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800666 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700667 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
668
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800669 // TODO: can this call to GetNext_Item go in the loop below so there is only
670 // one call to it so it can inline?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700671 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
672 if(nReturn) {
673 goto Done;
674 }
675
676 // To reduce code size by removing support for indefinite length strings, the
677 // code in this function from here down can be eliminated. Run tests to be sure
678 // all is OK if you remove this.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700679
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800680 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700681 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
682 goto Done; // no need to do any work here on non-string types
683 }
684
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800685 // Is this a string with an indefinite length?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700686 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 +0800687 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700688 }
689
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800690 // can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700691 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700692 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
693 goto Done;
694 }
695
696 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800697 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700698 const uint8_t uStringType = pDecodedItem->uDataType;
699
700 // Loop getting segments of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700701 for(;;) {
702 // Get item for next segment
703 QCBORItem Item;
704 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL); // Never alloc segments of indefinite length strings
705 if(nReturn) {
706 // Error getting the next segment
707 break;
708 }
709
710 // See if it is marker at end of indefinite length string
711 if(Item.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800712 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700713 pDecodedItem->val.string = FullString;
714 pDecodedItem->uAllocated = 1;
715 break;
716 }
717
718 // Match data type of segment to type at beginning
719 if(Item.uDataType != uStringType) {
720 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
721 break;
722 }
723
724 // Expand the buffer so it can fit
725 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, (void *)FullString.ptr, FullString.len + Item.val.string.len);
726 if(UsefulBuf_IsNULL(NewMem)) {
727 nReturn = QCBOR_ERR_STRING_ALLOC;
728 break;
729 }
730
731 // Copy data to the end of it.
732 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
733 }
734
735Done:
736 if(nReturn && FullString.ptr) {
737 // Getting item failed, clean up the allocated memory
738 (pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
739 }
740
741 return nReturn;
742}
743
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744
745/*
746 Returns an error if there was something wrong with the optional item or it couldn't
747 be handled.
748 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700749static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700751 int nReturn;
752
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800753 // TODO: optimize loop below so there is only one call to GetNext_FullItem
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700754 nReturn = GetNext_FullItem(me, pDecodedItem);
755 if(nReturn) {
756 goto Done;
757 }
758
759 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
760 goto Done;
761 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700762
763 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700765
766 QCBORItem Item;
767
768 do {
769 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
770 uTagFlags |= 0x01LL << uTagToProcess;
771 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
772 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
773 }
774 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700775 greater than 63. Ignoring tags that are not understoof
776 is allowed by the standard. Multiple tags are
777 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780 if(nReturn) {
781 // Bail out of the whole item fetch on any sort of error here
782 goto Done;
783 }
784
785 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
786 break;
787 }
788
789 uTagToProcess = Item.uTag;
790 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700791
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792
793 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 CBOR allows multiple tags on a data item. It also defines
795 a number of standard tag values, most of which are
796 less than 64. This code can deal with multiple tag
797 values that are less than 64 and the last tag of multiple
798 if the value is more than 64. Or said another way
799 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700803 At this point in this code. uTagFlags has all the flags
804 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700806 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807 */
808
809 Item.uTagBits = uTagFlags;
810 Item.uTag = uTagToProcess;
811
812 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
813 case 0:
814 // No tags we know about. Pass them up
815 *pDecodedItem = Item;
816 break;
817
818 case QCBOR_TAGFLAG_DATE_STRING:
819 nReturn = DecodeDateString(Item, pDecodedItem);
820 break;
821
822 case QCBOR_TAGFLAG_DATE_EPOCH:
823 nReturn = DecodeDateEpoch(Item, pDecodedItem);
824 break;
825
826 case QCBOR_TAGFLAG_POS_BIGNUM:
827 case QCBOR_TAGFLAG_NEG_BIGNUM:
828 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
829 break;
830
831 default:
832 // Encountering some mixed up CBOR like something that
833 // is tagged as both a string and integer date.
834 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 }
836
837Done:
838 return nReturn;
839}
840
841
842/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800843 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700847 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700848 if(nReturn)
849 goto Done;
850
851 // If in a map and the right decoding mode, get the label
852 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
853 // In a map and caller wants maps decoded, not treated as arrays
854
855 // Get the next item which will be the real data; Item will be the label
856 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700857 nReturn = GetNext_TaggedItem(me, pDecodedItem); // TODO: test indefinite length string labels
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 if(nReturn)
859 goto Done;
860
861 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
862 // strings are always good labels
863 pDecodedItem->label.string = LabelItem.val.string;
864 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
865 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
866 // It's not a string and we only want strings, probably for easy translation to JSON
867 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
868 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 pDecodedItem->label.int64 = LabelItem.val.int64;
871 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
872 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
873 pDecodedItem->label.uint64 = LabelItem.val.uint64;
874 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
875 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
876 pDecodedItem->label.string = LabelItem.val.string;
877 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
878 } else {
879 // label is not an int or a string. It is an arrray
880 // or a float or such and this implementation doesn't handle that.
881 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
882 goto Done;
883 }
884 }
885
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700886Done:
887 return nReturn;
888}
889
890
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800891/* Loops processing breaks until a non-break is encountered
892 or an error is encountered
893 */
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800894static int GetNext_GetNonBreak(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800895{
896 int nReturn = QCBOR_SUCCESS;
897
898 do {
899 nReturn = GetNext_MapEntry(me, pDecodedItem);
900 if(nReturn) {
901 goto Done;
902 }
903
904 if(pDecodedItem->uDataType != QCBOR_TYPE_BREAK) {
905 break;
906 }
907
908 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
909 if(nReturn) {
910 goto Done;
911 }
912 } while (DecodeNesting_IsNested(&(me->nesting)));
913Done:
914 return nReturn;
915}
916
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700917/*
918 Public function, see header qcbor.h file
919 */
920/*
921 Decoding items is done in layers:
922 - This top layer takes care of tracking for decsending into and
923 ascending out of maps and arrays GetNext()
924 - The next layer takes care of map entries that are made up
925 of a label and a data item. They are returned as one. GetNextMap() GetNext_MapEntry()
926 - The next layer takes care of tagging and tagged types GetNext_TaggedItem()
927 - The next layer takes care of indefinite length strings GetFullItem() GetNext_FullItem()
928 - The next layer does the main decoding of the non-compound GetAnItem() GetNext_Item()
929 items, all the different types of them
930
931 */
932int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
933{
934 int nReturn;
935
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800936 // Loop getting items until one that is not a break is fetched
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800937 nReturn = GetNext_GetNonBreak(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800938 if(nReturn) {
939 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 }
941
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800942 // 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 +0700943
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800944 // Record the nesting level for this data item before processing any of
945 // decrementing and decsending
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
947
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800948 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800949 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800950 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800951 // Maps and arrays do count in as items in the map/array that encloses
952 // them so a decrement needs to be done for them too, but that is done
953 // only when all the items in them have been processed, not when they
954 // are opened.
955 } else {
956 // Decrement the count of items in the enclosing map/array
957 // If the count in the enclosing map/array goes to zero, that
958 // triggers a decrement for in the map/array above that and
959 // and ascend in mnesting level.
960 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700961 }
962
963Done:
964 return nReturn;
965}
966
967
968/*
969 Public function, see header qcbor.h file
970 */
971int QCBORDecode_Finish(QCBORDecodeContext *me)
972{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700973 int nReturn = QCBOR_SUCCESS;
974
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800975 // Consume any last breaks ending indefinite length arrays or maps here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 // Definite length arrays and maps get closed off above when they
977 // the last item in them is consumed; they are not handled here.
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800978 if(DecodeNesting_IsNested(&(me->nesting))) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 QCBORItem Item;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800980 nReturn = GetNext_GetNonBreak(me, &Item);
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800981 if(nReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800982 goto Done;
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800983 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984 }
985
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800986 // Error out if all the maps/arrays are not closed out
987 if(DecodeNesting_IsNested(&(me->nesting))) {
988 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
989 goto Done;
990 }
991
992 // Error out if not all the bytes are consumed
993 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
994 nReturn = QCBOR_ERR_EXTRA_BYTES;
995 }
996
997Done:
998 // Call the destructor for the string allocator if there is one
999 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 if(me->pStringAllocator) {
1001 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1002 if(pAllocator->fDestructor) {
1003 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1004 }
1005 }
1006
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001008}
1009
1010
1011
Laurence Lundblade7023b952018-10-02 01:54:24 -07001012/*
1013
1014 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
1015
1016 There is a tag map.
1017
1018 TODO: how does tinyCBOR do it?
1019
1020
1021
1022
1023
1024 */
1025
1026
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001027/*
1028
1029Decoder errors handled in this file
1030
1031 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001033 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1034
1035 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1036
1037 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
1038
1039 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
1040
1041 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1042
1043 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1044
1045 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1046
1047 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1048
1049 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1050
1051 */
1052
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053
1054
1055typedef struct {
1056 QCBORStringAllocator StringAllocator;
1057 uint8_t *pStart;
1058 uint8_t *pEnd;
1059 uint8_t *pFree;
1060} MemPool;
1061
1062
1063/*
1064 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1065 */
1066static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1067{
1068 MemPool *me = (MemPool *)ctx;
1069 void *pReturn = NULL;
1070
1071 if(pMem) {
1072 // Realloc case
1073 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001074 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1075 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001076 pReturn = pMem;
1077 }
1078 } else {
1079 // New chunk case
1080 if(me->pFree + uNewSize <= me->pEnd) {
1081 pReturn = me->pFree;
1082 me->pFree += uNewSize;
1083 }
1084 }
1085
1086 return (UsefulBuf){pReturn, uNewSize};
1087}
1088
1089
1090static void MemPool_Free(void *ctx, void *pOldMem)
1091{
1092 MemPool *me = (MemPool *)ctx;
1093 me->pFree = pOldMem;
1094}
1095
1096
1097void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
1098{
1099 if(Pool.len < sizeof(MemPool)+1) {
1100 return; // Failure will happen when first string needs to be allocated
1101 }
1102
1103 MemPool *pMP = (MemPool *)Pool.ptr;
1104
1105 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1106 pMP->StringAllocator.fFree = MemPool_Free;
1107 pMP->StringAllocator.fDestructor = NULL;
1108
1109 pMP->pStart = Pool.ptr + sizeof(MemPool);
1110 pMP->pFree = pMP->pStart;
1111 pMP->pEnd = Pool.ptr + Pool.len;
1112 pMP->StringAllocator.pAllocaterContext = pMP;
1113
1114 me->pStringAllocator = pMP;
1115 me->bStringAllocateAll = bAllStrings;
1116}
1117
1118
1119