more work on indefinite lengths and mem pool. All tests passing but more are needed and there is still an issue with indefinite length arrays and strings
diff --git a/inc/qcbor.h b/inc/qcbor.h
index d8bf35f..679105c 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -481,7 +481,7 @@
QCBOR_MAX_ARRAY_NESTING (this is typically 10).
- Max items in an array or map when encoding / decoding is
QCBOR_MAX_ITEMS_IN_ARRAY (typicall 65,536).
- - Does not support encoding or decoding indefinite lengths.
+ - Does not support encoding indefinite lengths.
- Does not directly support some tagged types: decimal fractions, big floats
- Does not directly support labels in maps other than text strings and ints.
- Epoch dates limited to INT64_MAX (+/- 292 billion years)
@@ -542,7 +542,7 @@
#define QCBOR_ERR_TOO_MANY_CLOSES 4
/** During decoding, some CBOR construct was encountered that this decoder
- doesn't support. For example indefinite lengths. */
+ doesn't support. */
#define QCBOR_ERR_UNSUPPORTED 5
/** During decoding, hit the end of the given data to decode. For example,
@@ -688,7 +688,7 @@
UsefulBufC bigNum; /** The value for uDataType QCBOR_TYPE_BIGNUM */
uint8_t uSimple; /** The integer value for unknown simple types */
- } val; /** The union holding the item's value. Select union member based on uMajorType */
+ } val; /** The union holding the item's value. Select union member based on uDataType */
union {
UsefulBufC string; /** The label for uLabelType QCBOR_TYPE_BYTE_STRING and QCBOR_TYPE_TEXT_STRING */
@@ -1648,12 +1648,15 @@
@param[in] MemPool The pointer and length of the memory pool
@param[in] bAllStrings true means to put even definite length strings in the pool
+ @return 0 if the MemPool was at least minimum size, 1 if not.
+
Indefinite length strings (text and byte) cannot be decoded unless there is
either a memory pool set up or a string allocator configured.
The MemPool must be sized large enough. For a 64-bit CPU it must be sized
- at 64 bytes plus space to hold all the indefinite length strings. For a 32-bit CPU
- the size is 32 bytes plus space for the strings. There is no overhead per
+ at 72 bytes plus space to hold all the indefinite length strings. For a 32-bit CPU
+ the size is 36 bytes plus space for the strings. (This is space for 9 pointers;
+ it may vary from one CPU or OS to another). There is no overhead per
string. This includes indefinite length strings that are serve as labels
for map items.
@@ -1669,10 +1672,7 @@
*/
-void QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx, UsefulBuf MemPool, bool bAllStrings);
-
-
-int QCBORDecode_SetMemPool_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, int8_t nMode, UsefulBuf MemPool);
+int QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx, UsefulBuf MemPool, bool bAllStrings);
/**
@@ -1680,8 +1680,6 @@
*/
void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator);
-QCBORStringAllocator *QCBORDecode_GetAllocator(QCBORDecodeContext *pCtx);
-
/**
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 2ec7a68..a34afe1 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -648,11 +648,8 @@
static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
{
int nReturn;
- UsefulBufC FullString = NULLUsefulBufC;
- QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
+ QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
- // TODO: can this call to GetNext_Item go in the loop below so there is only
- // one call to it so it can inline?
nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
if(nReturn) {
goto Done;
@@ -681,6 +678,7 @@
// There is an indefinite length string to work on...
// Track which type of string it is
const uint8_t uStringType = pDecodedItem->uDataType;
+ UsefulBufC FullString = NULLUsefulBufC;
// Loop getting segments of indefinite string
for(;;) {
@@ -718,7 +716,7 @@
}
Done:
- if(nReturn && FullString.ptr) {
+ if(pAlloc && nReturn && FullString.ptr) {
// Getting item failed, clean up the allocated memory
(pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
}
@@ -878,7 +876,27 @@
/* Loops processing breaks until a non-break is encountered
- or an error is encountered
+ or an error is encountered.
+
+ Case 1) data ends correctly in a break
+
+ Case 2) data is short a break
+
+ Case 3) data is short other than a break
+
+ Case 4) extra break
+
+ Case 5) other extra stuff
+
+
+ Can stop when nesting is exhausted, possibly returning a break
+
+ Can stop when getting to a non-break or to end of data
+ return error on end of data or return no error on end of data
+
+ All getnexts either return an item or an error so far
+
+
*/
static int GetNext_GetNonBreak(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
{
@@ -921,6 +939,21 @@
// Record the nesting level for this data item before processing any of
// decrementing and decsending
pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
+#if 0
+ // Maybe peek at next item here.
+ {
+ // Only need to do this is current item is indefinite length
+ if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
+ size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
+ QCBORItem Peek;
+ GetNext_Item(&(me->InBuf), &Peek, NULL);
+ if(Peek.uDataType == 99) { // TODO:
+ // Mark current item as end of array / map
+ }
+ UsefulInputBuf_Seek(&(me->InBuf), uPeek);
+ }
+ }
+#endif
if(IsMapOrArray(pDecodedItem->uDataType)) {
// If the new item is array or map, the nesting level descends
@@ -1041,9 +1074,7 @@
- Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
- Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
-
- - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
-
+
- Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
- Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
@@ -1100,10 +1131,10 @@
}
-void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
+int QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
{
if(Pool.len < sizeof(MemPool)+1) {
- return; // Failure will happen when first string needs to be allocated
+ return 1;
}
MemPool *pMP = (MemPool *)Pool.ptr;
@@ -1119,6 +1150,8 @@
me->pStringAllocator = pMP;
me->bStringAllocateAll = bAllStrings;
+
+ return 0;
}
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index a2d53a9..05930f5 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1683,7 +1683,7 @@
static const uint8_t pIndefiniteArrayBad2[] = {0x9f, 0x9f, 0x02, 0xff}; // Not enough closing breaks
static const uint8_t pIndefiniteArrayBad3[] = {0x9f, 0x02, 0xff, 0xff}; // Too many closing breaks
static const uint8_t pIndefiniteArrayBad4[] = {0x81, 0x9f}; // Unclosed indeflen inside def len
-
+//static const uint8_t pIndefiniteArrayBad5[] = {0x9f, 0xc7, 0xff}; // confused tag
int indefinite_length_decode_test()
{
@@ -1796,7 +1796,6 @@
if(nResult != QCBOR_ERR_EXTRA_BYTES) {
return -2;
}
-
// --- next test -----
IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad4);
@@ -1809,7 +1808,7 @@
if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) {
return -1;
}
-
+
nResult = QCBORDecode_GetNext(&DC, &Item);
if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) {
return -1;
@@ -1820,6 +1819,33 @@
return -2;
}
+#if 0
+
+ // --- next test -----
+ IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad5);
+
+ QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
+
+ QCBORDecode_SetMemPool(&DC, MemPool, false);
+
+ nResult = QCBORDecode_GetNext(&DC, &Item);
+ if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) {
+ return -1;
+ }
+
+ nResult = QCBORDecode_GetNext(&DC, &Item);
+ if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) {
+ return -1;
+ }
+
+ nResult = QCBORDecode_Finish(&DC);
+ if(nResult != QCBOR_ERR_HIT_END) {
+ return -2;
+ }
+#endif
+
+
+
return 0;
}
@@ -1832,7 +1858,8 @@
0xff // ending break
};
-int indefinite_length_decode_string_test() {
+int indefinite_length_decode_string_test()
+{
UsefulBufC IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteLenString);
@@ -1843,7 +1870,9 @@
QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
- QCBORDecode_SetMemPool(&DC, MemPool, false);
+ if(QCBORDecode_SetMemPool(&DC, MemPool, false)) {
+ return -4;
+ }
QCBORDecode_GetNext(&DC, &Item);
@@ -1855,7 +1884,45 @@
if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
return -1;
}
-
+
+ // ------ Don't set a string allocator and see an error
+ QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
+
+ QCBORDecode_GetNext(&DC, &Item);
+ if(Item.uDataType != QCBOR_TYPE_ARRAY) {
+ return -1;
+ }
+
+ if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_NO_STRING_ALLOCATOR) {
+ return -1;
+ }
+
+ // ----- Mempool is way too small -----
+ UsefulBuf_MakeStackUB(MemPoolTooSmall, 20); // 20 is too small no matter what
+
+ QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
+ if(!QCBORDecode_SetMemPool(&DC, MemPoolTooSmall, false)) {
+ return -8;
+ }
+
+
+
+ // ----- Mempool is way too small -----
+ UsefulBuf_MakeStackUB(MemPoolSmall, 60); // TODO: this tests needs some big strings to be CPU indepedent
+
+ QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
+ if(QCBORDecode_SetMemPool(&DC, MemPoolSmall, false)) {
+ return -8;
+ }
+
+ QCBORDecode_GetNext(&DC, &Item);
+ if(Item.uDataType != QCBOR_TYPE_ARRAY) {
+ return -1;
+ }
+ if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_STRING_ALLOC) {
+ return -1;
+ }
+
return 0;
}