Merge from master
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4ec0628..1e233d2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,6 +17,10 @@
- os-image: ubuntu-latest
container: ubuntu:22.04
+ dis-xxx: '-DQCBOR_DISABLE_NON_INTEGER_LABELS'
+
+ - os-image: ubuntu-latest
+ container: ubuntu:22.04
dis-xxx: '-DQCBOR_DISABLE_TAGS'
- os-image: ubuntu-latest
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index d7ebc4c..34bdfc7 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -173,7 +173,7 @@
E776E094214AE09700E67947 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/UsefulBuf.h; sourceTree = "<group>"; tabWidth = 3; };
E776E096214AE0C700E67947 /* cmd_line_main.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = cmd_line_main.c; sourceTree = "<group>"; tabWidth = 3; };
E776E161214EE19C00E67947 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
- E7864765252CE63100A0C11B /* qcbor_err_to_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_err_to_str.c; path = src/qcbor_err_to_str.c; sourceTree = "<group>"; };
+ E7864765252CE63100A0C11B /* qcbor_err_to_str.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_err_to_str.c; path = src/qcbor_err_to_str.c; sourceTree = "<group>"; tabWidth = 3; };
E78C91DE240C90C100F4CECE /* qcbor_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_decode.h; path = inc/qcbor/qcbor_decode.h; sourceTree = "<group>"; tabWidth = 3; };
E78C91DF240C90C100F4CECE /* qcbor_common.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_common.h; path = inc/qcbor/qcbor_common.h; sourceTree = "<group>"; tabWidth = 3; };
E78C91E0240C90C100F4CECE /* qcbor_private.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_private.h; path = inc/qcbor/qcbor_private.h; sourceTree = "<group>"; tabWidth = 3; };
diff --git a/README.md b/README.md
index 2f2deef..9adfefe 100644
--- a/README.md
+++ b/README.md
@@ -458,6 +458,7 @@
| QCBOR_DISABLE_PREFERRED_FLOAT | 900 |
| QCBOR_DISABLE_FLOAT_HW_USE | 50 |
| QCBOR_DISABLE_TAGS | 400 |
+ | QCBOR_DISABLE_NON_INTEGER_LABELS | 140 |
| USEFULBUF_DISABLE_ALL_FLOAT | 950 |
QCBOR_DISABLE_ENCODE_USAGE_GUARDS affects encoding only. It doesn't
@@ -497,6 +498,12 @@
have no tags. "Borrowed" tag content formats (e.g. an epoch-based date
without the tag number), can still be processed.
+QCBOR_DISABLE_NON_INTEGER_LABELS causes any label that doesn't
+fit in an int64_t to result in a QCBOR_ERR_MAP_LABEL_TYPE error.
+This also disables QCBOR_DECODE_MODE_MAP_AS_ARRAY and
+QCBOR_DECODE_MODE_MAP_STRINGS_ONLY. It is fairly common for CBOR-based
+protocols to use only small integers as labels.
+
See the discussion above on floating-point.
### Size of spiffy decode
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 652cf01..d64e973 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -555,12 +555,17 @@
/**
* @brief Get string describing an error code.
*
- * @param[in] err The error code.
+ * @param[in] uErr The error code.
*
* @return NULL-terminated string describing error or "Unidentified
* error" if the error is not known.
+ *
+ * This is not thread-safe because it uses a static buffer
+ * for formatting, but this is only a diagnostic and the only
+ * consequence is the wrong description.
*/
-const char *qcbor_err_to_str(QCBORError err);
+const char *
+qcbor_err_to_str(QCBORError uErr);
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 2f55ac4..c1f37cf 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -520,13 +520,15 @@
/** Union holding the different label types selected based on @c uLabelType */
union {
+ /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
+ int64_t int64;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
+ uint64_t uint64;
/** The label for @c uLabelType @ref QCBOR_TYPE_BYTE_STRING and
* @ref QCBOR_TYPE_TEXT_STRING */
UsefulBufC string;
- /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
- int64_t int64;
- /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
- uint64_t uint64;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
} label;
#ifndef QCBOR_DISABLE_TAGS
@@ -1107,7 +1109,7 @@
* in the QCBORItem.
*
* Tags nest. Here the tag with index 0 has the data item as its content. The
- * tag with index 1 has the tag at index 0 has its content and so forth.
+ * tag with index 1 has the tag at index 0 has its content and so forth.
*
* Deep tag nesting is rare so this implementation imposes a limit of
* @ref QCBOR_MAX_TAGS_PER_ITEM on nesting and returns @ref
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 86402ee..c72f4d9 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -1990,15 +1990,20 @@
* @param[in] pMe The encode context.
* @param[in] uNum The simple value.
*
- * Use QCBOREncode_AddBool(), QCBOREncode_AddUndef()... instead of this.
+ * QCBOREncode_AddBool(), QCBOREncode_AddUndef() and
+ * QCBOREncode_AddNull() are preferred to this for the simple values
+ * defined in RFC 8949, but this can be used for them too.
*
- * Use this to add simple values beyond those in defined RFC
- * 8949. Simple values must be registered with IANA. There is no range
- * of values for proprietary use.
+ * The main purpose of this is to add simple values beyond those in
+ * defined RFC 8949. Note that simple values must be registered with
+ * IANA. Those in the range of 0 to 19 must be standardized. Those in
+ * the range of 32 to 255 do not require a standard, but must be
+ * publically specified. There is no range of values for proprietary
+ * use. See
* https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml
*/
static void
-QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum);
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum);
static void
QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
@@ -3954,7 +3959,7 @@
static inline void
-QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum)
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum)
{
#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
if(pMe->uMode >= QCBOR_ENCODE_MODE_DCBOR) {
@@ -3976,8 +3981,8 @@
static inline void
QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
- const char *szLabel,
- const uint8_t uSimple)
+ const char *szLabel,
+ const uint8_t uSimple)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddSimple(pMe, uSimple);
@@ -3985,8 +3990,8 @@
static inline void
QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pMe,
- const int64_t nLabel,
- const uint8_t uSimple)
+ const int64_t nLabel,
+ const uint8_t uSimple)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddSimple(pMe, uSimple);
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 6169a90..d1e5d20 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -1218,6 +1218,37 @@
/**
+ * @brief Decode the next item as a CBOR simple value.
+ *
+ * @param[in] pCtx The decode context.
+ * @param[out] puSimpleValue The simplle value returned.
+ *
+ * The purpose of this is to get a CBOR simple value other than a
+ * Boolean, NULL or "undefined", but this works on all simple
+ * values. See QCBOREncode_AddSimple() for more details on simple
+ * values in general.
+ *
+ * See QCBORDecode_GetBool(), QCBORDecode_GetNull(),
+ * QCBORDecode_GetUndefined() for the preferred way of getting those
+ * simple values.
+ */
+void
+QCBORDecode_GetSimple(QCBORDecodeContext *pCtx, uint8_t *puSimpleValue);
+
+void
+QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pCtx,
+ int64_t nLabel,
+ uint8_t *puSimpleValue);
+
+void
+QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pCtx,
+ const char *szLabel,
+ uint8_t *puSimpleValue);
+
+
+
+
+/**
* @brief Decode the next item as a date string.
*
* @param[in] pCtx The decode context.
@@ -2284,6 +2315,7 @@
QCBORItem *pItem,
UsefulBufC *pEncodedCBOR)
{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORItem OneItemSeach[2];
OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
@@ -2291,6 +2323,12 @@
OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+#else
+ (void)szLabel;
+ (void)pItem;
+ (void)pEncodedCBOR;
+ pMe->uLastError = QCBOR_ERR_MAP_LABEL_TYPE;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
}
static inline void
@@ -2324,6 +2362,7 @@
QCBORItem *pItem,
UsefulBufC *pEncodedCBOR)
{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORItem OneItemSeach[2];
OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
@@ -2331,6 +2370,12 @@
OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+#else
+ (void)szLabel;
+ (void)pItem;
+ (void)pEncodedCBOR;
+ pMe->uLastError = QCBOR_ERR_MAP_LABEL_TYPE;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
}
@@ -2620,6 +2665,7 @@
}
+
static inline void
QCBORDecode_GetDateString(QCBORDecodeContext *pMe,
const uint8_t uTagRequirement,
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 645f6a8..13a728d 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -105,8 +105,10 @@
{
const uint8_t uDataType = Item.uDataType;
return uDataType == QCBOR_TYPE_MAP ||
- uDataType == QCBOR_TYPE_ARRAY ||
- uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ uDataType == QCBOR_TYPE_MAP_AS_ARRAY ||
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+ uDataType == QCBOR_TYPE_ARRAY;
}
static bool
@@ -150,6 +152,7 @@
if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
return true;
}
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
} else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
return true;
@@ -162,6 +165,7 @@
if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
return true;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
}
/* Other label types are never matched */
@@ -373,9 +377,11 @@
}
uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
uItemDataType = QCBOR_TYPE_ARRAY;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
if(uItemDataType != uType) {
return false;
@@ -845,11 +851,13 @@
/**
* @brief Decode integer types, major types 0 and 1.
*
- * @param[in] nMajorType The CBOR major type (0 or 1).
- * @param[in] uArgument The argument from the head.
- * @param[out] pDecodedItem The filled in decoded item.
+ * @param[in] nMajorType The CBOR major type (0 or 1).
+ * @param[in] uArgument The argument from the head.
+ * @param[in] nAdditionalInfo So it can be error-checked.
+ * @param[out] pDecodedItem The filled in decoded item.
*
- * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
+ * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered.
+ * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
*
* Must only be called when major type is 0 or 1.
*
@@ -865,10 +873,16 @@
static QCBORError
QCBOR_Private_DecodeInteger(const int nMajorType,
const uint64_t uArgument,
+ const int nAdditionalInfo,
QCBORItem *pDecodedItem)
{
QCBORError uReturn = QCBOR_SUCCESS;
+ if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+ uReturn = QCBOR_ERR_BAD_INT;
+ goto Done;
+ }
+
if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
if (uArgument <= INT64_MAX) {
pDecodedItem->val.int64 = (int64_t)uArgument;
@@ -895,10 +909,234 @@
}
}
+Done:
return uReturn;
}
+/**
+ * @brief Decode text and byte strings
+ *
+ * @param[in] pMe Decoder context.
+ * @param[in] bAllocate Whether to allocate and copy string.
+ * @param[in] nMajorType Whether it is a byte or text string.
+ * @param[in] uStrLen The length of the string.
+ * @param[in] nAdditionalInfo Whether it is an indefinite-length string.
+ * @param[out] pDecodedItem The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_HIT_END Unexpected end of input.
+ * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
+ *
+ * This reads @c uStrlen bytes from the input and fills in @c
+ * pDecodedItem. If @c bAllocate is true, then memory for the string
+ * is allocated.
+ */
+static QCBORError
+QCBOR_Private_DecodeString(QCBORDecodeContext *pMe,
+ const bool bAllocate,
+ const int nMajorType,
+ const uint64_t uStrLen,
+ const int nAdditionalInfo,
+ QCBORItem *pDecodedItem)
+{
+ QCBORError uReturn = QCBOR_SUCCESS;
+
+ /* ---- Figure out the major type ---- */
+ #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
+ #error QCBOR_TYPE_BYTE_STRING not lined up with major type
+ #endif
+
+ #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
+ #error QCBOR_TYPE_TEXT_STRING not lined up with major type
+ #endif
+ pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
+
+ if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+ /* --- Just the head of an indefinite-length string --- */
+ pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
+
+ } else {
+ /* --- A definite-length string --- */
+ /* --- (which might be a chunk of an indefinte-length string) --- */
+
+ /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
+ * CPUs. This check makes the casts to size_t below safe.
+ *
+ * The max is 4 bytes less than the largest sizeof() so this can be
+ * tested by putting a SIZE_MAX length in the CBOR test input (no
+ * one will care the limit on strings is 4 bytes shorter).
+ */
+ if(uStrLen > SIZE_MAX-4) {
+ uReturn = QCBOR_ERR_STRING_TOO_LONG;
+ goto Done;
+ }
+
+ const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
+ if(UsefulBuf_IsNULLC(Bytes)) {
+ /* Failed to get the bytes for this string item */
+ uReturn = QCBOR_ERR_HIT_END;
+ goto Done;
+ }
+
+ if(bAllocate) {
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+ /* --- Put string in allocated memory --- */
+
+ /* Note that this is not where allocation to coalesce
+ * indefinite-length strings is done. This is for when the
+ * caller has requested all strings be allocated. Disabling
+ * indefinite length strings also disables this allocate-all
+ * option.
+ */
+
+ if(pMe->StringAllocator.pfAllocator == NULL) {
+ uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
+ goto Done;
+ }
+ UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
+ if(UsefulBuf_IsNULL(NewMem)) {
+ uReturn = QCBOR_ERR_STRING_ALLOCATE;
+ goto Done;
+ }
+ pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
+ pDecodedItem->uDataAlloc = 1;
+#else
+ uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+ } else {
+ /* --- Normal case with no string allocator --- */
+ pDecodedItem->val.string = Bytes;
+ }
+ }
+
+Done:
+ return uReturn;
+}
+
+
+/**
+ * @brief Decode array or map.
+ *
+ * @param[in] uMode Decoder mode.
+ * @param[in] nMajorType Whether it is a byte or text string.
+ * @param[in] uItemCount The length of the string.
+ * @param[in] nAdditionalInfo Whether it is an indefinite-length.
+ * @param[out] pDecodedItem The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
+ *
+ * Not much to do for arrays and maps. Just the type item count (but a
+ * little messy because of ifdefs for indefinite-lengths and
+ * map-as-array decoding).
+ *
+ * This also does the bulk of the work for @ref
+ * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
+ * arbitrarily complex map labels. This ifdefs out with
+ * QCBOR_DISABLE_NON_INTEGER_LABELS.
+ */
+static QCBORError
+QCBOR_Private_DecodeArrayOrMap(const uint8_t uMode,
+ const int nMajorType,
+ const uint64_t uItemCount,
+ const int nAdditionalInfo,
+ QCBORItem *pDecodedItem)
+{
+ QCBORError uReturn;
+
+ /* ------ Sort out the data type ------ */
+ #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
+ #error QCBOR_TYPE_ARRAY value not lined up with major type
+ #endif
+
+ #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
+ #error QCBOR_TYPE_MAP value not lined up with major type
+ #endif
+ pDecodedItem->uDataType = (uint8_t)nMajorType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
+ pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
+ }
+#else
+ (void)uMode;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+ uReturn = QCBOR_SUCCESS;
+
+ if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+ /* ------ Indefinite-length array/map ----- */
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+ pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
+#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+ uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+ } else {
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
+ /* ------ Definite-length map as array ------ */
+
+ if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
+ uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
+ } else {
+ /* cast OK because of check above */
+ pDecodedItem->val.uCount = (uint16_t)uItemCount*2;
+ }
+
+ } else
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+ {
+ /* ------ Definite-length array/map ------ */
+ if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
+ uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
+ } else {
+ /* cast OK because of check above */
+ pDecodedItem->val.uCount = (uint16_t)uItemCount;
+ }
+ }
+ }
+
+ return uReturn;
+}
+
+
+/**
+ * @brief Decode a tag number.
+ *
+ * @param[in] uTagNumber The length of the string.
+ * @param[in] nAdditionalInfo So this can be error-checked.
+ * @param[out] pDecodedItem The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_BAD_INT nAdditionalInfo is LEN_IS_INDEFINITE.
+ * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
+ *
+ * Not much to do for tags, but fill in pDecodedItem and check for
+ * error in nAdditionalInfo.
+ */
+static QCBORError
+QCBOR_Private_DecodeTag(const uint64_t uTagNumber,
+ const int nAdditionalInfo,
+ QCBORItem *pDecodedItem)
+{
+#ifndef QCBOR_DISABLE_TAGS
+ if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+ return QCBOR_ERR_BAD_INT;
+ } else {
+ pDecodedItem->val.uTagV = uTagNumber;
+ pDecodedItem->uDataType = QCBOR_TYPE_TAG;
+ return QCBOR_SUCCESS;
+ }
+#else /* QCBOR_DISABLE_TAGS */
+ (void)nAdditionalInfo;
+ (void)uTagNumber;
+ (void)pDecodedItem;
+ return QCBOR_ERR_TAGS_DISABLED;
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
/* Make sure #define value line up as DecodeSimple counts on this. */
#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
#error QCBOR_TYPE_FALSE macro value wrong
@@ -1048,129 +1286,11 @@
/**
- * @brief Decode text and byte strings
- *
- * @param[in] pAllocator The string allocator or NULL.
- * @param[in] uStrLen The length of the string.
- * @param[in] pUInBuf The surce from which to read the string's bytes.
- * @param[out] pDecodedItem The filled in decoded item.
- *
- * @retval QCBOR_ERR_HIT_END Unexpected end of input.
- * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
- * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
- *
- * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
- * pDecodedItem. If @c pAllocator is not NULL then memory for the
- * string is allocated.
- */
-static QCBORError
-QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
- const uint64_t uStrLen,
- UsefulInputBuf *pUInBuf,
- QCBORItem *pDecodedItem)
-{
- QCBORError uReturn = QCBOR_SUCCESS;
-
- /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
- * CPUs. This check makes the casts to size_t below safe.
- *
- * The max is 4 bytes less than the largest sizeof() so this can be
- * tested by putting a SIZE_MAX length in the CBOR test input (no
- * one will care the limit on strings is 4 bytes shorter).
- */
- if(uStrLen > SIZE_MAX-4) {
- uReturn = QCBOR_ERR_STRING_TOO_LONG;
- goto Done;
- }
-
- const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
- if(UsefulBuf_IsNULLC(Bytes)) {
- /* Failed to get the bytes for this string item */
- uReturn = QCBOR_ERR_HIT_END;
- goto Done;
- }
-
-#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
- /* Note that this is not where allocation to coalesce
- * indefinite-length strings is done. This is for when the caller
- * has requested all strings be allocated. Disabling indefinite
- * length strings also disables this allocate-all option.
- */
- if(pAllocator) {
- /* request to use the string allocator to make a copy */
- UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
- if(UsefulBuf_IsNULL(NewMem)) {
- uReturn = QCBOR_ERR_STRING_ALLOCATE;
- goto Done;
- }
- pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
- pDecodedItem->uDataAlloc = 1;
- goto Done;
- }
-#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
- (void)pAllocator;
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
-
- /* Normal case with no string allocator */
- pDecodedItem->val.string = Bytes;
-
-Done:
- return uReturn;
-}
-
-
-/**
- * @brief Map the CBOR major types for strings to the QCBOR types.
- *
- * @param[in] nCBORMajorType The CBOR major type to convert.
- * @retturns QCBOR type number.
- *
- * This only works for the two string types.
- */
-static uint8_t
-QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
-{
- #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
- #error QCBOR_TYPE_BYTE_STRING no lined up with major type
- #endif
-
- #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
- #error QCBOR_TYPE_TEXT_STRING no lined up with major type
- #endif
-
- return (uint8_t)(nCBORMajorType + 4);
-}
-
-
-/**
- * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
- *
- * @param[in] nCBORMajorType The CBOR major type to convert.
- * @retturns QCBOR type number.
- *
- * This only works for the two aggregate types.
- */
-static uint8_t
-QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
-{
- #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
- #error QCBOR_TYPE_ARRAY value not lined up with major type
- #endif
-
- #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
- #error QCBOR_TYPE_MAP value not lined up with major type
- #endif
-
- return (uint8_t)(nCBORMajorType);
-}
-
-
-/**
* @brief Decode a single primitive data item (decode layer 6).
*
- * @param[in] pUInBuf Input buffer to read data item from.
- * @param[out] pDecodedItem The filled-in decoded item.
- * @param[in] pAllocator The allocator to use for strings or NULL.
+ * @param[in] pMe Decoder context.
+ * @param[in] bAllocateStrings If true, use allocator for strings.
+ * @param[out] pDecodedItem The filled-in decoded item.
*
* @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
* features
@@ -1178,6 +1298,7 @@
* @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
* @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
* @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
* @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
* of half-precision disabled
* @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
@@ -1187,104 +1308,67 @@
* @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
* in input, but indefinite
* lengths disabled.
+ * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
+ * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
*
- * This decodes the most primitive / atomic data item. It does
- * no combing of data items.
+ * This decodes the most primitive/atomic data item. It does no
+ * combining of data items.
*/
static QCBORError
-QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
- QCBORItem *pDecodedItem,
- const QCBORInternalAllocator *pAllocator)
+QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext *pMe,
+ const bool bAllocateStrings,
+ QCBORItem *pDecodedItem)
{
QCBORError uReturn;
-
- /* Get the major type and the argument. The argument could be
- * length of more bytes or the value depending on the major
- * type. nAdditionalInfo is an encoding of the length of the
- * uNumber and is needed to decode floats and doubles.
- */
int nMajorType = 0;
uint64_t uArgument = 0;
int nAdditionalInfo = 0;
- memset(pDecodedItem, 0, sizeof(QCBORItem));
-
- uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
- if(uReturn) {
- goto Done;
+ /* Decode the "head" that every CBOR item has into the major type,
+ * argument and the additional info.
+ */
+ uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf), &nMajorType, &uArgument, &nAdditionalInfo);
+ if(uReturn != QCBOR_SUCCESS) {
+ return uReturn;
}
- /* At this point the major type and the argument are valid. We've
- * got the type and the argument that starts every CBOR data item.
+ memset(pDecodedItem, 0, sizeof(QCBORItem));
+
+ /* All the functions below get inlined by the optimizer. This code
+ * is easier to read with them all being similar functions, even if
+ * some functions don't do much.
*/
switch (nMajorType) {
case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
- if(nAdditionalInfo == LEN_IS_INDEFINITE) {
- uReturn = QCBOR_ERR_BAD_INT;
- } else {
- uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
- }
+ return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
break;
case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
- pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
- if(nAdditionalInfo == LEN_IS_INDEFINITE) {
- pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
- } else {
- uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
- }
+ return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
break;
case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
- if(nAdditionalInfo == LEN_IS_INDEFINITE) {
- /* Indefinite-length string. */
-#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
- pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
-#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
- uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
- break;
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
- } else {
- /* Definite-length string. */
- if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
- uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
- goto Done;
- }
- /* cast OK because of check above */
- pDecodedItem->val.uCount = (uint16_t)uArgument;
- }
- pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
+ return QCBOR_Private_DecodeArrayOrMap(pMe->uDecodeMode, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
break;
case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
-#ifndef QCBOR_DISABLE_TAGS
- if(nAdditionalInfo == LEN_IS_INDEFINITE) {
- uReturn = QCBOR_ERR_BAD_INT;
- } else {
- pDecodedItem->val.uTagV = uArgument;
- pDecodedItem->uDataType = QCBOR_TYPE_TAG;
- }
-#else /* QCBOR_DISABLE_TAGS */
- uReturn = QCBOR_ERR_TAGS_DISABLED;
-#endif /* QCBOR_DISABLE_TAGS */
+ return QCBOR_Private_DecodeTag(uArgument, nAdditionalInfo, pDecodedItem);
break;
case CBOR_MAJOR_TYPE_SIMPLE:
/* Major type 7: float, double, true, false, null... */
- uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
+ return QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
break;
default:
/* Never happens because DecodeHead() should never return > 7 */
- uReturn = QCBOR_ERR_UNSUPPORTED;
+ return QCBOR_ERR_UNSUPPORTED;
break;
}
-
-Done:
- return uReturn;
}
@@ -1336,57 +1420,53 @@
* QCBORItem 56 52
* TOTAL 120 74
*/
-
- /* The string allocator is used here for two purposes: 1)
- * coalescing the chunks of an indefinite-length string, 2)
- * allocating storage for every string returned when requested.
- *
- * The first use is below in this function. Indefinite-length
- * strings cannot be processed at all without a string allocator.
- *
- * The second used is in DecodeBytes() which is called by
- * GetNext_Item() below. This second use unneccessary for most use
- * and only happens when requested in the call to
- * QCBORDecode_SetMemPool(). If the second use not requested then
- * NULL is passed for the string allocator to GetNext_Item().
- *
- * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
- * allocator altogether and thus both of these uses. It reduced the
- * decoder object code by about 400 bytes.
- */
- const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
-
-#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
- const QCBORInternalAllocator *pAllocator = NULL;
-
- if(pMe->StringAllocator.pfAllocator) {
- pAllocator = &(pMe->StringAllocator);
- if(pMe->bStringAllocateAll) {
- pAllocatorForGetNext = pAllocator;
- }
- }
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
-
QCBORError uReturn;
- uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
+
+ /* A note about string allocation -- Memory for strings is
+ * allocated either because 1) indefinte-length string chunks are
+ * being coalecsed or 2) caller has requested all strings be
+ * allocated. The first case is handed below here. The second case
+ * is handled in DecodeString if the bAllocate is true. That
+ * boolean originates here with pMe->bStringAllocateAll immediately
+ * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
+ * in two different contexts here 1) main-line processing which is
+ * where definite-length strings need to be allocated if
+ * bStringAllocateAll is true and 2) processing chunks of
+ * indefinite-lengths strings in in which case there must be no
+ * allocation.
+ */
+
+
+ uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
if(uReturn != QCBOR_SUCCESS) {
goto Done;
}
- /* Only do indefinite-length processing on strings */
- const uint8_t uStringType = pDecodedItem->uDataType;
- if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
+
+ /* This is where out-of-place break is detected for the whole
+ * decoding stack. Break is an error for everything that calls
+ * QCBORDecode_Private_GetNextFullString(), so the check is
+ * centralized here.
+ */
+ if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+ uReturn = QCBOR_ERR_BAD_BREAK;
goto Done;
}
- /* Is this a string with an indefinite length? */
+
+ /* Skip out if not an indefinite-length string */
+ const uint8_t uStringType = pDecodedItem->uDataType;
+ if(uStringType != QCBOR_TYPE_BYTE_STRING &&
+ uStringType != QCBOR_TYPE_TEXT_STRING) {
+ goto Done;
+ }
if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
goto Done;
}
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
/* Can't decode indefinite-length strings without a string allocator */
- if(pAllocator == NULL) {
+ if(!pMe->StringAllocator.pfAllocator) {
uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
goto Done;
}
@@ -1397,12 +1477,12 @@
for(;;) {
/* Get QCBORItem for next chunk */
QCBORItem StringChunkItem;
- /* Pass a NULL string allocator to GetNext_Item() because the
- * individual string chunks in an indefinite-length should not
- * be allocated. They are always copied in the the contiguous
- * buffer allocated here.
+ /* Pass false to DecodeAtomicDataItem() because the individual
+ * string chunks in an indefinite-length must not be
+ * allocated. They are always copied into the allocated
+ * contiguous buffer allocated here.
*/
- uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
+ uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
if(uReturn) {
break;
}
@@ -1431,10 +1511,9 @@
* equivalent to StringAllocator_Allocate(). Subsequently it is
* not NULL and a reallocation happens.
*/
- UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
+ UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
FullString.ptr,
FullString.len + StringChunkItem.val.string.len);
-
if(UsefulBuf_IsNULL(NewMem)) {
uReturn = QCBOR_ERR_STRING_ALLOCATE;
break;
@@ -1447,7 +1526,7 @@
if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
/* Getting the item failed, clean up the allocated memory */
- StringAllocator_Free(pAllocator, FullString.ptr);
+ StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
}
#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
@@ -1675,96 +1754,83 @@
* @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
* @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
*
- * If a the current nesting level is a map, then this
- * combines pairs of items into one data item with a label
- * and value.
+ * If the current nesting level is a map, then this combines pairs of
+ * items into one data item with a label and value.
*
- * This is passthrough if the current nesting level is
- * not a map.
+ * This is passthrough if the current nesting level is not a map.
*
- * This also implements maps-as-array mode where a map
- * is treated like an array to allow caller to do their
- * own label processing.
+ * This also implements maps-as-array mode where a map is treated like
+ * an array to allow caller to do their own label processing.
*/
+
static QCBORError
QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
QCBORItem *pDecodedItem)
{
- QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
- if(uReturn != QCBOR_SUCCESS) {
+ QCBORItem LabelItem;
+ QCBORError uErr;
+
+ uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
+ if(QCBORDecode_IsUnrecoverableError(uErr)) {
goto Done;
}
- if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
- /* Break can't be a map entry */
+ if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
+ /* Not decoding a map. Nothing to do. */
+ /* When decoding maps-as-arrays, the type will be
+ * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
+ * here. This is now map processing for maps-as-arrays is not
+ * done. */
goto Done;
}
- if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
- /* Normal decoding of maps -- combine label and value into one item. */
+ /* Decoding a map entry, so the item decoded above was the label */
+ LabelItem = *pDecodedItem;
- if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
- /* Save label in pDecodedItem and get the next which will
- * be the real data item.
- */
- QCBORItem LabelItem = *pDecodedItem;
- uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
- if(QCBORDecode_IsUnrecoverableError(uReturn)) {
- goto Done;
- }
+ /* Get the value of the map item */
+ uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
+ if(QCBORDecode_IsUnrecoverableError(uErr)) {
+ goto Done;
+ }
- pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
+ /* Combine the label item and value item into one */
+ pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
+ pDecodedItem->uLabelType = LabelItem.uDataType;
- if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
- /* strings are always good labels */
- pDecodedItem->label.string = LabelItem.val.string;
- pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
- } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
- /* It's not a string and we only want strings */
- uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
- goto Done;
- } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
- pDecodedItem->label.int64 = LabelItem.val.int64;
- pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
- } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
- pDecodedItem->label.uint64 = LabelItem.val.uint64;
- pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
- } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
- pDecodedItem->label.string = LabelItem.val.string;
- pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
- pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
- } else {
- /* label is not an int or a string. It is an arrray
- * or a float or such and this implementation doesn't handle that.
- * Also, tags on labels are ignored.
- */
- uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
- goto Done;
- }
- }
- } else {
- /* Decoding of maps as arrays to let the caller decide what to do
- * about labels, particularly lables that are not integers or
- * strings.
- */
- if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
- pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
- if(pDecodedItem->val.uCount != UINT16_MAX) {
- /* Adjust definite-length map item count */
- if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
- uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
- goto Done;
- }
- /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
- * Cast is needed because of integer promotion.
- */
- pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
- }
- }
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ /* QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
+ * get rid of it in QCBOR 2.0
+ */
+ if(pMe->uDecodeMode == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
+ LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
+ uErr = QCBOR_ERR_MAP_LABEL_TYPE;
+ goto Done;
+ }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+ switch(LabelItem.uDataType) {
+ case QCBOR_TYPE_INT64:
+ pDecodedItem->label.int64 = LabelItem.val.int64;
+ break;
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ case QCBOR_TYPE_UINT64:
+ pDecodedItem->label.uint64 = LabelItem.val.uint64;
+ break;
+
+ case QCBOR_TYPE_TEXT_STRING:
+ case QCBOR_TYPE_BYTE_STRING:
+ pDecodedItem->label.string = LabelItem.val.string;
+ break;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+ default:
+ uErr = QCBOR_ERR_MAP_LABEL_TYPE;
+ goto Done;
}
Done:
- return uReturn;
+ return uErr;
}
@@ -1772,7 +1838,7 @@
/**
* @brief Peek and see if next data item is a break;
*
- * @param[in] pUIB UsefulInputBuf to read from.
+ * param[in] pUIB UsefulInputBuf to read from.
* @param[out] pbNextIsBreak Indicate if next was a break or not.
*
* @return Any decoding error.
@@ -1781,19 +1847,19 @@
* if not it is not consumed.
*/
static QCBORError
-QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
+QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
{
*pbNextIsBreak = false;
- if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
+ if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
QCBORItem Peek;
- size_t uPeek = UsefulInputBuf_Tell(pUIB);
- QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
+ size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
+ QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
if(uReturn != QCBOR_SUCCESS) {
return uReturn;
}
if(Peek.uDataType != QCBOR_TYPE_BREAK) {
/* It is not a break, rewind so it can be processed normally. */
- UsefulInputBuf_Seek(pUIB, uPeek);
+ UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
} else {
*pbNextIsBreak = true;
}
@@ -1861,7 +1927,7 @@
/* Check for a break which is what ends indefinite-length arrays/maps */
bool bIsBreak = false;
- uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
+ uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
if(uReturn != QCBOR_SUCCESS) {
goto Done;
}
@@ -1992,14 +2058,6 @@
goto Done;
}
- /* Breaks ending arrays/maps are processed later in the call to
- * QCBORDecode_NestLevelAscender(). They should never show up here.
- */
- if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
- uReturn = QCBOR_ERR_BAD_BREAK;
- goto Done;
- }
-
/* Record the nesting level for this data item before processing
* any of decrementing and descending.
*/
@@ -3509,6 +3567,7 @@
return;
}
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORItem OneItemSeach[2];
OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
@@ -3526,8 +3585,16 @@
}
*pItem = OneItemSeach[0];
-
Done:
+
+#else
+ (void)pMe;
+ (void)szLabel;
+ (void)uQcborType;
+ (void)pItem;
+ QCBORError uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
pMe->uLastError = (uint8_t)uReturn;
}
@@ -3578,9 +3645,11 @@
}
uint8_t uItemDataType = pItem->uDataType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
uItemDataType = QCBOR_TYPE_ARRAY;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
if(uItemDataType != uType) {
pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
@@ -3997,6 +4066,7 @@
void
QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORItem OneItemSeach[2];
OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
@@ -4004,6 +4074,10 @@
OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+#else
+ (void)szLabel;
+ pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
}
/*
@@ -4027,6 +4101,7 @@
void
QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORItem OneItemSeach[2];
OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
@@ -4034,6 +4109,10 @@
OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+#else
+ (void)szLabel;
+ pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
}
@@ -4069,9 +4148,13 @@
}
uint8_t uItemDataType = Item.uDataType;
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
uItemDataType = QCBOR_TYPE_ARRAY;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
if(uItemDataType != uType) {
uErr = QCBOR_ERR_UNEXPECTED_TYPE;
goto Done;
@@ -4499,6 +4582,97 @@
}
+/**
+ * @brief Process simple values.
+ *
+ * @param[in] pMe The decode context.
+ * @param[in] pItem The item with the simple value.
+ * @param[out] puSimple The simple value output.
+ *
+ * Sets the internal error if the item isn't a true or a false. Also
+ * records any tag numbers as the tag numbers of the last item.
+ */
+static void
+QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
+ const QCBORItem *pItem,
+ uint8_t *puSimple)
+{
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ return;
+ }
+
+ /* It's kind of lame to remap true...undef back to simple values, but
+ * this function isn't used much and to not do it would require
+ * changing GetNext() behavior in an incompatible way.
+ */
+ switch(pItem->uDataType) {
+ case QCBOR_TYPE_UKNOWN_SIMPLE:
+ *puSimple = pItem->val.uSimple;
+ break;
+
+ case QCBOR_TYPE_TRUE:
+ *puSimple = CBOR_SIMPLEV_TRUE;
+ break;
+
+ case QCBOR_TYPE_FALSE:
+ *puSimple = CBOR_SIMPLEV_FALSE;
+ break;
+
+ case QCBOR_TYPE_NULL:
+ *puSimple = CBOR_SIMPLEV_NULL;
+ break;
+
+ case QCBOR_TYPE_UNDEF:
+ *puSimple = CBOR_SIMPLEV_UNDEF;
+ break;
+
+ default:
+ pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+ return;
+ }
+ QCBORDecode_Private_CopyTags(pMe, pItem);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
+{
+ QCBORItem Item;
+
+ QCBORDecode_VGetNext(pMe, &Item);
+ QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
+ int64_t nLabel,
+ uint8_t *puSimpleValue)
+{
+ QCBORItem Item;
+ QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+ QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
+ const char *szLabel,
+ uint8_t *puSimpleValue)
+{
+ QCBORItem Item;
+ QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+ QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
+}
+
/**
diff --git a/src/qcbor_err_to_str.c b/src/qcbor_err_to_str.c
index 4879f91..87c2b28 100644
--- a/src/qcbor_err_to_str.c
+++ b/src/qcbor_err_to_str.c
@@ -1,69 +1,92 @@
-/*==============================================================================
- err_to_str.c -- strings names for errors
-
- Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
- Copyright (c) 2020, Laurence Lundblade.
- Copyright (c) 2021, Arm Limited. All rights reserved.
-
- SPDX-License-Identifier: BSD-3-Clause
-
- See BSD-3-Clause license in README.md
-
- Created on 3/21/20
- =============================================================================*/
+/* ==========================================================================
+ * err_to_str.c -- strings names for errors
+ *
+ * Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
+ * Copyright (c) 2020,2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.md
+ *
+ * Created on 3/21/20
+ * ========================================================================== */
#include "qcbor/qcbor_common.h"
+#include <string.h>
-#define _ERR_TO_STR(errpart) case QCBOR_##errpart: return "QCBOR_" #errpart;
+#define ERR_TO_STR_CASE(errpart) case errpart: return #errpart;
-const char *qcbor_err_to_str(QCBORError err) {
- switch (err) {
- _ERR_TO_STR(SUCCESS)
- _ERR_TO_STR(ERR_BUFFER_TOO_SMALL)
- _ERR_TO_STR(ERR_ENCODE_UNSUPPORTED)
- _ERR_TO_STR(ERR_BUFFER_TOO_LARGE)
- _ERR_TO_STR(ERR_ARRAY_NESTING_TOO_DEEP)
- _ERR_TO_STR(ERR_CLOSE_MISMATCH)
- _ERR_TO_STR(ERR_ARRAY_TOO_LONG)
- _ERR_TO_STR(ERR_TOO_MANY_CLOSES)
- _ERR_TO_STR(ERR_ARRAY_OR_MAP_STILL_OPEN)
- _ERR_TO_STR(ERR_BAD_TYPE_7)
- _ERR_TO_STR(ERR_EXTRA_BYTES)
- _ERR_TO_STR(ERR_UNSUPPORTED)
- _ERR_TO_STR(ERR_ARRAY_OR_MAP_UNCONSUMED)
- _ERR_TO_STR(ERR_BAD_INT)
- _ERR_TO_STR(ERR_INDEFINITE_STRING_CHUNK)
- _ERR_TO_STR(ERR_HIT_END)
- _ERR_TO_STR(ERR_BAD_BREAK)
- _ERR_TO_STR(ERR_INPUT_TOO_LARGE)
- _ERR_TO_STR(ERR_ARRAY_DECODE_NESTING_TOO_DEEP)
- _ERR_TO_STR(ERR_ARRAY_DECODE_TOO_LONG)
- _ERR_TO_STR(ERR_STRING_TOO_LONG)
- _ERR_TO_STR(ERR_BAD_EXP_AND_MANTISSA)
- _ERR_TO_STR(ERR_NO_STRING_ALLOCATOR)
- _ERR_TO_STR(ERR_STRING_ALLOCATE)
- _ERR_TO_STR(ERR_TOO_MANY_TAGS)
- _ERR_TO_STR(ERR_MAP_LABEL_TYPE)
- _ERR_TO_STR(ERR_UNEXPECTED_TYPE)
- _ERR_TO_STR(ERR_BAD_OPT_TAG)
- _ERR_TO_STR(ERR_DUPLICATE_LABEL)
- _ERR_TO_STR(ERR_MEM_POOL_SIZE)
- _ERR_TO_STR(ERR_INT_OVERFLOW)
- _ERR_TO_STR(ERR_DATE_OVERFLOW)
- _ERR_TO_STR(ERR_EXIT_MISMATCH)
- _ERR_TO_STR(ERR_NO_MORE_ITEMS)
- _ERR_TO_STR(ERR_LABEL_NOT_FOUND)
- _ERR_TO_STR(ERR_NUMBER_SIGN_CONVERSION)
- _ERR_TO_STR(ERR_CONVERSION_UNDER_OVER_FLOW)
- _ERR_TO_STR(ERR_MAP_NOT_ENTERED)
- _ERR_TO_STR(ERR_CALLBACK_FAIL)
- _ERR_TO_STR(ERR_FLOAT_DATE_DISABLED)
- _ERR_TO_STR(ERR_HALF_PRECISION_DISABLED)
- _ERR_TO_STR(ERR_HW_FLOAT_DISABLED)
- _ERR_TO_STR(ERR_FLOAT_EXCEPTION)
- _ERR_TO_STR(ERR_ALL_FLOAT_DISABLED)
- default:
- return "Unidentified error";
- }
+const char *
+qcbor_err_to_str(const QCBORError uErr) {
+ switch (uErr) {
+ ERR_TO_STR_CASE(QCBOR_SUCCESS)
+ ERR_TO_STR_CASE(QCBOR_ERR_BUFFER_TOO_SMALL)
+ ERR_TO_STR_CASE(QCBOR_ERR_ENCODE_UNSUPPORTED)
+ ERR_TO_STR_CASE(QCBOR_ERR_BUFFER_TOO_LARGE)
+ ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_NESTING_TOO_DEEP)
+ ERR_TO_STR_CASE(QCBOR_ERR_CLOSE_MISMATCH)
+ ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_TOO_LONG)
+ ERR_TO_STR_CASE(QCBOR_ERR_TOO_MANY_CLOSES)
+ ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN)
+ ERR_TO_STR_CASE(QCBOR_ERR_OPEN_BYTE_STRING)
+ ERR_TO_STR_CASE(QCBOR_ERR_CANNOT_CANCEL)
+ ERR_TO_STR_CASE(QCBOR_ERR_BAD_TYPE_7)
+ ERR_TO_STR_CASE(QCBOR_ERR_EXTRA_BYTES)
+ ERR_TO_STR_CASE(QCBOR_ERR_UNSUPPORTED)
+ ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED)
+ ERR_TO_STR_CASE(QCBOR_ERR_BAD_INT)
+ ERR_TO_STR_CASE(QCBOR_ERR_INDEFINITE_STRING_CHUNK)
+ ERR_TO_STR_CASE(QCBOR_ERR_HIT_END)
+ ERR_TO_STR_CASE(QCBOR_ERR_BAD_BREAK)
+ ERR_TO_STR_CASE(QCBOR_ERR_INPUT_TOO_LARGE)
+ ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP)
+ ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_DECODE_TOO_LONG)
+ ERR_TO_STR_CASE(QCBOR_ERR_STRING_TOO_LONG)
+ ERR_TO_STR_CASE(QCBOR_ERR_BAD_EXP_AND_MANTISSA)
+ ERR_TO_STR_CASE(QCBOR_ERR_NO_STRING_ALLOCATOR)
+ ERR_TO_STR_CASE(QCBOR_ERR_STRING_ALLOCATE)
+ ERR_TO_STR_CASE(QCBOR_ERR_MAP_LABEL_TYPE)
+ ERR_TO_STR_CASE(QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT)
+ ERR_TO_STR_CASE(QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_TAGS_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_TOO_MANY_TAGS)
+ ERR_TO_STR_CASE(QCBOR_ERR_UNEXPECTED_TYPE)
+ ERR_TO_STR_CASE(QCBOR_ERR_DUPLICATE_LABEL)
+ ERR_TO_STR_CASE(QCBOR_ERR_MEM_POOL_SIZE)
+ ERR_TO_STR_CASE(QCBOR_ERR_INT_OVERFLOW)
+ ERR_TO_STR_CASE(QCBOR_ERR_DATE_OVERFLOW)
+ ERR_TO_STR_CASE(QCBOR_ERR_EXIT_MISMATCH)
+ ERR_TO_STR_CASE(QCBOR_ERR_NO_MORE_ITEMS)
+ ERR_TO_STR_CASE(QCBOR_ERR_LABEL_NOT_FOUND)
+ ERR_TO_STR_CASE(QCBOR_ERR_NUMBER_SIGN_CONVERSION)
+ ERR_TO_STR_CASE(QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW)
+ ERR_TO_STR_CASE(QCBOR_ERR_MAP_NOT_ENTERED)
+ ERR_TO_STR_CASE(QCBOR_ERR_CALLBACK_FAIL)
+ ERR_TO_STR_CASE(QCBOR_ERR_FLOAT_DATE_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_HALF_PRECISION_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_HW_FLOAT_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_FLOAT_EXCEPTION)
+ ERR_TO_STR_CASE(QCBOR_ERR_ALL_FLOAT_DISABLED)
+ ERR_TO_STR_CASE(QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT)
+ ERR_TO_STR_CASE(QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING)
+
+ default:
+ if(uErr >= QCBOR_ERR_FIRST_USER_DEFINED && uErr <= QCBOR_ERR_LAST_USER_DEFINED) {
+ /* Static buffer is not thread safe, but this is only a diagnostic */
+ static char buf[20];
+ strcpy(buf, "USER_DEFINED_");
+ size_t uEndOffset = strlen(buf);
+ buf[uEndOffset] = (char)(uErr/100 + '0');
+ buf[uEndOffset+1] = (char)(((uErr/10) % 10) + '0');
+ buf[uEndOffset+2] = (char)((uErr % 10 )+ '0');
+ buf[uEndOffset+3] = '\0';
+ return buf;
+
+ } else {
+ return "Unidentified QCBOR error";
+ }
+ }
}
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index 0524b4d..0235466 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -1,35 +1,35 @@
-/*==============================================================================
- Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2024, Laurence Lundblade.
- Copyright (c) 2021, Arm Limited.
- All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of The Linux Foundation nor the names of its
- contributors, nor the name "Laurence Lundblade" may be used to
- endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- =============================================================================*/
+/* ==========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors, nor the name "Laurence Lundblade" may be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
#include "UsefulBuf.h"
@@ -146,13 +146,12 @@
/*
- Append test utility.
- pUOB is the buffer to append too
- num is the amount to append
- expected is the expected return code, 0 or 1
-
- returns 0 if test passed
-
+ * Append test utility.
+ * pUOB is the buffer to append too
+ * num is the amount to append
+ * expected is the expected return code, 0 or 1
+ *
+ * returns 0 if test passed
*/
static int AppendTest(UsefulOutBuf *pUOB, size_t num, int expected)
{
@@ -175,7 +174,7 @@
/*
- Same as append, but takes a position param too
+ * Same as append, but takes a position param too
*/
static int InsertTest(UsefulOutBuf *pUOB, size_t num, size_t pos, int expected)
{
@@ -196,15 +195,14 @@
/*
- Boundary conditions to test
- - around 0
- - around the buffer size
- - around MAX size_t
-
-
- Test these for the buffer size and the cursor, the insert amount, the
- append amount and the insert position
-
+ * Boundary conditions to test
+ * - around 0
+ * - around the buffer size
+ * - around MAX size_t
+ *
+ *
+ * Test these for the buffer size and the cursor, the insert amount, the
+ * append amount and the insert position
*/
const char *UOBTest_BoundaryConditionsTest(void)
@@ -280,19 +278,34 @@
if(!UsefulOutBuf_GetError(&UOB)) {
return "lengths near max size";
}
+ UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
+ if(!UsefulBuf_IsNULLC(O)) {
+ return "OutUBuf in error should have returned NULL";
+ }
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, 100});
if(!UsefulOutBuf_IsBufferNULL(&UOB)) {
return "NULL check failed";
}
+ UsefulOutBuf_Init(&UOB, outbuf);
+ UOB.magic = 99; // corrupt the UOB
+ O = UsefulOutBuf_OutUBuf(&UOB);
+ if(!UsefulBuf_IsNULLC(O)) {
+ return "OutUBuf on corrupted should have returned NULL";
+ }
+
+ MakeUsefulBufOnStack(Tmp, 20);
+ O = UsefulOutBuf_CopyOut(&UOB, Tmp);
+ if(!UsefulBuf_IsNULLC(O)) {
+ return "CopyOut on corrupted should have returned NULL";
+ }
+
return NULL;
}
-
-
// Test function to get size and magic number check
const char *TestBasicSanity(void)
@@ -640,6 +653,10 @@
return "Failed to find 3";
}
+ if(SIZE_MAX != UsefulBuf_FindBytes(Expected, ExpectedLonger)) {
+ return "Failed to find 4";
+ }
+
const uint8_t pB[] = {0x01, 0x02, 0x03};
UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
@@ -704,7 +721,7 @@
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
const float f = (float)314.15;
const double d = 2.1e10;
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition
@@ -714,7 +731,7 @@
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat
UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
if(UsefulBuf_IsNULLC(O))
@@ -755,6 +772,16 @@
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+ if(UsefulInputBuf_GetUint16(&UIB) != 0) {
+ return "Didn't catch off end with GetUint16";
+ }
+ if(UsefulInputBuf_GetUint32(&UIB) !=0 ) {
+ return "Didn't catch off end with GetUint32";
+ }
+ if(UsefulInputBuf_GetUint64(&UIB) !=0 ) {
+ return "Didn't catch off end with GetUint64";
+ }
+
// Reset and go again for a few more tests
UsefulInputBuf_Init(&UIB, O);
@@ -789,7 +816,7 @@
if(UsefulInputBuf_BytesAvailable(&UIB, 12)){
return "Wrong number of bytes available II";
}
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
UsefulInputBuf_Seek(&UIB, 0);
@@ -830,6 +857,37 @@
return "OffsetToPointer SIZE_MAX fail";
}
+ UsefulInputBuf_Init(&UIB, Boo);
+ UIB.magic = 88;
+ size_t uUnc = UsefulInputBuf_BytesUnconsumed(&UIB);
+ if(uUnc != 0) {
+ return "Didn't detect corrupted UsefulInputBuf";
+ }
+
+ UsefulInputBuf_Init(&UIB, Boo);
+ UIB.cursor = 500;
+ uUnc = UsefulInputBuf_BytesUnconsumed(&UIB);
+ if(uUnc != 0) {
+ return "Didn't detect bad UsefulInputBuf cursor";
+ }
+
+ if(!UsefulBuf_IsNULLC(UsefulInputBuf_GetUsefulBuf(&UIB, 5000))) {
+ return "Didn't detect off-end request of UsefulInputBuf";
+ }
+
+ if(!UsefulInputBuf_GetError(&UIB)) {
+ return "UIB Error state not reported";
+ }
+
+ UsefulInputBuf_Init(&UIB, Boo);
+ if(UsefulInputBuf_GetBufferLength(&UIB) != Boo.len) {
+ return "UIB length wrong";
+ }
+ UsefulInputBuf_SetBufferLength(&UIB, 1);
+ if(UsefulInputBuf_GetBufferLength(&UIB) != 1) {
+ return "UIB SetBufferLength failed";
+ }
+
return NULL;
}
@@ -855,7 +913,7 @@
return NULL;
}
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
const char *UBAdvanceTest(void)
@@ -901,6 +959,34 @@
return "Advance off end didn't set error";
}
+ // Try to advance in error state
+ UsefulOutBuf_Reset(&UOB);
+ UsefulOutBuf_Advance(&UOB, 1);
+ Place = UsefulOutBuf_GetOutPlace(&UOB);
+ UsefulOutBuf_Advance(&UOB, 1000);
+ UsefulOutBuf_Advance(&UOB, 1);
+ UsefulBuf Place2;
+ Place2 = UsefulOutBuf_GetOutPlace(&UOB);
+ if(memcmp(&Place, &Place2, sizeof(Place))) {
+ return "Advance didn't noop in error state";
+ }
+
+ UsefulOutBuf_Reset(&UOB);
+ UOB.data_len = UOB.UB.len + 1; // React in and corrupt
+ UsefulOutBuf_Advance(&UOB, 1);
+ if(!UsefulOutBuf_GetError(&UOB)) {
+ return "didn't detect corrupted UOB";
+ }
+
+ UsefulOutBuf BadUOB;
+ memset(&BadUOB, 'x', sizeof(BadUOB));
+ BadUOB.err = 0;
+ UsefulOutBuf_Advance(&BadUOB, 1);
+ if(!UsefulOutBuf_GetError(&BadUOB)) {
+ return "didn't detect bad UOB";
+ }
+
+
return NULL;
}
diff --git a/test/UsefulBuf_Tests.h b/test/UsefulBuf_Tests.h
index e00aa37..c0317e8 100644
--- a/test/UsefulBuf_Tests.h
+++ b/test/UsefulBuf_Tests.h
@@ -1,35 +1,35 @@
-/*==============================================================================
- Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2023, Laurence Lundblade.
- Copyright (c) 2021, Arm Limited.
- All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of The Linux Foundation nor the names of its
- contributors, nor the name "Laurence Lundblade" may be used to
- endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ==============================================================================*/
+/* ==========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors, nor the name "Laurence Lundblade" may be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
#ifndef UsefulBuf_UsefulBuf_Tests_h
#define UsefulBuf_UsefulBuf_Tests_h
@@ -48,7 +48,7 @@
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
const char * UBUTest_CopyUtil(void);
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
const char * UBAdvanceTest(void);
diff --git a/test/not_well_formed_cbor.h b/test/not_well_formed_cbor.h
index e505887..5a213ef 100644
--- a/test/not_well_formed_cbor.h
+++ b/test/not_well_formed_cbor.h
@@ -159,9 +159,10 @@
{(uint8_t[]){0xa1, 0xff, 0x00}, 3},
// Array of length 1 with 2nd member value replaced by a break
{(uint8_t[]){0xa1, 0x00, 0xff}, 3},
- // Map of length 2 with 2nd member replaced by a break
- {(uint8_t[]){0xa2, 0x00, 0x00, 0xff}, 4},
-
+ // Map of length 2 with 2nd entry label replaced by a break
+ {(uint8_t[]){0xa2, 0x00, 0x00, 0xff, 0x00}, 5},
+ // Map of length 2 with 2nd entry value replaced by a break
+ {(uint8_t[]){0xa2, 0x00, 0x00, 0x00, 0xff}, 5},
// Breaks must not occur on their own out of an indefinite length
// data item
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 3108fcb..6b97768 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1135,6 +1135,7 @@
#endif
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
/*
Decode and thoroughly check a moderately complex
set of maps. Can be run in QCBOR_DECODE_MODE_NORMAL or in
@@ -1262,7 +1263,7 @@
return 0;
}
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
/* This test requires indef strings, HW float and preferred float,... */
#if !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) && \
@@ -2085,6 +2086,7 @@
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
/*
Fully or partially decode pValidMapEncoded. When
@@ -2292,7 +2294,6 @@
-
int32_t ParseMapTest(void)
{
// Parse a moderatly complex map structure very thoroughly
@@ -2320,6 +2321,7 @@
return nResult;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
/* The simple-values including some not well formed */
@@ -2328,79 +2330,156 @@
0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20,
0xf8, 0xff};
-int32_t ParseSimpleTest(void)
+/* A map of good simple values, plus one well-formed integer */
+static const uint8_t spGoodSimpleValues[] = {
+ 0xa9, 0x01, 0xf4, 0x02, 0xf5, 0x03, 0xf6, 0x04, 0xf7,
+ 0x05, 0xe0, 0x06, 0xf3, 0x07, 0xf8, 0x20, 0x61, 0x40,
+ 0xf8, 0xff, 0x0f, 0x0f};
+
+int32_t SimpleValueDecodeTests(void)
{
QCBORDecodeContext DCtx;
- QCBORItem Item;
- QCBORError nCBORError;
-
+ QCBORItem Item;
+ QCBORError uErr;
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues),
QCBOR_DECODE_MODE_NORMAL);
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_ARRAY ||
Item.val.uCount != 10)
- return -1;
+ return 1;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_FALSE)
- return -1;
+ return 2;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_TRUE)
- return -1;
+ return 3;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_NULL)
- return -1;
+ return 4;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_UNDEF)
- return -1;
+ return 5;
// A break
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_BREAK)
- return -1;
+ return 6;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 0)
- return -1;
+ return 7;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 19)
- return -1;
+ return 8;
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7)
- return -1;
+ return 9;
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7)
- return -1;
+ return 10;
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7)
- return -1;
+ return 11;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 32)
- return -1;
+ return 12;
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return (int32_t)nCBORError;
+ if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+ return (int32_t)uErr;
if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 255)
- return -1;
+ return 13;
+
+
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spGoodSimpleValues),
+ QCBOR_DECODE_MODE_NORMAL);
+
+ uint8_t uSimple;
+
+ QCBORDecode_EnterMap(&DCtx, &Item);
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_FALSE) {
+ return 20;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_TRUE) {
+ return 21;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_NULL) {
+ return 22;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_UNDEF) {
+ return 23;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != 0) {
+ return 24;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != 19) {
+ return 25;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != 32) {
+ return 26;
+ }
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != 255) {
+ return 27;
+ }
+ QCBORDecode_VGetNext(&DCtx, &Item);
+ QCBORDecode_GetSimple(&DCtx, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_NO_MORE_ITEMS) {
+ return 28;
+ }
+
+ QCBORDecode_Rewind(&DCtx);
+
+ QCBORDecode_GetSimpleInMapN(&DCtx, 6, &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != 19) {
+ return 30;
+ }
+
+ QCBORDecode_GetSimpleInMapSZ(&DCtx, "@", &uSimple);
+ if(QCBORDecode_GetError(&DCtx) || uSimple != 255) {
+ return 31;
+ }
+
+ QCBORDecode_GetSimpleInMapN(&DCtx, 99, &uSimple);
+ if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+ return 32;
+ }
+
+ QCBORDecode_GetSimpleInMapSZ(&DCtx, "xx", &uSimple);
+ if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+ return 33;
+ }
+
+ QCBORDecode_GetSimpleInMapN(&DCtx, 15, &uSimple);
+ if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+ return 34;
+ }
return 0;
-
}
@@ -2414,10 +2493,6 @@
const struct someBinaryBytes *pBytes = &paNotWellFormedCBOR[nIterate];
const UsefulBufC Input = (UsefulBufC){pBytes->p, pBytes->n};
- if(nIterate == 86) {
- nIterate = 86;
- }
-
// Set up decoder context. String allocator needed for indefinite
// string test cases
QCBORDecodeContext DCtx;
@@ -2844,9 +2919,14 @@
{"\xa1\x00\xff", 3},
QCBOR_ERR_BAD_BREAK
},
- { "Map of length 2 with 2nd member replaced by a break",
+ { "Map of length 2 with 2nd entry label replaced by a break",
QCBOR_DECODE_MODE_NORMAL,
- {"\xa2\x00\x00\xff", 4},
+ {"\xa2\x00\x00\xff\x00", 5},
+ QCBOR_ERR_BAD_BREAK
+ },
+ { "Map of length 2 with 2nd entry value replaced by a break",
+ QCBOR_DECODE_MODE_NORMAL,
+ {"\xa2\x00\x00\x01\xff", 5},
QCBOR_ERR_BAD_BREAK
},
@@ -4455,12 +4535,14 @@
* These are showing the big numbers converted to integers.
* The tag numbers are not shown.
*
- * [ 18446744073709551616,
- * -18446744073709551617,
- * {"BN+": 18446744073709551616,
- * 64: 18446744073709551616,
- * "BN-": -18446744073709551617,
- * -64: -18446744073709551617
+ * [
+ * 18446744073709551616,
+ * -18446744073709551617,
+ * {
+ * -64: -18446744073709551617,
+ * 64: 18446744073709551616,
+ * "BN+": 18446744073709551616,
+ * "BN-": -18446744073709551617
* }
* ]
*/
@@ -4470,14 +4552,15 @@
0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xA4,
- 0x63, 0x42, 0x4E, 0x2B,
- 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x38, 0x3F,
+ 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x40,
0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x63, 0x42, 0x4E, 0x2D,
- 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x3F,
- 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ 0x63, 0x42, 0x4E, 0x2B,
+ 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x63, 0x42, 0x4E, 0x2D,
+ 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
#ifndef QCBOR_DISABLE_TAGS
/* The expected big num */
@@ -4530,11 +4613,12 @@
}
if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return -9;
- if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
- Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+ return -15;
+ if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
+ Item.uLabelType != QCBOR_TYPE_INT64 ||
+ Item.label.int64 != -64 ||
UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
- return -10;
+ return -16;
}
if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
@@ -4546,6 +4630,15 @@
return -12;
}
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
+ return -9;
+ if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
+ Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+ UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
+ return -10;
+ }
+
if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
return -13;
if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
@@ -4554,14 +4647,9 @@
return -14;
}
- if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
- return -15;
- if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
- Item.uLabelType != QCBOR_TYPE_INT64 ||
- Item.label.int64 != -64 ||
- UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
- return -16;
- }
+
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
#else
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_TAGS_DISABLED) {
@@ -4573,7 +4661,6 @@
}
-
static int32_t CheckItemWithIntLabel(QCBORDecodeContext *pCtx,
uint8_t uDataType,
uint8_t uNestingLevel,
@@ -4587,15 +4674,13 @@
if((nCBORError = QCBORDecode_GetNext(pCtx, &Item))) return -1;
if(Item.uDataType != uDataType) return -1;
if(uNestingLevel > 0) {
- if(Item.uLabelType != QCBOR_TYPE_INT64 &&
- Item.uLabelType != QCBOR_TYPE_UINT64) {
+ if(Item.uLabelType != QCBOR_TYPE_INT64) {
return -1;
}
- if(Item.uLabelType == QCBOR_TYPE_INT64) {
- if(Item.label.int64 != nLabel) return -1;
- } else {
- if(Item.label.uint64 != (uint64_t)nLabel) return -1;
+ if(Item.label.int64 != nLabel) {
+ return -1;
}
+
}
if(Item.uNestingLevel != uNestingLevel) return -1;
if(Item.uNextNestLevel != uNextNest) return -1;
@@ -4606,7 +4691,6 @@
return 0;
}
-
// Same code checks definite and indefinite length versions of the map
static int32_t CheckCSRMaps(QCBORDecodeContext *pDC)
{
@@ -5009,6 +5093,7 @@
// missing end of string
};
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
static const uint8_t spIndefiniteLenStringLabel[] = {
0xa1, // Array of length one
0x7f, // text string marked with indefinite length
@@ -5017,6 +5102,7 @@
0xff, // ending break
0x01 // integer being labeled.
};
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
/**
Make an indefinite length string
@@ -5225,6 +5311,7 @@
return -29;
}
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
// --- label is an indefinite length string ------
QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL);
@@ -5250,6 +5337,7 @@
if(QCBORDecode_Finish(&DC)) {
return -34;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
return 0;
}
@@ -5277,6 +5365,7 @@
return -2;
}
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
// Next parse, save pointers to a few strings, destroy original and
// see all is OK.
UsefulBuf_MAKE_STACK_UB(CopyOfStorage, sizeof(pValidMapEncoded) + QCBOR_DECODE_MIN_MEM_POOL_SIZE);
@@ -5308,7 +5397,9 @@
Item1.val.int64 != 42 ||
Item1.uDataAlloc != 0 ||
Item1.uLabelAlloc == 0 ||
- UsefulBufCompareToSZ(Item1.label.string, "first integer")) {
+ UsefulBufCompareToSZ(Item1.label.string, "first integer") ||
+ Item1.label.string.ptr < Pool.ptr ||
+ Item1.label.string.ptr > (const void *)((const uint8_t *)Pool.ptr + Pool.len)) {
return -4;
}
@@ -5357,6 +5448,7 @@
if(nCBORError != QCBOR_ERR_STRING_ALLOCATE) {
return -10;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
return 0;
}
@@ -6731,7 +6823,6 @@
int32_t EnterMapTest(void)
{
QCBORItem Item1;
- QCBORItem ArrayItem;
QCBORDecodeContext DCtx;
int32_t nReturn;
QCBORError uErr;
@@ -6780,13 +6871,17 @@
return 3011;
}
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
(void)pValidMapIndefEncoded;
nReturn = SpiffyDecodeBasicMap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapIndefEncoded));
if(nReturn) {
return nReturn + 20000;
}
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ QCBORItem ArrayItem;
nReturn = SpiffyDecodeBasicMap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded));
if(nReturn) {
@@ -6868,20 +6963,25 @@
if(QCBORDecode_GetNext(&DCtx, &Item1) != QCBOR_ERR_NO_MORE_ITEMS) {
return 2007;
}
+#endif /* !QCBOR_DISABLE_NON_INTEGER_LABELS */
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleArray), 0);
QCBORDecode_EnterArray(&DCtx, NULL);
int64_t nDecodedInt2;
+
+ UsefulBufC String;
+ QCBORDecode_GetTextStringInMapN(&DCtx, 88, &String);
+ uErr = QCBORDecode_GetAndResetError(&DCtx);
+ if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){
+ return 2009;
+ }
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt2);
uErr = QCBORDecode_GetAndResetError(&DCtx);
if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){
return 2008;
}
- UsefulBufC String;
- QCBORDecode_GetTextStringInMapN(&DCtx, 88, &String);
- if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){
- return 2009;
- }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmptyMap), 0);
@@ -7002,6 +7102,7 @@
}
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
QCBORDecode_VGetNextConsume(&DCtx, &Item1);
if(Item1.uDataType != QCBOR_TYPE_MAP) {
@@ -7050,6 +7151,7 @@
if(QCBORDecode_GetError(&DCtx)) {
return 2410;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
nReturn = DecodeNestedIterate();
@@ -8611,6 +8713,7 @@
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
/*
* An array of an integer and an array. The second array contains
* a bstr-wrapped map.
@@ -8671,11 +8774,11 @@
0x73,
0xff, 0xff
};
-#endif
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
static const uint8_t pWithEmptyMap[] = {0x82, 0x18, 0x64, 0xa0};
+
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
static const uint8_t pWithEmptyMapInDef[] = {0x9f, 0x18, 0x64, 0xbf, 0xff, 0xff};
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
@@ -8701,13 +8804,17 @@
};
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+#endif
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
int32_t PeekAndRewindTest(void)
{
QCBORItem Item;
QCBORError nCBORError;
QCBORDecodeContext DCtx;
+ // Improvement: rework this test to use only integer labels.
+
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) {
@@ -9316,7 +9423,7 @@
}
*/
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
// Rewind an indefnite length byte-string wrapped sequence
@@ -9324,7 +9431,7 @@
return 0;
}
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
static const uint8_t spBooleansInMap[] =
@@ -9704,6 +9811,7 @@
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
static const uint8_t spExpectedArray2s[] = {
0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x31, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
@@ -9753,13 +9861,13 @@
};
#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
-
#ifndef QCBOR_DISABLE_TAGS
/* An exp / mant tag in two nested arrays */
static const uint8_t spExpMant[] = {0x81, 0x81, 0xC4, 0x82, 0x20, 0x03};
#endif /* !QCBOR_DISABLE_TAGS */
+#endif
-
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
int32_t GetMapAndArrayTest(void)
{
QCBORDecodeContext DCtx;
@@ -9767,7 +9875,7 @@
QCBORItem Item;
UsefulBufC ReturnedEncodedCBOR;
-
+ // Improvement: rework so it can run with QCBOR_DISABLE_NON_INTEGER_LABELS
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
0);
@@ -10024,10 +10132,11 @@
if(uPosition != QCBORDecode_Tell(&DCtx)) {
return 102;
}
-#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
return 0;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
int32_t
@@ -10108,6 +10217,41 @@
return -23;
}
+ /* Test error strings */
+ const char *szErrString;
+
+ szErrString = qcbor_err_to_str(QCBOR_ERR_ARRAY_DECODE_TOO_LONG);
+ if(szErrString == NULL) {
+ return -100;
+ }
+ if(strcmp(szErrString, "QCBOR_ERR_ARRAY_DECODE_TOO_LONG")) {
+ return -101;
+ }
+
+ szErrString = qcbor_err_to_str(QCBOR_SUCCESS);
+ if(szErrString == NULL) {
+ return -102;
+ }
+ if(strcmp(szErrString, "QCBOR_SUCCESS")) {
+ return -103;
+ }
+
+ szErrString = qcbor_err_to_str(100);
+ if(szErrString == NULL) {
+ return -104;
+ }
+ if(strcmp(szErrString, "Unidentified QCBOR error")) {
+ return -105;
+ }
+
+ szErrString = qcbor_err_to_str(200);
+ if(szErrString == NULL) {
+ return -106;
+ }
+ if(strcmp(szErrString, "USER_DEFINED_200")) {
+ return -107;
+ }
+
return 0;
}
@@ -10120,6 +10264,7 @@
int nIndex;
int64_t nDecodedInt;
+ // Improvement: rewrite so this can run with only integer labels
static const uint32_t aPos[] =
{0, 1, 17, 42, 50, 58, 72, 85, 98, 112, UINT32_MAX};
QCBORDecode_Init(&DCtx,
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index e3fe1b6..4c4c0a6 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -126,7 +126,7 @@
/*
Test parsing of some simple values like true, false, null...
*/
-int32_t ParseSimpleTest(void);
+int32_t SimpleValueDecodeTests(void);
/*
diff --git a/test/run_tests.c b/test/run_tests.c
index a94aa47..e24506a 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -67,48 +67,58 @@
static test_entry s_tests[] = {
- TEST_ENTRY(ErrorHandlingTests),
- TEST_ENTRY(OpenCloseBytesTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
TEST_ENTRY(GetMapAndArrayTest),
TEST_ENTRY(TellTests),
+ TEST_ENTRY(ParseMapAsArrayTest),
+ TEST_ENTRY(SpiffyDateDecodeTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+ TEST_ENTRY(ErrorHandlingTests),
+ TEST_ENTRY(OpenCloseBytesTest),
TEST_ENTRY(EnterBstrTest),
TEST_ENTRY(IntegerConvertTest),
TEST_ENTRY(EnterMapTest),
TEST_ENTRY(QCBORHeadTest),
TEST_ENTRY(EmptyMapsAndArraysTest),
TEST_ENTRY(NotWellFormedTests),
- TEST_ENTRY(ParseMapAsArrayTest),
+
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
TEST_ENTRY(IndefiniteLengthNestTest),
TEST_ENTRY(IndefiniteLengthArrayMapTest),
TEST_ENTRY(NestedMapTestIndefLen),
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
- TEST_ENTRY(ParseSimpleTest),
+
+ TEST_ENTRY(SimpleValueDecodeTests),
TEST_ENTRY(DecodeFailureTests),
TEST_ENTRY(EncodeRawTest),
TEST_ENTRY(RTICResultsTest),
TEST_ENTRY(MapEncodeTest),
TEST_ENTRY(ArrayNestingTest1),
TEST_ENTRY(ArrayNestingTest2),
+
#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
TEST_ENTRY(ArrayNestingTest3),
#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
TEST_ENTRY(EncodeDateTest),
TEST_ENTRY(SimpleValuesTest1),
TEST_ENTRY(IntegerValuesTest1),
TEST_ENTRY(AllAddMethodsTest),
TEST_ENTRY(ParseTooDeepArrayTest),
TEST_ENTRY(ComprehensiveInputTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
TEST_ENTRY(ParseMapTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
TEST_ENTRY(BasicEncodeTest),
TEST_ENTRY(NestedMapTest),
TEST_ENTRY(BignumParseTest),
+
#ifndef QCBOR_DISABLE_TAGS
TEST_ENTRY(OptTagParseTest),
TEST_ENTRY(DateParseTest),
TEST_ENTRY(DecodeTaggedTypeTests),
#endif /* QCBOR_DISABLE_TAGS */
- TEST_ENTRY(SpiffyDateDecodeTest),
+
TEST_ENTRY(ShortBufferParseTest2),
TEST_ENTRY(ShortBufferParseTest),
TEST_ENTRY(ParseDeepArrayTest),
@@ -118,9 +128,12 @@
TEST_ENTRY(AllocAllStringsTest),
TEST_ENTRY(MemPoolTest),
TEST_ENTRY(IndefiniteLengthStringTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
TEST_ENTRY(SpiffyIndefiniteLengthStringsTests),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
TEST_ENTRY(SetUpAllocatorTest),
TEST_ENTRY(CBORTestIssue134),
+
#endif /* #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
@@ -131,19 +144,29 @@
TEST_ENTRY(GeneralFloatEncodeTests),
TEST_ENTRY(GeneralFloatDecodeTests),
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
TEST_ENTRY(BstrWrapTest),
TEST_ENTRY(BstrWrapErrorTest),
TEST_ENTRY(BstrWrapNestTest),
TEST_ENTRY(CoseSign1TBSTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
TEST_ENTRY(StringDecoderModeFailTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
TEST_ENTRY_DISABLED(TooLargeInputTest),
TEST_ENTRY(EncodeErrorTests),
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
+#endif
TEST_ENTRY(EncodeLengthThirtyoneTest),
TEST_ENTRY(CBORSequenceDecodeTests),
TEST_ENTRY(IntToTests),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
TEST_ENTRY(PeekAndRewindTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+
+
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
TEST_ENTRY(ExponentAndMantissaDecodeTests),
#ifndef QCBOR_DISABLE_TAGS