New #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
#define QCBOR_DISABLE_NON_INTEGER_LABELS allows label processing for all but integers labels to be disabled to save object code.
There was also a lot of refactoring of the decode in this change for the sake of clarity and object code size reduction.
All totaled, this saves nearly 200 bytes of object code, but that is the growth in object code over the last years from small fixes and features so there's no net gain compared to a years ago. The minimal decoder is still 1550 bytes.
* #define to disable non-integer labels
* Add non-int to CI
* Remove string labels from QCBORItem
* Small corrections
* lots of code tidiness
* optimize out-of-place break error handling
* fix allocate all bug introduced early in PR
---------
Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
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 eeed238..aae1f80 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1139,6 +1139,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
@@ -1266,7 +1267,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) && \
@@ -2089,6 +2090,7 @@
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
/*
Fully or partially decode pValidMapEncoded. When
@@ -2296,7 +2298,6 @@
-
int32_t ParseMapTest(void)
{
// Parse a moderatly complex map structure very thoroughly
@@ -2324,6 +2325,7 @@
return nResult;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
/* The simple-values including some not well formed */
@@ -2418,10 +2420,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;
@@ -2848,9 +2846,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
},
@@ -4459,12 +4462,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
* }
* ]
*/
@@ -4474,14 +4479,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 */
@@ -4534,11 +4540,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)))
@@ -4550,6 +4557,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 ||
@@ -4558,14 +4574,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) {
@@ -4577,7 +4588,6 @@
}
-
static int32_t CheckItemWithIntLabel(QCBORDecodeContext *pCtx,
uint8_t uDataType,
uint8_t uNestingLevel,
@@ -4591,15 +4601,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;
@@ -4610,7 +4618,6 @@
return 0;
}
-
// Same code checks definite and indefinite length versions of the map
static int32_t CheckCSRMaps(QCBORDecodeContext *pDC)
{
@@ -5013,6 +5020,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
@@ -5021,6 +5029,7 @@
0xff, // ending break
0x01 // integer being labeled.
};
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
/**
Make an indefinite length string
@@ -5229,6 +5238,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);
@@ -5254,6 +5264,7 @@
if(QCBORDecode_Finish(&DC)) {
return -34;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
return 0;
}
@@ -5281,6 +5292,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);
@@ -5312,7 +5324,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;
}
@@ -5361,6 +5375,7 @@
if(nCBORError != QCBOR_ERR_STRING_ALLOCATE) {
return -10;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
return 0;
}
@@ -6736,7 +6751,6 @@
int32_t EnterMapTest(void)
{
QCBORItem Item1;
- QCBORItem ArrayItem;
QCBORDecodeContext DCtx;
int32_t nReturn;
QCBORError uErr;
@@ -6785,13 +6799,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) {
@@ -6873,20 +6891,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);
@@ -7013,6 +7036,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) {
@@ -7061,6 +7085,7 @@
if(QCBORDecode_GetError(&DCtx)) {
return 2410;
}
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
nReturn = DecodeNestedIterate();
@@ -8610,6 +8635,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.
@@ -8670,11 +8696,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 */
@@ -8700,13 +8726,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))) {
@@ -9315,7 +9345,7 @@
}
*/
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
// Rewind an indefnite length byte-string wrapped sequence
@@ -9323,7 +9353,7 @@
return 0;
}
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
static const uint8_t spBooleansInMap[] =
@@ -9495,7 +9525,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,
@@ -9545,13 +9575,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;
@@ -9559,7 +9589,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);
@@ -9816,10 +9846,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
@@ -9947,6 +9978,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/run_tests.c b/test/run_tests.c
index e4a431b..a600731 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -66,8 +66,12 @@
static test_entry s_tests[] = {
+#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),
@@ -76,7 +80,6 @@
TEST_ENTRY(QCBORHeadTest),
TEST_ENTRY(EmptyMapsAndArraysTest),
TEST_ENTRY(NotWellFormedTests),
- TEST_ENTRY(ParseMapAsArrayTest),
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
TEST_ENTRY(IndefiniteLengthNestTest),
TEST_ENTRY(IndefiniteLengthArrayMapTest),
@@ -98,7 +101,9 @@
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),
@@ -107,7 +112,6 @@
TEST_ENTRY(DateParseTest),
TEST_ENTRY(DecodeTaggedTypeTests),
#endif /* QCBOR_DISABLE_TAGS */
- TEST_ENTRY(SpiffyDateDecodeTest),
TEST_ENTRY(ShortBufferParseTest2),
TEST_ENTRY(ShortBufferParseTest),
TEST_ENTRY(ParseDeepArrayTest),
@@ -117,7 +121,9 @@
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 */
@@ -133,7 +139,9 @@
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),
@@ -143,7 +151,9 @@
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