blob: ee43e65914ecf68754996988b1d7c48949018763 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018, Laurence Lundblade.
4 All rights reserved.
Laurence Lundblade624405d2018-09-18 20:10:47 -07005
Laurence Lundbladed92a6162018-11-01 11:38:35 +07006 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
8 met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade624405d2018-09-18 20:10:47 -070019
Laurence Lundbladed92a6162018-11-01 11:38:35 +070020 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundblade624405d2018-09-18 20:10:47 -070031 ==============================================================================*/
32
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070033/*===================================================================================
34 FILE: qcbor_decode.c
35
36 DESCRIPTION: This file contains the implementation of QCBOR.
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- ---------------------------------------------------
45 02/04/17 llundbla Work on CPUs that don's require pointer alignment
46 by making use of changes in UsefulBuf
47 03/01/17 llundbla More data types; decoding improvements and fixes
48 11/13/16 llundbla Integrate most TZ changes back into github version.
49 09/30/16 gkanike Porting to TZ.
50 03/15/16 llundbla Initial Version.
51
52 =====================================================================================*/
53
54#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070055#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070057
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053058/*
59 This casts away the const-ness of a pointer, usually so it can be
60 freed or realloced.
61 */
62#define UNCONST_POINTER(ptr) ((void *)(ptr))
63
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070064
65/*
Laurence Lundblade3a760b02018-10-08 13:46:03 +080066 Collection of functions to track the map/array nesting for decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070067 */
68
69inline static int IsMapOrArray(uint8_t uDataType)
70{
71 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
72}
73
74inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
75{
76 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
77}
78
Laurence Lundblade041ffa52018-10-07 11:43:51 +070079inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -070080{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070081 return pNesting->pCurrent->uCount == UINT16_MAX;
82}
83
Laurence Lundblade3a760b02018-10-08 13:46:03 +080084inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
85{
86 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
87}
88
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070089inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
90{
Laurence Lundblade0f99d692018-09-26 14:39:28 -070091 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070092 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -070093 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094
95 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
96}
97
Laurence Lundblade3a760b02018-10-08 13:46:03 +080098// Process a break. This will either ascend the nesting or error out
99inline static int DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700100{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800101 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800103 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104 }
105
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800106 // breaks can only occur when the map/array is indefinite length
107 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
108 return QCBOR_ERR_BAD_BREAK;
109 }
110
111 // if all OK, the break reduces the level of nesting
112 pNesting->pCurrent--;
113
114 return QCBOR_SUCCESS;
115}
116
117// Called on every single item except breaks including the opening of a map/array
118inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
119{
120 if(!DecodeNesting_IsNested(pNesting)) {
121 // at top level where there is no tracking
122 return;
123 }
124
125 if(DecodeNesting_IsIndefiniteLength(pNesting)) {
126 // There is no count for indefinite length arrays/maps
127 return;
128 }
129
130 // Decrement the count of items in this array/map
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700131 pNesting->pCurrent->uCount--;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700132
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800133 // Pop up nesting levels if the counts at the levels are zero
134 while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135 pNesting->pCurrent--;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800136 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
137 pNesting->pCurrent->uCount--;
138 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700139 }
140}
141
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800142// Called on every map/array
143inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144{
145 int nReturn = QCBOR_SUCCESS;
146
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800147 if(pItem->val.uCount == 0) {
148 // Nothing to do for empty definite lenth arrays. They are just are
149 // effectively the same as an item that is not a map or array
150 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530151 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800152 }
153
154 // Error out if arrays is too long to handle
155 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
157 goto Done;
158 }
159
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800160 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700161 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
162 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
163 goto Done;
164 }
165
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800166 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700167 pNesting->pCurrent++;
168
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800169 // Record a few details for this nesting level
170 pNesting->pCurrent->uMajorType = pItem->uDataType;
171 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700172
173Done:
174 return nReturn;;
175}
176
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700177inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
178{
179 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
180}
181
182
183
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700184/*
185 This list of built-in tags. Only add tags here that are
186 clearly established and useful. Once a tag is added here
187 it can't be taken out as that would break backwards compatibility.
188 There are only 48 slots available forever.
189 */
190static const uint16_t spBuiltInTagMap[] = {
191 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR
192 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
193 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
194 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
195 CBOR_TAG_FRACTION,
196 CBOR_TAG_BIGFLOAT,
197 CBOR_TAG_COSE_ENCRYPTO,
198 CBOR_TAG_COSE_MAC0,
199 CBOR_TAG_COSE_SIGN1,
200 CBOR_TAG_ENC_AS_B64URL,
201 CBOR_TAG_ENC_AS_B64,
202 CBOR_TAG_ENC_AS_B16,
203 CBOR_TAG_CBOR,
204 CBOR_TAG_URI,
205 CBOR_TAG_B64URL,
206 CBOR_TAG_B64,
207 CBOR_TAG_REGEX,
208 CBOR_TAG_MIME,
209 CBOR_TAG_BIN_UUID,
210 CBOR_TAG_CWT,
211 CBOR_TAG_ENCRYPT,
212 CBOR_TAG_MAC,
213 CBOR_TAG_SIGN,
214 CBOR_TAG_GEO_COORD,
215 CBOR_TAG_CBOR_MAGIC
216};
217
218// This is used in a bit of cleverness in GetNext_TaggedItem() to
219// keep code size down and switch for the internal processing of
220// these types. This will break if the first four items in
221// spBuiltInTagMap don't have values 0,1,2,3. That is the
222// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3.
223#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
224#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
225#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
226#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
227
228#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
229 QCBOR_TAGFLAG_DATE_EPOCH |\
230 QCBOR_TAGFLAG_POS_BIGNUM |\
231 QCBOR_TAGFLAG_NEG_BIGNUM)
232
233#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
234#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
235#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
236
237static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
238{
239 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
240 // This is a cross-check to make sure the above array doesn't
241 // accidentally get made too big.
242 // In normal conditions the above test should optimize out
243 // as all the values are known at compile time.
244 return -1;
245 }
246
247 if(uTag > UINT16_MAX) {
248 // This tag map works only on 16-bit tags
249 return -1;
250 }
251
252 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
253 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
254 return nTagBitIndex;
255 }
256 }
257 return -1; // Indicates no match
258}
259
260static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
261{
262 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
263 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
264 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
265 }
266 }
267
268 return -1; // Indicates no match
269}
270
271/*
272 Find the tag bit index for a given tag value, or error out
273
274 This and the above functions could probably be optimized and made
275 clearer and neater.
276 */
277static int TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex)
278{
279 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
280 if(nTagBitIndex >= 0) {
281 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
282 *puTagBitIndex = (uint8_t)nTagBitIndex;
283 return QCBOR_SUCCESS;
284 }
285
286 if(pCallerConfiguredTagMap) {
287 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
288 return QCBOR_ERR_TOO_MANY_TAGS;
289 }
290 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
291 if(nTagBitIndex >= 0) {
292 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
293
294 *puTagBitIndex = (uint8_t)nTagBitIndex;
295 return QCBOR_SUCCESS;
296 }
297 }
298
299 return QCBOR_ERR_BAD_OPT_TAG;
300}
301
302
303
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700304
305/*
306 Public function, see header file
307 */
308void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
309{
310 memset(me, 0, sizeof(QCBORDecodeContext));
311 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
312 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
313 // if the default normal mode of 0 was set.
314 me->uDecodeMode = nDecodeMode;
315 DecodeNesting_Init(&(me->nesting));
316}
317
318
319/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700320 Public function, see header file
321 */
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530322void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700323{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700324 pCtx->pStringAllocator = (void *)pAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530325 pCtx->bStringAllocateAll = bAllocAll;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700326}
327
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700328void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
329{
330 me->pCallerConfiguredTagList = pTagList;
331}
332
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700333
334/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700335 This decodes the fundamental part of a CBOR data item, the type and number
336
337 This is the Counterpart to InsertEncodedTypeAndNumber().
338
339 This does the network->host byte order conversion. The conversion here
340 also results in the conversion for floats in addition to that for
341 lengths, tags and integer values.
342
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700343 This returns:
344 pnMajorType -- the major type for the item
345 puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
346 puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
347
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700348 */
349inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
350{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700351 // Stack usage: int/ptr 5 -- 40
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700352 int nReturn;
353
354 // Get the initial byte that every CBOR data item has
355 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
356
357 // Break down the initial byte
358 const uint8_t uTmpMajorType = InitialByte >> 5;
359 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
360
361 // 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 +0700362 // Also convert from network byte order.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700363 uint64_t uTmpValue;
364 switch(uAdditionalInfo) {
365
366 case LEN_IS_ONE_BYTE:
367 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
368 break;
369
370 case LEN_IS_TWO_BYTES:
371 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
372 break;
373
374 case LEN_IS_FOUR_BYTES:
375 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
376 break;
377
378 case LEN_IS_EIGHT_BYTES:
379 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
380 break;
381
382 case ADDINFO_RESERVED1: // reserved by CBOR spec
383 case ADDINFO_RESERVED2: // reserved by CBOR spec
384 case ADDINFO_RESERVED3: // reserved by CBOR spec
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700385 nReturn = QCBOR_ERR_UNSUPPORTED;
386 goto Done;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700387
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700388 default:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700389 // This is when the "number" is in the additional info
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700390 uTmpValue = uAdditionalInfo;
391 break;
392 }
393
394 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
395 // There is no harm in this. This following check takes care of catching all of
396 // these errors.
397
398 if(UsefulInputBuf_GetError(pUInBuf)) {
399 nReturn = QCBOR_ERR_HIT_END;
400 goto Done;
401 }
402
403 // All successful if we got here.
404 nReturn = QCBOR_SUCCESS;
405 *pnMajorType = uTmpMajorType;
406 *puNumber = uTmpValue;
407 *puAdditionalInfo = uAdditionalInfo;
408
409Done:
410 return nReturn;
411}
412
413
414/*
415 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
416 use it these days and the test vectors in the RFC are so. All integers in the CBOR
417 structure are positive and the major type indicates positive or negative.
418 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
419 and negative integers down to 2^x. Note that negative numbers can be one
420 more away from zero than positive.
421 Stdint, as far as I can tell, uses two's compliment to represent
422 negative integers.
423
424 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
425 used here in any way including in the interface
426 */
427inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
428{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700429 // Stack usage: int/ptr 1 -- 8
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700430 int nReturn = QCBOR_SUCCESS;
431
432 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
433 if (uNumber <= INT64_MAX) {
434 pDecodedItem->val.int64 = (int64_t)uNumber;
435 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
436
437 } else {
438 pDecodedItem->val.uint64 = uNumber;
439 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
440
441 }
442 } else {
443 if(uNumber <= INT64_MAX) {
444 pDecodedItem->val.int64 = -uNumber-1;
445 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
446
447 } else {
448 // C can't represent a negative integer in this range
449 // so it is an error. todo -- test this condition
450 nReturn = QCBOR_ERR_INT_OVERFLOW;
451 }
452 }
453
454 return nReturn;
455}
456
457// Make sure #define value line up as DecodeSimple counts on this.
458#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
459#error QCBOR_TYPE_FALSE macro value wrong
460#endif
461
462#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
463#error QCBOR_TYPE_TRUE macro value wrong
464#endif
465
466#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
467#error QCBOR_TYPE_NULL macro value wrong
468#endif
469
470#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
471#error QCBOR_TYPE_UNDEF macro value wrong
472#endif
473
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700474#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
475#error QCBOR_TYPE_BREAK macro value wrong
476#endif
477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700478#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
479#error QCBOR_TYPE_DOUBLE macro value wrong
480#endif
481
482#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
483#error QCBOR_TYPE_FLOAT macro value wrong
484#endif
485
486/*
487 Decode true, false, floats, break...
488 */
489
490inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
491{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700492 // Stack usage: 0
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700493 int nReturn = QCBOR_SUCCESS;
494
495 // uAdditionalInfo is 5 bits from the initial byte
496 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
497 pDecodedItem->uDataType = uAdditionalInfo;
498
499 switch(uAdditionalInfo) {
500 case ADDINFO_RESERVED1: // 28
501 case ADDINFO_RESERVED2: // 29
502 case ADDINFO_RESERVED3: // 30
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700503 nReturn = QCBOR_ERR_UNSUPPORTED;
504 break;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700505
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700506 case HALF_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700507 pDecodedItem->val.fnum = IEEE754_HalfToFloat((uint16_t)uNumber);
508 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
509 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700510 case SINGLE_PREC_FLOAT:
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700511 pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
512 break;
513 case DOUBLE_PREC_FLOAT:
514 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
515 break;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700516
517 case CBOR_SIMPLEV_FALSE: // 20
518 case CBOR_SIMPLEV_TRUE: // 21
519 case CBOR_SIMPLEV_NULL: // 22
520 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700521 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700522 break; // nothing to do
523
524 case CBOR_SIMPLEV_ONEBYTE: // 24
525 if(uNumber <= CBOR_SIMPLE_BREAK) {
526 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
527 nReturn = QCBOR_ERR_INVALID_CBOR;
528 goto Done;
529 }
530 // fall through intentionally
531
532 default: // 0-19
533 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
534 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
535 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
536 pDecodedItem->val.uSimple = (uint8_t)uNumber;
537 break;
538 }
539
540Done:
541 return nReturn;
542}
543
544
545
546/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530547 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700548 */
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530549inline static int DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700550{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700551 // Stack usage: UsefulBuf 2, int/ptr 1 40
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530552 int nReturn = QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700553
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530554 UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
555 if(UsefulBuf_IsNULLC(Bytes)) {
556 // Failed to get the bytes for this string item
557 nReturn = QCBOR_ERR_HIT_END;
558 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700559 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530560
561 if(pAlloc) {
562 // We are asked to use string allocator to make a copy
563 UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen);
564 if(UsefulBuf_IsNULL(NewMem)) {
565 nReturn = QCBOR_ERR_STRING_ALLOC;
566 goto Done;
567 }
568 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
569 } else {
570 // Normal case with no string allocator
571 pDecodedItem->val.string = Bytes;
572 }
573 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700574
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530575Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700576 return nReturn;
577}
578
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579
580/*
581 Mostly just assign the right data type for the date string.
582 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700583inline static int DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700585 // Stack Use: UsefulBuf 1 16
586 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700587 return QCBOR_ERR_BAD_OPT_TAG;
588 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700589
590 UsefulBufC Temp = pDecodedItem->val.string;
591 pDecodedItem->val.dateString = Temp;
592 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700593 return QCBOR_SUCCESS;
594}
595
596
597/*
598 Mostly just assign the right data type for the bignum.
599 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700600inline static int DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700601{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700602 // Stack Use: UsefulBuf 1 -- 16
603 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700604 return QCBOR_ERR_BAD_OPT_TAG;
605 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700606 UsefulBufC Temp = pDecodedItem->val.string;
607 pDecodedItem->val.bigNum = Temp;
608 pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM; // TODO: check this
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700609 return QCBOR_SUCCESS;
610}
611
612
613/*
614 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
615 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700616static int DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700618 // Stack usage: 1
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619 int nReturn = QCBOR_SUCCESS;
620
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700622 double d = pDecodedItem->val.dfnum; // Might not use this, but keeps code flow neater below
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700624 switch (pDecodedItem->uDataType) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625
626 case QCBOR_TYPE_INT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700627 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 break;
629
630 case QCBOR_TYPE_UINT64:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700631 if(pDecodedItem->val.uint64 > INT64_MAX) {
632 nReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700633 goto Done;
634 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700635 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700636 break;
637
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800638 case QCBOR_TYPE_FLOAT:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700639 d = pDecodedItem->val.fnum;
640 // Fall through
641
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800642 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700643 if(d > INT64_MAX) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800644 nReturn = QCBOR_ERR_DATE_OVERFLOW;
645 goto Done;
646 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700647 pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
648 pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800649 break;
650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 default:
652 nReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700653 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700655 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656
657Done:
658 return nReturn;
659}
660
661
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700662
663
664// Make sure the constants align as this is assumed by the GetAnItem() implementation
665#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
666#error QCBOR_TYPE_ARRAY value not lined up with major type
667#endif
668#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
669#error QCBOR_TYPE_MAP value not lined up with major type
670#endif
671
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672/*
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700673 This gets a single data item and decodes it including preceding optional tagging. This does not
674 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
675 maps are handled at the next level up in GetNext().
676
677 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
678 a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679 */
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530680static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700681{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700682 // Stack usage: int/ptr 3 -- 24
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700683 int nReturn;
684
685 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
686 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
687 int uMajorType;
688 uint64_t uNumber;
689 uint8_t uAdditionalInfo;
690
691 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
692
693 // Error out here if we got into trouble on the type and number.
694 // The code after this will not work if the type and number is not good.
695 if(nReturn)
696 goto Done;
697
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530698 memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700699
700 // At this point the major type and the value are valid. We've got the type and the number that
701 // starts every CBOR data item.
702 switch (uMajorType) {
703 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
704 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
705 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
706 break;
707
708 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
709 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
710 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
711 pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530712 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700713 } else {
714 nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
715 }
716 break;
717
718 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
719 case CBOR_MAJOR_TYPE_MAP: // Major type 5
720 // Record the number of items in the array or map
721 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
722 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
723 goto Done;
724 }
725 if(uAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530726 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700727 } else {
728 pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
729 }
730 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
731 break;
732
733 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700734 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700735 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
736 break;
737
738 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
739 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
740 break;
741
742 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
743 nReturn = QCBOR_ERR_UNSUPPORTED;
744 break;
745 }
746
747Done:
748 return nReturn;
749}
750
751
752
753/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800754 This layer deals with indefinite length strings. It pulls all the
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700755 individual chunk items together into one QCBORItem using the
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530756 string allocator.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530757
758 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700759 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700760static inline int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700761{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700762 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700763 int nReturn;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +0530764 QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530765 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700766
767 nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
768 if(nReturn) {
769 goto Done;
770 }
771
772 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530773 // code in this function from here down can be eliminated. Run tests, except
774 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700775
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800776 // Only do indefinite length processing on strings
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
778 goto Done; // no need to do any work here on non-string types
779 }
780
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800781 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530782 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800783 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700784 }
785
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530786 // Can't do indefinite length strings without a string allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700787 if(pAlloc == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
789 goto Done;
790 }
791
792 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800793 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 const uint8_t uStringType = pDecodedItem->uDataType;
795
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700796 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700797 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700798 // Get item for next chunk
799 QCBORItem StringChunkItem;
800 // NULL passed to never string alloc chunk of indefinite length strings
801 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700802 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700803 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700804 }
805
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530806 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700807 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800808 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700809 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530810 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700811 break;
812 }
813
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700814 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530815 // Also catches error of other non-string types that don't belong.
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700816 if(StringChunkItem.uDataType != uStringType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700817 nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
818 break;
819 }
820
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530821 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530822 UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
823 UNCONST_POINTER(FullString.ptr),
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700824 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700825 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530826 // Allocation of memory for the string failed
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700827 nReturn = QCBOR_ERR_STRING_ALLOC;
828 break;
829 }
830
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700831 // Copy new string chunk at the end of string so far.
832 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700833 }
834
835Done:
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530836 if(pAlloc && nReturn && !UsefulBuf_IsNULLC(FullString)) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700837 // Getting item failed, clean up the allocated memory
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530838 (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700839 }
840
841 return nReturn;
842}
843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844
845/*
846 Returns an error if there was something wrong with the optional item or it couldn't
847 be handled.
848 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700849static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700850{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700851 // Stack usage: int/ptr: 3 -- 24
852 int nReturn;
853 uint64_t uTagBits = 0;
854 if(pTags) {
855 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700856 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700857
858 for(;;) {
859 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700860 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700861 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700862 }
863
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700864 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
865 // Successful exit from loop; maybe got some tags, maybe not
866 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 break;
868 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700869
870 uint8_t uTagBitIndex;
871 // Tag was mapped, tag was not mapped, error with tag list
872 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
873
874 case QCBOR_SUCCESS:
875 // Successfully mapped the tag
876 uTagBits |= 0x01ULL << uTagBitIndex;
877 break;
878
879 case QCBOR_ERR_BAD_OPT_TAG:
880 // Tag is not recognized. Do nothing
881 break;
882
883 default:
884 // Error Condition
885 goto Done;
886 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700887
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700888 if(pTags) {
889 // Caller wants all tags recorded in the provided buffer
890 if(pTags->uNumUsed >= pTags->uNumAllocated) {
891 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
892 goto Done;
893 }
894 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
895 pTags->uNumUsed++;
896 }
897 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700898
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700899 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900 case 0:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700901 // No tags at all or none we know about. Nothing to do.
902 // This is part of the pass-through path of this function
903 // that will mostly be taken when decoding any item.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700904 break;
905
906 case QCBOR_TAGFLAG_DATE_STRING:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700907 nReturn = DecodeDateString(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700908 break;
909
910 case QCBOR_TAGFLAG_DATE_EPOCH:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700911 nReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700912 break;
913
914 case QCBOR_TAGFLAG_POS_BIGNUM:
915 case QCBOR_TAGFLAG_NEG_BIGNUM:
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700916 nReturn = DecodeBigNum(pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700917 break;
918
919 default:
920 // Encountering some mixed up CBOR like something that
921 // is tagged as both a string and integer date.
922 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700923 }
924
925Done:
926 return nReturn;
927}
928
929
930/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800931 This layer takes care of map entries. It combines the label and data items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700932 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700933static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700935 // Stack use: int/ptr 1, QCBORItem -- 56
936 int nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700937 if(nReturn)
938 goto Done;
939
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800940 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700941 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +0800942 goto Done;
943 }
944
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700945 // If in a map and the right decoding mode, get the label
946 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
947 // In a map and caller wants maps decoded, not treated as arrays
948
949 // Get the next item which will be the real data; Item will be the label
950 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700951 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700952 if(nReturn)
953 goto Done;
954
Laurence Lundbladefab1b522018-10-19 13:40:52 +0530955 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
956
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700957 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
958 // strings are always good labels
959 pDecodedItem->label.string = LabelItem.val.string;
960 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
961 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
962 // It's not a string and we only want strings, probably for easy translation to JSON
963 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
964 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700966 pDecodedItem->label.int64 = LabelItem.val.int64;
967 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
968 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
969 pDecodedItem->label.uint64 = LabelItem.val.uint64;
970 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
971 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
972 pDecodedItem->label.string = LabelItem.val.string;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530973 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700974 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
975 } else {
976 // label is not an int or a string. It is an arrray
977 // or a float or such and this implementation doesn't handle that.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700978 // Also, tags on labels are ignored.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700979 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
980 goto Done;
981 }
982 }
983
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984Done:
985 return nReturn;
986}
987
988
989/*
990 Public function, see header qcbor.h file
991 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700992int QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700994 // Stack ptr/int: 2, QCBORItem : 64
995
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530996 // The public entry point for fetching and parsing the next QCBORItem.
997 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 int nReturn;
999
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001000 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001001 if(nReturn) {
1002 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301004
1005 // Break ending arrays/maps are always processed at the end of this function.
1006 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301007 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301008 nReturn = QCBOR_ERR_BAD_BREAK;
1009 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301010 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001011
Laurence Lundblade6de37062018-10-15 12:22:42 +05301012 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301013 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301014 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
1015
1016 // Process the item just received for descent or decrement, and
1017 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001018 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001019 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001020 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001021 // Maps and arrays do count in as items in the map/array that encloses
1022 // them so a decrement needs to be done for them too, but that is done
1023 // only when all the items in them have been processed, not when they
1024 // are opened.
1025 } else {
1026 // Decrement the count of items in the enclosing map/array
1027 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301028 // triggers a decrement in the map/array above that and
1029 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001030 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001031 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301032 if(nReturn) {
1033 goto Done;
1034 }
1035
1036 // For indefinite length maps/arrays, looking at any and
1037 // all breaks that might terminate them. The equivalent
1038 // for definite length maps/arrays happens in
1039 // DecodeNesting_DecrementCount().
1040 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1041 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1042 // Peek forward one item to see if it is a break.
1043 QCBORItem Peek;
1044 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1045 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1046 if(nReturn) {
1047 goto Done;
1048 }
1049 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1050 // It is not a break, rewind so it can be processed normally.
1051 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1052 break;
1053 }
1054 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301055 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301056 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1057 if(nReturn) {
1058 // break occured outside of an indefinite length array/map
1059 goto Done;
1060 }
1061 }
1062 }
1063
1064 // Tell the caller what level is next. This tells them what maps/arrays
1065 // were closed out and makes it possible for them to reconstruct
1066 // the tree with just the information returned by GetNext
1067 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001068
1069Done:
1070 return nReturn;
1071}
1072
1073
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001074int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1075{
1076 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1077}
1078
1079
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001080/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301081 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301082 next one down. If a layer has no work to do for a particular item
1083 it returns quickly.
1084
1085 - QCBORDecode_GetNext -- The top layer manages the beginnings and
1086 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301087 out of maps/arrays. It processes all breaks that terminate
1088 maps and arrays.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301089
1090 - GetNext_MapEntry -- This handles the combining of two
1091 items, the label and the data, that make up a map entry.
1092 It only does work on maps. It combines the label and data
1093 items into one labeled item.
1094
1095 - GetNext_TaggedItem -- This handles the type 6 tagged items.
1096 It accumulates all the tags and combines them with the following
1097 non-tagged item. If the tagged item is something that is understood
1098 like a date, the decoding of that item is invoked.
1099
1100 - GetNext_FullItem -- This assembles the sub items that make up
1101 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301102 string allocater to create contiguous space for the item. It
1103 processes all breaks that are part of indefinite length strings.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301104
1105 - GetNext_Item -- This gets and decodes the most atomic
1106 item in CBOR, the thing with an initial byte containing
1107 the major type.
1108
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001109 Roughly this takes 300 bytes of stack for vars. Need to
1110 evaluate this more carefully and correctly.
1111
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301112 */
1113
1114
1115/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001116 Public function, see header qcbor.h file
1117 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001118int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
1119{
1120 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
1121
1122 uint8_t uTagBitIndex;
1123 // Do not care about errors in pCallerConfiguredTagMap here. They are
1124 // caught during GetNext() before this is called.
1125 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1126 return 0;
1127 }
1128
1129 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1130 return (uTagBit & pItem->uTagBits) != 0;
1131}
1132
1133
1134/*
1135 Public function, see header qcbor.h file
1136 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001137int QCBORDecode_Finish(QCBORDecodeContext *me)
1138{
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001139 int nReturn = QCBOR_SUCCESS;
1140
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001141 // Error out if all the maps/arrays are not closed out
1142 if(DecodeNesting_IsNested(&(me->nesting))) {
1143 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1144 goto Done;
1145 }
1146
1147 // Error out if not all the bytes are consumed
1148 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1149 nReturn = QCBOR_ERR_EXTRA_BYTES;
1150 }
1151
1152Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301153 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001154 // Always called, even if there are errors; always have to clean up
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155 if(me->pStringAllocator) {
1156 QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
1157 if(pAllocator->fDestructor) {
1158 (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
1159 }
1160 }
1161
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001162 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001163}
1164
1165
1166
Laurence Lundblade7023b952018-10-02 01:54:24 -07001167/*
1168
1169 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
1170
1171 There is a tag map.
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301172
Laurence Lundblade7023b952018-10-02 01:54:24 -07001173
1174 */
1175
1176
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001177/*
1178
1179Decoder errors handled in this file
1180
1181 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001182
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001183 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
1184
1185 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
1186
1187 - 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 +05301188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001189 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
1190
1191 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
1192
1193 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
1194
1195 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
1196
1197 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
1198
1199 */
1200
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001201
1202
1203typedef struct {
1204 QCBORStringAllocator StringAllocator;
1205 uint8_t *pStart;
1206 uint8_t *pEnd;
1207 uint8_t *pFree;
1208} MemPool;
1209
1210
1211/*
1212 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1213 */
1214static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
1215{
1216 MemPool *me = (MemPool *)ctx;
1217 void *pReturn = NULL;
1218
1219 if(pMem) {
1220 // Realloc case
1221 // TODO: review this pointer math
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001222 if((uint8_t *)pMem + uNewSize <= me->pEnd) {//} && (uint8_t *)pMem > me->pStart) {
1223 me->pFree = (uint8_t *)pMem + uNewSize;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001224 pReturn = pMem;
1225 }
1226 } else {
1227 // New chunk case
1228 if(me->pFree + uNewSize <= me->pEnd) {
1229 pReturn = me->pFree;
1230 me->pFree += uNewSize;
1231 }
1232 }
1233
1234 return (UsefulBuf){pReturn, uNewSize};
1235}
1236
1237
1238static void MemPool_Free(void *ctx, void *pOldMem)
1239{
1240 MemPool *me = (MemPool *)ctx;
1241 me->pFree = pOldMem;
1242}
1243
1244
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301245int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001246{
1247 if(Pool.len < sizeof(MemPool)+1) {
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301248 return 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001249 }
1250
1251 MemPool *pMP = (MemPool *)Pool.ptr;
1252
1253 pMP->StringAllocator.fAllocate = MemPool_Alloc;
1254 pMP->StringAllocator.fFree = MemPool_Free;
1255 pMP->StringAllocator.fDestructor = NULL;
1256
Laurence Lundblade570fab52018-10-13 18:28:27 +08001257 pMP->pStart = (uint8_t *)Pool.ptr + sizeof(MemPool);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001258 pMP->pFree = pMP->pStart;
Laurence Lundblade570fab52018-10-13 18:28:27 +08001259 pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001260 pMP->StringAllocator.pAllocaterContext = pMP;
1261
1262 me->pStringAllocator = pMP;
1263 me->bStringAllocateAll = bAllStrings;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301264
1265 return 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001266}
1267
1268
1269