blob: eccd469e5b00129f4206c17e40b20fb9dbb7e84e [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/*
83 Collection of functions to track the map and array nesting for decoding
84 */
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{
98 if(!DecodeNesting_IsNested(pNesting)) {
99 return 0;
100 }
101
102 return pNesting->pCurrent->uCount == UINT16_MAX;
103}
104
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700105inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
106{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700107 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700109 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700110
111 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
112}
113
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700114inline static void DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
115{
116 pNesting->pCurrent--;
117}
118
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700119inline static void DecodeNesting_Decrement(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700120{
121 if(!DecodeNesting_IsNested(pNesting)) {
122 return; // at top level where there is no tracking
123 }
124
125 // Decrement
126 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700127
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700128 // Pop up nesting levels if the counts at the levels is zero
129 while(0 == pNesting->pCurrent->uCount && DecodeNesting_IsNested(pNesting)) {
130 pNesting->pCurrent--;
131 }
132}
133
134inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uMajorType, int uCount)
135{
136 int nReturn = QCBOR_SUCCESS;
137
138 if(uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
139 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
140 goto Done;
141 }
142
143 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
144 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
145 goto Done;
146 }
147
148 pNesting->pCurrent++;
149
150 pNesting->pCurrent->uMajorType = uMajorType;
151 pNesting->pCurrent->uCount = uCount;
152
153Done:
154 return nReturn;;
155}
156
157inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
158{
159 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
160}
161
162inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
163{
164 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
165}
166
167
168
169
170/*
171 Public function, see header file
172 */
173void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
174{
175 memset(me, 0, sizeof(QCBORDecodeContext));
176 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
177 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
178 // if the default normal mode of 0 was set.
179 me->uDecodeMode = nDecodeMode;
180 DecodeNesting_Init(&(me->nesting));
181}
182
183
184/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700185 Public function, see header file
186 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700187void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700188{
189 pCtx->pStringAllocator = (void *)pAllocator;
190}
191
192
193/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700194 This decodes the fundamental part of a CBOR data item, the type and number
195
196 This is the Counterpart to InsertEncodedTypeAndNumber().
197
198 This does the network->host byte order conversion. The conversion here
199 also results in the conversion for floats in addition to that for
200 lengths, tags and integer values.
201
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700202 This returns:
203 pnMajorType -- the major type for the item
204 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
205 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
206
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700207 */
208inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
209{
210 int nReturn;
211
212 // Get the initial byte that every CBOR data item has
213 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
214
215 // Break down the initial byte
216 const uint8_t uTmpMajorType = InitialByte >> 5;
217 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
218
219 // 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 +0700220 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700221 uint64_t uTmpValue;
222 switch(uAdditionalInfo) {
223
224 case LEN_IS_ONE_BYTE:
225 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
226 break;
227
228 case LEN_IS_TWO_BYTES:
229 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
230 break;
231
232 case LEN_IS_FOUR_BYTES:
233 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
234 break;
235
236 case LEN_IS_EIGHT_BYTES:
237 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
238 break;
239
240 case ADDINFO_RESERVED1: // reserved by CBOR spec
241 case ADDINFO_RESERVED2: // reserved by CBOR spec
242 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700243 nReturn = QCBOR_ERR_UNSUPPORTED;
244 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700245
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700246 case LEN_IS_INDEFINITE:
247 // Fall through to see what happens: TODO: check this.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248
249 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700250 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251 uTmpValue = uAdditionalInfo;
252 break;
253 }
254
255 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
256 // There is no harm in this. This following check takes care of catching all of
257 // these errors.
258
259 if(UsefulInputBuf_GetError(pUInBuf)) {
260 nReturn = QCBOR_ERR_HIT_END;
261 goto Done;
262 }
263
264 // All successful if we got here.
265 nReturn = QCBOR_SUCCESS;
266 *pnMajorType = uTmpMajorType;
267 *puNumber = uTmpValue;
268 *puAdditionalInfo = uAdditionalInfo;
269
270Done:
271 return nReturn;
272}
273
274
275/*
276 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
277 use it these days and the test vectors in the RFC are so. All integers in the CBOR
278 structure are positive and the major type indicates positive or negative.
279 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
280 and negative integers down to 2^x. Note that negative numbers can be one
281 more away from zero than positive.
282 Stdint, as far as I can tell, uses two's compliment to represent
283 negative integers.
284
285 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
286 used here in any way including in the interface
287 */
288inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
289{
290 int nReturn = QCBOR_SUCCESS;
291
292 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
293 if (uNumber <= INT64_MAX) {
294 pDecodedItem->val.int64 = (int64_t)uNumber;
295 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
296
297 } else {
298 pDecodedItem->val.uint64 = uNumber;
299 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
300
301 }
302 } else {
303 if(uNumber <= INT64_MAX) {
304 pDecodedItem->val.int64 = -uNumber-1;
305 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
306
307 } else {
308 // C can't represent a negative integer in this range
309 // so it is an error. todo -- test this condition
310 nReturn = QCBOR_ERR_INT_OVERFLOW;
311 }
312 }
313
314 return nReturn;
315}
316
317// Make sure #define value line up as DecodeSimple counts on this.
318#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
319#error QCBOR_TYPE_FALSE macro value wrong
320#endif
321
322#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
323#error QCBOR_TYPE_TRUE macro value wrong
324#endif
325
326#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
327#error QCBOR_TYPE_NULL macro value wrong
328#endif
329
330#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
331#error QCBOR_TYPE_UNDEF macro value wrong
332#endif
333
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700334#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
335#error QCBOR_TYPE_BREAK macro value wrong
336#endif
337
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700338#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
339#error QCBOR_TYPE_DOUBLE macro value wrong
340#endif
341
342#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
343#error QCBOR_TYPE_FLOAT macro value wrong
344#endif
345
346/*
347 Decode true, false, floats, break...
348 */
349
350inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
351{
352 int nReturn = QCBOR_SUCCESS;
353
354 // uAdditionalInfo is 5 bits from the initial byte
355 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
356 pDecodedItem->uDataType = uAdditionalInfo;
357
358 switch(uAdditionalInfo) {
359 case ADDINFO_RESERVED1: // 28
360 case ADDINFO_RESERVED2: // 29
361 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700362 nReturn = QCBOR_ERR_UNSUPPORTED;
363 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700364
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700365 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700366 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
367 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
368 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700369 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700370 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
371 break;
372 case DOUBLE_PREC_FLOAT:
373 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
374 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700375
376 case CBOR_SIMPLEV_FALSE: // 20
377 case CBOR_SIMPLEV_TRUE: // 21
378 case CBOR_SIMPLEV_NULL: // 22
379 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700380 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700381 break; // nothing to do
382
383 case CBOR_SIMPLEV_ONEBYTE: // 24
384 if(uNumber <= CBOR_SIMPLE_BREAK) {
385 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
386 nReturn = QCBOR_ERR_INVALID_CBOR;
387 goto Done;
388 }
389 // fall through intentionally
390
391 default: // 0-19
392 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
393 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
394 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
395 pDecodedItem->val.uSimple = (uint8_t)uNumber;
396 break;
397 }
398
399Done:
400 return nReturn;
401}
402
403
404
405/*
406 Decode text and byte strings
407 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700408inline static int DecodeBytesOld(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700409{
410 const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
411
412 int nReturn = QCBOR_ERR_HIT_END;
413
414 if(pBytes != NULL) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700415 pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
416 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700417 nReturn = QCBOR_SUCCESS;
418 }
419
420 return nReturn;
421}
422
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700423inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
424{
425 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uNumber);
426
427 int nReturn = QCBOR_ERR_HIT_END;
428
429 if(!UsefulBuf_IsNULLC(Bytes)) {
430 if(pAlloc) {
431 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uNumber);
432 if(UsefulBuf_IsNULL(NewMem)) {
433 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
434 } else {
435 // TODO: failure
436 }
437 } else {
438 pDecodedItem->val.string = Bytes;
439 }
440 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
441 nReturn = QCBOR_SUCCESS;
442 }
443
444 return nReturn;
445}
446
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700447
448/*
449 Mostly just assign the right data type for the date string.
450 */
451inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
452{
453 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
454 return QCBOR_ERR_BAD_OPT_TAG;
455 }
456 pDecodedItem->val.dateString = Item.val.string;
457 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
458 pDecodedItem->uTagBits = Item.uTagBits;
459 pDecodedItem->uTag = Item.uTag;
460 return QCBOR_SUCCESS;
461}
462
463
464/*
465 Mostly just assign the right data type for the bignum.
466 */
467inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
468{
469 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
470 return QCBOR_ERR_BAD_OPT_TAG;
471 }
472 pDecodedItem->val.bigNum = Item.val.string;
473 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
474 pDecodedItem->uTagBits = Item.uTagBits;
475 pDecodedItem->uTag = Item.uTag;
476 return QCBOR_SUCCESS;
477}
478
479
480/*
481 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
482 */
483static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
484{
485 int nReturn = QCBOR_SUCCESS;
486
487 pDecodedItem->uTagBits = Item.uTagBits;
488 pDecodedItem->uTag = Item.uTag;
489 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
490 pDecodedItem->val.epochDate.fSecondsFraction = 0;
491
492 switch (Item.uDataType) {
493
494 case QCBOR_TYPE_INT64:
495 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
496 break;
497
498 case QCBOR_TYPE_UINT64:
499 if(Item.val.uint64 > INT64_MAX) {
500 nReturn = QCBOR_ERR_DATE_OVERFLOW;
501 goto Done;
502 }
503 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
504 break;
505
506 default:
507 nReturn = QCBOR_ERR_BAD_OPT_TAG;
508 }
509
510Done:
511 return nReturn;
512}
513
514
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700515
516
517// Make sure the constants align as this is assumed by the GetAnItem() implementation
518#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
519#error QCBOR_TYPE_ARRAY value not lined up with major type
520#endif
521#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
522#error QCBOR_TYPE_MAP value not lined up with major type
523#endif
524
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700525/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700526 This gets a single data item and decodes it including preceding optional tagging. This does not
527 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
528 maps are handled at the next level up in GetNext().
529
530 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
531 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700533
534static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
535{
536 int nReturn;
537
538 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
539 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
540 int uMajorType;
541 uint64_t uNumber;
542 uint8_t uAdditionalInfo;
543
544 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
545
546 // Error out here if we got into trouble on the type and number.
547 // The code after this will not work if the type and number is not good.
548 if(nReturn)
549 goto Done;
550
551 pDecodedItem->uTagBits = 0;
552 pDecodedItem->uTag = 0;
553 pDecodedItem->uAllocated = 0;
554
555 // At this point the major type and the value are valid. We've got the type and the number that
556 // starts every CBOR data item.
557 switch (uMajorType) {
558 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
559 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
560 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
561 break;
562
563 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
564 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
565 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
566 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
567 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; // TODO: SIZE_MAX this is OK, right?
568 } else {
569 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
570 }
571 break;
572
573 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
574 case CBOR_MAJOR_TYPE_MAP: // Major type 5
575 // Record the number of items in the array or map
576 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
577 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
578 goto Done;
579 }
580 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
581 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length; TODO: a better way?
582 } else {
583 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
584 }
585 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
586 break;
587
588 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
589 pDecodedItem->uTag = uNumber;
590 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
591 break;
592
593 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
594 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
595 break;
596
597 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
598 nReturn = QCBOR_ERR_UNSUPPORTED;
599 break;
600 }
601
602Done:
603 return nReturn;
604}
605
606
607
608/*
609 This layer deals with indefinite length strings
610
611 */
612static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
613{
614 int nReturn;
615 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
616
617 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
618 if(nReturn) {
619 goto Done;
620 }
621
622 // To reduce code size by removing support for indefinite length strings, the
623 // code in this function from here down can be eliminated. Run tests to be sure
624 // all is OK if you remove this.
625 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
626 nReturn = QCBOR_ERR_BAD_BREAK;
627 goto Done;
628 }
629
630 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
631 goto Done; // no need to do any work here on non-string types
632 }
633
634 if(pDecodedItem->val.string.len != SIZE_MAX) { // TODO: is this right? Is there a better way to mark this?
635 goto Done; // length is not indefinite, so no work to do
636 }
637
638 if(pAlloc == NULL) {
639 // can't do indefinite length strings without an allocator
640 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
641 goto Done;
642 }
643
644 // There is an indefinite length string to work on...
645 const uint8_t uStringType = pDecodedItem->uDataType;
646
647 // Loop getting segments of indefinite string
648 UsefulBufC FullString = NULLUsefulBufC;
649 for(;;) {
650 // Get item for next segment
651 QCBORItem Item;
652 nReturn = GetNext_Item(&(me->InBuf), &Item, NULL); // Never alloc segments of indefinite length strings
653 if(nReturn) {
654 // Error getting the next segment
655 break;
656 }
657
658 // See if it is marker at end of indefinite length string
659 if(Item.uDataType == QCBOR_TYPE_BREAK) {
660 // SUCCESS!!!
661 pDecodedItem->val.string = FullString;
662 pDecodedItem->uAllocated = 1;
663 break;
664 }
665
666 // Match data type of segment to type at beginning
667 if(Item.uDataType != uStringType) {
668 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
669 break;
670 }
671
672 // Expand the buffer so it can fit
673 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, (void *)FullString.ptr, FullString.len + Item.val.string.len);
674 if(UsefulBuf_IsNULL(NewMem)) {
675 nReturn = QCBOR_ERR_STRING_ALLOC;
676 break;
677 }
678
679 // Copy data to the end of it.
680 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
681 }
682
683Done:
684 if(nReturn && FullString.ptr) {
685 // Getting item failed, clean up the allocated memory
686 (pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
687 }
688
689 return nReturn;
690}
691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692
693/*
694 Returns an error if there was something wrong with the optional item or it couldn't
695 be handled.
696 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700697static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700698{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700699 int nReturn;
700
701 nReturn = GetNext_FullItem(me, pDecodedItem);
702 if(nReturn) {
703 goto Done;
704 }
705
706 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
707 goto Done;
708 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709
710 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700711 uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712
713 QCBORItem Item;
714
715 do {
716 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
717 uTagFlags |= 0x01LL << uTagToProcess;
718 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
719 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
720 }
721 /* This code ignores the all but the first tag of value
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700722 greater than 63. Ignoring tags that are not understoof
723 is allowed by the standard. Multiple tags are
724 presumably rare. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700726 nReturn = GetNext_FullItem(me, &Item);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 if(nReturn) {
728 // Bail out of the whole item fetch on any sort of error here
729 goto Done;
730 }
731
732 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
733 break;
734 }
735
736 uTagToProcess = Item.uTag;
737 } while (1);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700738
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739
740 /*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700741 CBOR allows multiple tags on a data item. It also defines
742 a number of standard tag values, most of which are
743 less than 64. This code can deal with multiple tag
744 values that are less than 64 and the last tag of multiple
745 if the value is more than 64. Or said another way
746 if there is one tag with a value >64 this code works.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700747
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700748 The assumption is that multiple tag values > 64 are rare.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700750 At this point in this code. uTagFlags has all the flags
751 < 64 and uTagToProcess has the last tag.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700752
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700753 Does this deal with multiple tags on an item we process?
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700754 */
755
756 Item.uTagBits = uTagFlags;
757 Item.uTag = uTagToProcess;
758
759 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
760 case 0:
761 // No tags we know about. Pass them up
762 *pDecodedItem = Item;
763 break;
764
765 case QCBOR_TAGFLAG_DATE_STRING:
766 nReturn = DecodeDateString(Item, pDecodedItem);
767 break;
768
769 case QCBOR_TAGFLAG_DATE_EPOCH:
770 nReturn = DecodeDateEpoch(Item, pDecodedItem);
771 break;
772
773 case QCBOR_TAGFLAG_POS_BIGNUM:
774 case QCBOR_TAGFLAG_NEG_BIGNUM:
775 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
776 break;
777
778 default:
779 // Encountering some mixed up CBOR like something that
780 // is tagged as both a string and integer date.
781 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782 }
783
784Done:
785 return nReturn;
786}
787
788
789/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700790 This layer takes care of map entries. It combines the label and data items into one item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 int nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 if(nReturn)
796 goto Done;
797
798 // If in a map and the right decoding mode, get the label
799 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
800 // In a map and caller wants maps decoded, not treated as arrays
801
802 // Get the next item which will be the real data; Item will be the label
803 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700804 nReturn = GetNext_TaggedItem(me, pDecodedItem); // TODO: test indefinite length string labels
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 if(nReturn)
806 goto Done;
807
808 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
809 // strings are always good labels
810 pDecodedItem->label.string = LabelItem.val.string;
811 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
812 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
813 // It's not a string and we only want strings, probably for easy translation to JSON
814 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
815 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700816 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 pDecodedItem->label.int64 = LabelItem.val.int64;
818 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
819 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
820 pDecodedItem->label.uint64 = LabelItem.val.uint64;
821 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
822 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
823 pDecodedItem->label.string = LabelItem.val.string;
824 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
825 } else {
826 // label is not an int or a string. It is an arrray
827 // or a float or such and this implementation doesn't handle that.
828 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
829 goto Done;
830 }
831 }
832
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833Done:
834 return nReturn;
835}
836
837
838/*
839 Public function, see header qcbor.h file
840 */
841/*
842 Decoding items is done in layers:
843 - This top layer takes care of tracking for decsending into and
844 ascending out of maps and arrays GetNext()
845 - The next layer takes care of map entries that are made up
846 of a label and a data item. They are returned as one. GetNextMap() GetNext_MapEntry()
847 - The next layer takes care of tagging and tagged types GetNext_TaggedItem()
848 - The next layer takes care of indefinite length strings GetFullItem() GetNext_FullItem()
849 - The next layer does the main decoding of the non-compound GetAnItem() GetNext_Item()
850 items, all the different types of them
851
852 */
853int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
854{
855 int nReturn;
856
857 if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
858 nReturn = QCBOR_ERR_HIT_END;
859 goto Done;
860 }
861
862 nReturn = GetNext_MapEntry(me, pDecodedItem);
863 if(nReturn) {
864 goto Done;
865 }
866
867 // Handle any breaks that are closing out arrays or maps
868 while(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
869 if(!DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
870 nReturn = QCBOR_ERR_BAD_BREAK;
871 goto Done;
872 }
873
874 // Close out and ascend
875 DecodeNesting_Ascend(&(me->nesting));
876
877 nReturn = GetNext_MapEntry(me, pDecodedItem);
878 if(nReturn) {
879 goto Done;
880 }
881 }
882
883 // Now have the next item that is not a break. The one that is going to be returned
884
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700885 // Record the nesting level for this data item
886 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
887
888 // If the new item is a non-empty array or map, the nesting level descends
889 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount) {
890 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount);
891 } else {
892 // Track number of items in maps and arrays and ascend nesting if all are consumed
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 // Note that an empty array or map is like an integer or string in effect here
894 // No counting is done for indefinite length arrays
895 if(!DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700896 DecodeNesting_Decrement(&(me->nesting));
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700897 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898 }
899
900Done:
901 return nReturn;
902}
903
904
905/*
906 Public function, see header qcbor.h file
907 */
908int QCBORDecode_Finish(QCBORDecodeContext *me)
909{
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910 int nReturn = QCBOR_SUCCESS;
911
912 // Consume any breaks ending indefinite length arrays or maps here
913 // Definite length arrays and maps get closed off above when they
914 // the last item in them is consumed; they are not handled here.
915 while(DecodeNesting_GetLevel(&(me->nesting))) {
916 QCBORItem Item;
917 GetNext_Item(&(me->InBuf), &Item, false);
918 if(Item.uDataType != QCBOR_TYPE_BREAK) {
919 nReturn = QCBOR_ERR_EXTRA_BYTES;
920 break;
921 }
922 DecodeNesting_Ascend(&(me->nesting));
923 }
924
925 // Call the desctructor for the string allocator if there is one
926 if(me->pStringAllocator) {
927 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
928 if(pAllocator->fDestructor) {
929 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
930 }
931 }
932
933 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
934 nReturn = QCBOR_ERR_EXTRA_BYTES;
935 }
936
937 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700938}
939
940
941
Laurence Lundblade7023b952018-10-02 01:54:24 -0700942/*
943
944 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
945
946 There is a tag map.
947
948 TODO: how does tinyCBOR do it?
949
950
951
952
953
954 */
955
956
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700957/*
958
959Decoder errors handled in this file
960
961 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700963 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
964
965 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
966
967 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
968
969 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
970
971 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
972
973 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
974
975 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
976
977 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
978
979 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
980
981 */
982
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983
984
985typedef struct {
986 QCBORStringAllocator StringAllocator;
987 uint8_t *pStart;
988 uint8_t *pEnd;
989 uint8_t *pFree;
990} MemPool;
991
992
993/*
994 Code Reviewers: THIS FUNCTION DOES POINTER MATH
995 */
996static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
997{
998 MemPool *me = (MemPool *)ctx;
999 void *pReturn = NULL;
1000
1001 if(pMem) {
1002 // Realloc case
1003 // TODO: review this pointer math
1004 if((uint8_t *)pMem + uNewSize <= me->pEnd && (uint8_t *)pMem > me->pStart) {
1005 me->pFree = pMem + uNewSize;
1006 pReturn = pMem;
1007 }
1008 } else {
1009 // New chunk case
1010 if(me->pFree + uNewSize <= me->pEnd) {
1011 pReturn = me->pFree;
1012 me->pFree += uNewSize;
1013 }
1014 }
1015
1016 return (UsefulBuf){pReturn, uNewSize};
1017}
1018
1019
1020static void MemPool_Free(void *ctx, void *pOldMem)
1021{
1022 MemPool *me = (MemPool *)ctx;
1023 me->pFree = pOldMem;
1024}
1025
1026
1027void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
1028{
1029 if(Pool.len < sizeof(MemPool)+1) {
1030 return; // Failure will happen when first string needs to be allocated
1031 }
1032
1033 MemPool *pMP = (MemPool *)Pool.ptr;
1034
1035 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1036 pMP->StringAllocator.fFree = MemPool_Free;
1037 pMP->StringAllocator.fDestructor = NULL;
1038
1039 pMP->pStart = Pool.ptr + sizeof(MemPool);
1040 pMP->pFree = pMP->pStart;
1041 pMP->pEnd = Pool.ptr + Pool.len;
1042 pMP->StringAllocator.pAllocaterContext = pMP;
1043
1044 me->pStringAllocator = pMP;
1045 me->bStringAllocateAll = bAllStrings;
1046}
1047
1048
1049