blob: 187419b811f2b90b472ca3e46c1aaf0154192481 [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 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
921{
922 int nReturn;
923
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800924 // Loop getting items until one that is not a break is fetched
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800925 nReturn = GetNext_GetNonBreak(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800926 if(nReturn) {
927 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928 }
929
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800930 // 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 +0700931
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800932 // Record the nesting level for this data item before processing any of
933 // decrementing and decsending
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
935
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800936 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800937 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800938 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800939 // Maps and arrays do count in as items in the map/array that encloses
940 // them so a decrement needs to be done for them too, but that is done
941 // only when all the items in them have been processed, not when they
942 // are opened.
943 } else {
944 // Decrement the count of items in the enclosing map/array
945 // If the count in the enclosing map/array goes to zero, that
946 // triggers a decrement for in the map/array above that and
947 // and ascend in mnesting level.
948 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949 }
950
951Done:
952 return nReturn;
953}
954
955
956/*
Laurence Lundblade0fb2f642018-10-11 19:33:35 +0530957 Decoding items is done in 6 layered functions, one calling the
958 next one down. If a layer has no work to do for a particular item
959 it returns quickly.
960
961 - QCBORDecode_GetNext -- The top layer manages the beginnings and
962 ends of maps and arrays. It tracks descending into and ascending
963 out of maps/arrays.
964
965 - GetNext_GetNonBreak -- This handles the "break" items that
966 terminate indefinite length arrays and maps. It's job is to
967 loop over one or more breaks.
968
969 - GetNext_MapEntry -- This handles the combining of two
970 items, the label and the data, that make up a map entry.
971 It only does work on maps. It combines the label and data
972 items into one labeled item.
973
974 - GetNext_TaggedItem -- This handles the type 6 tagged items.
975 It accumulates all the tags and combines them with the following
976 non-tagged item. If the tagged item is something that is understood
977 like a date, the decoding of that item is invoked.
978
979 - GetNext_FullItem -- This assembles the sub items that make up
980 an indefinte length string into one string item. It uses the
981 string allocater to create contiguous space for the item.
982
983 - GetNext_Item -- This gets and decodes the most atomic
984 item in CBOR, the thing with an initial byte containing
985 the major type.
986
987 */
988
989
990/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700991 Public function, see header qcbor.h file
992 */
993int QCBORDecode_Finish(QCBORDecodeContext *me)
994{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 int nReturn = QCBOR_SUCCESS;
996
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800997 // Consume any last breaks ending indefinite length arrays or maps here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 // Definite length arrays and maps get closed off above when they
999 // the last item in them is consumed; they are not handled here.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001000 if(DecodeNesting_IsNested(&(me->nesting))) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 QCBORItem Item;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001002 nReturn = GetNext_GetNonBreak(me, &Item);
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001003 if(nReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001004 goto Done;
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001005 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001006 }
1007
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001008 // Error out if all the maps/arrays are not closed out
1009 if(DecodeNesting_IsNested(&(me->nesting))) {
1010 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1011 goto Done;
1012 }
1013
1014 // Error out if not all the bytes are consumed
1015 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1016 nReturn = QCBOR_ERR_EXTRA_BYTES;
1017 }
1018
1019Done:
1020 // Call the destructor for the string allocator if there is one
1021 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022 if(me->pStringAllocator) {
1023 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1024 if(pAllocator->fDestructor) {
1025 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1026 }
1027 }
1028
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001030}
1031
1032
1033
Laurence Lundblade7023b952018-10-02 01:54:24 -07001034/*
1035
1036 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
1037
1038 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301039
Laurence Lundblade7023b952018-10-02 01:54:24 -07001040
1041 */
1042
1043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001044/*
1045
1046Decoder errors handled in this file
1047
1048 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001050 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1051
1052 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1053
1054 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
1055
1056 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
1057
1058 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1059
1060 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1061
1062 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1063
1064 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1065
1066 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1067
1068 */
1069
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070
1071
1072typedef struct {
1073 QCBORStringAllocator StringAllocator;
1074 uint8_t *pStart;
1075 uint8_t *pEnd;
1076 uint8_t *pFree;
1077} MemPool;
1078
1079
1080/*
1081 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1082 */
1083static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1084{
1085 MemPool *me = (MemPool *)ctx;
1086 void *pReturn = NULL;
1087
1088 if(pMem) {
1089 // Realloc case
1090 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001091 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1092 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093 pReturn = pMem;
1094 }
1095 } else {
1096 // New chunk case
1097 if(me->pFree + uNewSize <= me->pEnd) {
1098 pReturn = me->pFree;
1099 me->pFree += uNewSize;
1100 }
1101 }
1102
1103 return (UsefulBuf){pReturn, uNewSize};
1104}
1105
1106
1107static void MemPool_Free(void *ctx, void *pOldMem)
1108{
1109 MemPool *me = (MemPool *)ctx;
1110 me->pFree = pOldMem;
1111}
1112
1113
1114void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
1115{
1116 if(Pool.len < sizeof(MemPool)+1) {
1117 return; // Failure will happen when first string needs to be allocated
1118 }
1119
1120 MemPool *pMP = (MemPool *)Pool.ptr;
1121
1122 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1123 pMP->StringAllocator.fFree = MemPool_Free;
1124 pMP->StringAllocator.fDestructor = NULL;
1125
1126 pMP->pStart = Pool.ptr + sizeof(MemPool);
1127 pMP->pFree = pMP->pStart;
1128 pMP->pEnd = Pool.ptr + Pool.len;
1129 pMP->StringAllocator.pAllocaterContext = pMP;
1130
1131 me->pStringAllocator = pMP;
1132 me->bStringAllocateAll = bAllStrings;
1133}
1134
1135
1136