blob: 9a789d7614e4c87688c20efc344862498dd96c74 [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
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053081/*
82 This casts away the const-ness of a pointer, usually so it can be
83 freed or realloced.
84 */
85#define UNCONST_POINTER(ptr) ((void *)(ptr))
86
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070087
88/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080089 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090 */
91
92inline static int IsMapOrArray(uint8_t uDataType)
93{
94 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
95}
96
97inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
98{
99 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
100}
101
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700102inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700103{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700104 return pNesting->pCurrent->uCount == UINT16_MAX;
105}
106
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800107inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
108{
109 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
110}
111
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700112inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
113{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700114 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700115 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700116 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700117
118 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
119}
120
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800121// Process a break. This will either ascend the nesting or error out
122inline static int DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700123{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800124 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800126 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700127 }
128
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800129 // breaks can only occur when the map/array is indefinite length
130 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
131 return QCBOR_ERR_BAD_BREAK;
132 }
133
134 // if all OK, the break reduces the level of nesting
135 pNesting->pCurrent--;
136
137 return QCBOR_SUCCESS;
138}
139
140// Called on every single item except breaks including the opening of a map/array
141inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
142{
143 if(!DecodeNesting_IsNested(pNesting)) {
144 // at top level where there is no tracking
145 return;
146 }
147
148 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
149 // There is no count for indefinite length arrays/maps
150 return;
151 }
152
153 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700155
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800156 // Pop up nesting levels if the counts at the levels are zero
157 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700158 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800159 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
160 pNesting->pCurrent->uCount--;
161 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700162 }
163}
164
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800165// Called on every map/array
166inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700167{
168 int nReturn = QCBOR_SUCCESS;
169
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800170 if(pItem->val.uCount == 0) {
171 // Nothing to do for empty definite lenth arrays. They are just are
172 // effectively the same as an item that is not a map or array
173 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530174 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800175 }
176
177 // Error out if arrays is too long to handle
178 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700179 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
180 goto Done;
181 }
182
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
185 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
186 goto Done;
187 }
188
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800189 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700190 pNesting->pCurrent++;
191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192 // Record a few details for this nesting level
193 pNesting->pCurrent->uMajorType = pItem->uDataType;
194 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700195
196Done:
197 return nReturn;;
198}
199
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700200inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
201{
202 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
203}
204
205
206
207
208/*
209 Public function, see header file
210 */
211void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
212{
213 memset(me, 0, sizeof(QCBORDecodeContext));
214 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
215 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
216 // if the default normal mode of 0 was set.
217 me->uDecodeMode = nDecodeMode;
218 DecodeNesting_Init(&(me->nesting));
219}
220
221
222/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700223 Public function, see header file
224 */
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530225void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700226{
227 pCtx->pStringAllocator = (void *)pAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530228 pCtx->bStringAllocateAll = bAllocAll;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700229}
230
231
232/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700233 This decodes the fundamental part of a CBOR data item, the type and number
234
235 This is the Counterpart to InsertEncodedTypeAndNumber().
236
237 This does the network->host byte order conversion. The conversion here
238 also results in the conversion for floats in addition to that for
239 lengths, tags and integer values.
240
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700241 This returns:
242 pnMajorType -- the major type for the item
243 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
244 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
245
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700246 */
247inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
248{
249 int nReturn;
250
251 // Get the initial byte that every CBOR data item has
252 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
253
254 // Break down the initial byte
255 const uint8_t uTmpMajorType = InitialByte >> 5;
256 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
257
258 // 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 +0700259 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260 uint64_t uTmpValue;
261 switch(uAdditionalInfo) {
262
263 case LEN_IS_ONE_BYTE:
264 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
265 break;
266
267 case LEN_IS_TWO_BYTES:
268 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
269 break;
270
271 case LEN_IS_FOUR_BYTES:
272 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
273 break;
274
275 case LEN_IS_EIGHT_BYTES:
276 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
277 break;
278
279 case ADDINFO_RESERVED1: // reserved by CBOR spec
280 case ADDINFO_RESERVED2: // reserved by CBOR spec
281 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700282 nReturn = QCBOR_ERR_UNSUPPORTED;
283 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700284
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700285 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700286 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700287 uTmpValue = uAdditionalInfo;
288 break;
289 }
290
291 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
292 // There is no harm in this. This following check takes care of catching all of
293 // these errors.
294
295 if(UsefulInputBuf_GetError(pUInBuf)) {
296 nReturn = QCBOR_ERR_HIT_END;
297 goto Done;
298 }
299
300 // All successful if we got here.
301 nReturn = QCBOR_SUCCESS;
302 *pnMajorType = uTmpMajorType;
303 *puNumber = uTmpValue;
304 *puAdditionalInfo = uAdditionalInfo;
305
306Done:
307 return nReturn;
308}
309
310
311/*
312 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
313 use it these days and the test vectors in the RFC are so. All integers in the CBOR
314 structure are positive and the major type indicates positive or negative.
315 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
316 and negative integers down to 2^x. Note that negative numbers can be one
317 more away from zero than positive.
318 Stdint, as far as I can tell, uses two's compliment to represent
319 negative integers.
320
321 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
322 used here in any way including in the interface
323 */
324inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
325{
326 int nReturn = QCBOR_SUCCESS;
327
328 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
329 if (uNumber <= INT64_MAX) {
330 pDecodedItem->val.int64 = (int64_t)uNumber;
331 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
332
333 } else {
334 pDecodedItem->val.uint64 = uNumber;
335 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
336
337 }
338 } else {
339 if(uNumber <= INT64_MAX) {
340 pDecodedItem->val.int64 = -uNumber-1;
341 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
342
343 } else {
344 // C can't represent a negative integer in this range
345 // so it is an error. todo -- test this condition
346 nReturn = QCBOR_ERR_INT_OVERFLOW;
347 }
348 }
349
350 return nReturn;
351}
352
353// Make sure #define value line up as DecodeSimple counts on this.
354#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
355#error QCBOR_TYPE_FALSE macro value wrong
356#endif
357
358#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
359#error QCBOR_TYPE_TRUE macro value wrong
360#endif
361
362#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
363#error QCBOR_TYPE_NULL macro value wrong
364#endif
365
366#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
367#error QCBOR_TYPE_UNDEF macro value wrong
368#endif
369
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700370#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
371#error QCBOR_TYPE_BREAK macro value wrong
372#endif
373
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700374#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
375#error QCBOR_TYPE_DOUBLE macro value wrong
376#endif
377
378#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
379#error QCBOR_TYPE_FLOAT macro value wrong
380#endif
381
382/*
383 Decode true, false, floats, break...
384 */
385
386inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
387{
388 int nReturn = QCBOR_SUCCESS;
389
390 // uAdditionalInfo is 5 bits from the initial byte
391 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
392 pDecodedItem->uDataType = uAdditionalInfo;
393
394 switch(uAdditionalInfo) {
395 case ADDINFO_RESERVED1: // 28
396 case ADDINFO_RESERVED2: // 29
397 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700398 nReturn = QCBOR_ERR_UNSUPPORTED;
399 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700400
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700401 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700402 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
403 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
404 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700405 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700406 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
407 break;
408 case DOUBLE_PREC_FLOAT:
409 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
410 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700411
412 case CBOR_SIMPLEV_FALSE: // 20
413 case CBOR_SIMPLEV_TRUE: // 21
414 case CBOR_SIMPLEV_NULL: // 22
415 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700416 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700417 break; // nothing to do
418
419 case CBOR_SIMPLEV_ONEBYTE: // 24
420 if(uNumber <= CBOR_SIMPLE_BREAK) {
421 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
422 nReturn = QCBOR_ERR_INVALID_CBOR;
423 goto Done;
424 }
425 // fall through intentionally
426
427 default: // 0-19
428 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
429 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
430 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
431 pDecodedItem->val.uSimple = (uint8_t)uNumber;
432 break;
433 }
434
435Done:
436 return nReturn;
437}
438
439
440
441/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530442 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700443 */
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530444inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700445{
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530446 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700447
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530448 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
449 if(UsefulBuf_IsNULLC(Bytes)) {
450 // Failed to get the bytes for this string item
451 nReturn = QCBOR_ERR_HIT_END;
452 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700453 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530454
455 if(pAlloc) {
456 // We are asked to use string allocator to make a copy
457 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen);
458 if(UsefulBuf_IsNULL(NewMem)) {
459 nReturn = QCBOR_ERR_STRING_ALLOC;
460 goto Done;
461 }
462 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
463 } else {
464 // Normal case with no string allocator
465 pDecodedItem->val.string = Bytes;
466 }
467 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700468
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530469Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700470 return nReturn;
471}
472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700473
474/*
475 Mostly just assign the right data type for the date string.
476 */
477inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
478{
479 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
480 return QCBOR_ERR_BAD_OPT_TAG;
481 }
482 pDecodedItem->val.dateString = Item.val.string;
483 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
484 pDecodedItem->uTagBits = Item.uTagBits;
485 pDecodedItem->uTag = Item.uTag;
486 return QCBOR_SUCCESS;
487}
488
489
490/*
491 Mostly just assign the right data type for the bignum.
492 */
493inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
494{
495 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
496 return QCBOR_ERR_BAD_OPT_TAG;
497 }
498 pDecodedItem->val.bigNum = Item.val.string;
499 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
500 pDecodedItem->uTagBits = Item.uTagBits;
501 pDecodedItem->uTag = Item.uTag;
502 return QCBOR_SUCCESS;
503}
504
505
506/*
507 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
508 */
509static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
510{
511 int nReturn = QCBOR_SUCCESS;
512
513 pDecodedItem->uTagBits = Item.uTagBits;
514 pDecodedItem->uTag = Item.uTag;
515 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
516 pDecodedItem->val.epochDate.fSecondsFraction = 0;
517
518 switch (Item.uDataType) {
519
520 case QCBOR_TYPE_INT64:
521 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
522 break;
523
524 case QCBOR_TYPE_UINT64:
525 if(Item.val.uint64 > INT64_MAX) {
526 nReturn = QCBOR_ERR_DATE_OVERFLOW;
527 goto Done;
528 }
529 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
530 break;
531
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800532 case QCBOR_TYPE_FLOAT:
533 // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
534 if(Item.val.fnum > INT64_MAX) {
535 nReturn = QCBOR_ERR_DATE_OVERFLOW;
536 goto Done;
537 }
538 pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
539 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
540 break;
541
542 case QCBOR_TYPE_DOUBLE:
543 if(Item.val.dfnum > INT64_MAX) {
544 nReturn = QCBOR_ERR_DATE_OVERFLOW;
545 goto Done;
546 }
547 pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
548 pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
549 break;
550
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700551 default:
552 nReturn = QCBOR_ERR_BAD_OPT_TAG;
553 }
554
555Done:
556 return nReturn;
557}
558
559
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700560
561
562// Make sure the constants align as this is assumed by the GetAnItem() implementation
563#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
564#error QCBOR_TYPE_ARRAY value not lined up with major type
565#endif
566#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
567#error QCBOR_TYPE_MAP value not lined up with major type
568#endif
569
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700571 This gets a single data item and decodes it including preceding optional tagging. This does not
572 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
573 maps are handled at the next level up in GetNext().
574
575 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
576 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700577 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700578static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
579{
580 int nReturn;
581
582 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
583 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
584 int uMajorType;
585 uint64_t uNumber;
586 uint8_t uAdditionalInfo;
587
588 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
589
590 // Error out here if we got into trouble on the type and number.
591 // The code after this will not work if the type and number is not good.
592 if(nReturn)
593 goto Done;
594
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530595 pDecodedItem->uTagBits = 0;
596 pDecodedItem->uTag = 0;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530597 pDecodedItem->uDataAlloc = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700598
599 // At this point the major type and the value are valid. We've got the type and the number that
600 // starts every CBOR data item.
601 switch (uMajorType) {
602 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
603 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
604 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
605 break;
606
607 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
608 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
609 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
610 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530611 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700612 } else {
613 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
614 }
615 break;
616
617 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
618 case CBOR_MAJOR_TYPE_MAP: // Major type 5
619 // Record the number of items in the array or map
620 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
621 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
622 goto Done;
623 }
624 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530625 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700626 } else {
627 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
628 }
629 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
630 break;
631
632 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
633 pDecodedItem->uTag = uNumber;
634 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
635 break;
636
637 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
638 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
639 break;
640
641 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
642 nReturn = QCBOR_ERR_UNSUPPORTED;
643 break;
644 }
645
646Done:
647 return nReturn;
648}
649
650
651
652/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800653 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530654 individual segment items together into one QCBORItem using the
655 string allocator.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530656
657 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700658 */
659static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
660{
661 int nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530662 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530663 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700664
665 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
666 if(nReturn) {
667 goto Done;
668 }
669
670 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530671 // code in this function from here down can be eliminated. Run tests, except
672 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700673
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800674 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700675 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
676 goto Done; // no need to do any work here on non-string types
677 }
678
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800679 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530680 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800681 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700682 }
683
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530684 // Can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700685 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700686 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
687 goto Done;
688 }
689
690 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800691 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700692 const uint8_t uStringType = pDecodedItem->uDataType;
693
694 // Loop getting segments of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700695 for(;;) {
696 // Get item for next segment
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530697 QCBORItem StringSegmentItem;
698 // NULL passed to never string alloc segments of indefinite length strings
699 nReturn = GetNext_Item(&(me->InBuf), &StringSegmentItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700700 if(nReturn) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530701 break; // Error getting the next segment
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700702 }
703
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530704 // See if it is a marker at end of indefinite length string
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530705 if(StringSegmentItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800706 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700707 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530708 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700709 break;
710 }
711
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530712 // Match data type of segment to type at beginning.
713 // Also catches error of other non-string types that don't belong.
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530714 if(StringSegmentItem.uDataType != uStringType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700715 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
716 break;
717 }
718
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530719 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530720 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
721 UNCONST_POINTER(FullString.ptr),
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530722 FullString.len + StringSegmentItem.val.string.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700723 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530724 // Allocation of memory for the string failed
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700725 nReturn = QCBOR_ERR_STRING_ALLOC;
726 break;
727 }
728
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530729 // Copy new string segment at the end of string so far.
730 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringSegmentItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700731 }
732
733Done:
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530734 if(pAlloc && nReturn && !UsefulBuf_IsNULLC(FullString)) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700735 // Getting item failed, clean up the allocated memory
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530736 (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700737 }
738
739 return nReturn;
740}
741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742
743/*
744 Returns an error if there was something wrong with the optional item or it couldn't
745 be handled.
746 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700747static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700749 int nReturn;
750
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530751 // TODO: optimize loop below so there is only one call to GetNext_FullItem?
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700752 nReturn = GetNext_FullItem(me, pDecodedItem);
753 if(nReturn) {
754 goto Done;
755 }
756
757 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
758 goto Done;
759 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760
761 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700762 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763
764 QCBORItem Item;
765
766 do {
767 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
768 uTagFlags |= 0x01LL << uTagToProcess;
769 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
770 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
771 }
772 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700773 greater than 63. Ignoring tags that are not understoof
774 is allowed by the standard. Multiple tags are
775 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778 if(nReturn) {
779 // Bail out of the whole item fetch on any sort of error here
780 goto Done;
781 }
782
783 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
784 break;
785 }
786
787 uTagToProcess = Item.uTag;
788 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790
791 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 CBOR allows multiple tags on a data item. It also defines
793 a number of standard tag values, most of which are
794 less than 64. This code can deal with multiple tag
795 values that are less than 64 and the last tag of multiple
796 if the value is more than 64. Or said another way
797 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801 At this point in this code. uTagFlags has all the flags
802 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700804 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 */
806
807 Item.uTagBits = uTagFlags;
808 Item.uTag = uTagToProcess;
809
810 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
811 case 0:
812 // No tags we know about. Pass them up
813 *pDecodedItem = Item;
814 break;
815
816 case QCBOR_TAGFLAG_DATE_STRING:
817 nReturn = DecodeDateString(Item, pDecodedItem);
818 break;
819
820 case QCBOR_TAGFLAG_DATE_EPOCH:
821 nReturn = DecodeDateEpoch(Item, pDecodedItem);
822 break;
823
824 case QCBOR_TAGFLAG_POS_BIGNUM:
825 case QCBOR_TAGFLAG_NEG_BIGNUM:
826 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
827 break;
828
829 default:
830 // Encountering some mixed up CBOR like something that
831 // is tagged as both a string and integer date.
832 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700833 }
834
835Done:
836 return nReturn;
837}
838
839
840/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800841 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700842 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846 if(nReturn)
847 goto Done;
848
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800849 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
850 goto Done;
851 }
852
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700853 // If in a map and the right decoding mode, get the label
854 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
855 // In a map and caller wants maps decoded, not treated as arrays
856
857 // Get the next item which will be the real data; Item will be the label
858 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530859 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700860 if(nReturn)
861 goto Done;
862
863 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
864 // strings are always good labels
865 pDecodedItem->label.string = LabelItem.val.string;
866 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
867 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
868 // It's not a string and we only want strings, probably for easy translation to JSON
869 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872 pDecodedItem->label.int64 = LabelItem.val.int64;
873 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
874 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
875 pDecodedItem->label.uint64 = LabelItem.val.uint64;
876 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
877 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
878 pDecodedItem->label.string = LabelItem.val.string;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530879 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700880 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
881 } else {
882 // label is not an int or a string. It is an arrray
883 // or a float or such and this implementation doesn't handle that.
884 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
885 goto Done;
886 }
887 }
888
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889Done:
890 return nReturn;
891}
892
893
894/*
895 Public function, see header qcbor.h file
896 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
898{
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530899 // The public entry point for fetching and parsing the next QCBORItem.
900 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901 int nReturn;
902
Laurence Lundblade6de37062018-10-15 12:22:42 +0530903 nReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800904 if(nReturn) {
905 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530907
908 // Break ending arrays/maps are always processed at the end of this function.
909 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530910 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +0530911 nReturn = QCBOR_ERR_BAD_BREAK;
912 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530913 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700914
Laurence Lundblade6de37062018-10-15 12:22:42 +0530915 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530916 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530917 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
918
919 // Process the item just received for descent or decrement, and
920 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800921 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800922 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800923 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800924 // Maps and arrays do count in as items in the map/array that encloses
925 // them so a decrement needs to be done for them too, but that is done
926 // only when all the items in them have been processed, not when they
927 // are opened.
928 } else {
929 // Decrement the count of items in the enclosing map/array
930 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +0530931 // triggers a decrement in the map/array above that and
932 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800933 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 }
Laurence Lundblade6de37062018-10-15 12:22:42 +0530935 if(nReturn) {
936 goto Done;
937 }
938
939 // For indefinite length maps/arrays, looking at any and
940 // all breaks that might terminate them. The equivalent
941 // for definite length maps/arrays happens in
942 // DecodeNesting_DecrementCount().
943 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
944 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
945 // Peek forward one item to see if it is a break.
946 QCBORItem Peek;
947 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
948 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
949 if(nReturn) {
950 goto Done;
951 }
952 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
953 // It is not a break, rewind so it can be processed normally.
954 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
955 break;
956 }
957 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530958 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +0530959 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
960 if(nReturn) {
961 // break occured outside of an indefinite length array/map
962 goto Done;
963 }
964 }
965 }
966
967 // Tell the caller what level is next. This tells them what maps/arrays
968 // were closed out and makes it possible for them to reconstruct
969 // the tree with just the information returned by GetNext
970 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700971
972Done:
973 return nReturn;
974}
975
976
977/*
Laurence Lundblade6de37062018-10-15 12:22:42 +0530978 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530979 next one down. If a layer has no work to do for a particular item
980 it returns quickly.
981
982 - QCBORDecode_GetNext -- The top layer manages the beginnings and
983 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +0530984 out of maps/arrays. It processes all breaks that terminate
985 maps and arrays.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530986
987 - GetNext_MapEntry -- This handles the combining of two
988 items, the label and the data, that make up a map entry.
989 It only does work on maps. It combines the label and data
990 items into one labeled item.
991
992 - GetNext_TaggedItem -- This handles the type 6 tagged items.
993 It accumulates all the tags and combines them with the following
994 non-tagged item. If the tagged item is something that is understood
995 like a date, the decoding of that item is invoked.
996
997 - GetNext_FullItem -- This assembles the sub items that make up
998 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +0530999 string allocater to create contiguous space for the item. It
1000 processes all breaks that are part of indefinite length strings.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301001
1002 - GetNext_Item -- This gets and decodes the most atomic
1003 item in CBOR, the thing with an initial byte containing
1004 the major type.
1005
1006 */
1007
1008
1009/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001010 Public function, see header qcbor.h file
1011 */
1012int QCBORDecode_Finish(QCBORDecodeContext *me)
1013{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001014 int nReturn = QCBOR_SUCCESS;
1015
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001016 // Error out if all the maps/arrays are not closed out
1017 if(DecodeNesting_IsNested(&(me->nesting))) {
1018 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1019 goto Done;
1020 }
1021
1022 // Error out if not all the bytes are consumed
1023 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1024 nReturn = QCBOR_ERR_EXTRA_BYTES;
1025 }
1026
1027Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301028 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001029 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 if(me->pStringAllocator) {
1031 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1032 if(pAllocator->fDestructor) {
1033 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1034 }
1035 }
1036
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001038}
1039
1040
1041
Laurence Lundblade7023b952018-10-02 01:54:24 -07001042/*
1043
1044 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
1045
1046 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301047
Laurence Lundblade7023b952018-10-02 01:54:24 -07001048
1049 */
1050
1051
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001052/*
1053
1054Decoder errors handled in this file
1055
1056 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001057
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001058 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1059
1060 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1061
1062 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301063
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001064 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1065
1066 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1067
1068 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1069
1070 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1071
1072 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1073
1074 */
1075
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001076
1077
1078typedef struct {
1079 QCBORStringAllocator StringAllocator;
1080 uint8_t *pStart;
1081 uint8_t *pEnd;
1082 uint8_t *pFree;
1083} MemPool;
1084
1085
1086/*
1087 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1088 */
1089static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1090{
1091 MemPool *me = (MemPool *)ctx;
1092 void *pReturn = NULL;
1093
1094 if(pMem) {
1095 // Realloc case
1096 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001097 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1098 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 pReturn = pMem;
1100 }
1101 } else {
1102 // New chunk case
1103 if(me->pFree + uNewSize <= me->pEnd) {
1104 pReturn = me->pFree;
1105 me->pFree += uNewSize;
1106 }
1107 }
1108
1109 return (UsefulBuf){pReturn, uNewSize};
1110}
1111
1112
1113static void MemPool_Free(void *ctx, void *pOldMem)
1114{
1115 MemPool *me = (MemPool *)ctx;
1116 me->pFree = pOldMem;
1117}
1118
1119
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301120int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001121{
1122 if(Pool.len < sizeof(MemPool)+1) {
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301123 return 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 }
1125
1126 MemPool *pMP = (MemPool *)Pool.ptr;
1127
1128 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1129 pMP->StringAllocator.fFree = MemPool_Free;
1130 pMP->StringAllocator.fDestructor = NULL;
1131
Laurence Lundblade570fab52018-10-13 18:28:27 +08001132 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001134 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135 pMP->StringAllocator.pAllocaterContext = pMP;
1136
1137 me->pStringAllocator = pMP;
1138 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301139
1140 return 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001141}
1142
1143
1144