Spiffy decode GetString() now ignores tag numbers (#260)
QCBORDecode_GetTextString() and QCBORDecode_GetByteString() now do not error out if there are tag numbers on the strings being decoded. This is to be consistent with all the other GetXXXX functions that also do not error out.
This is a behavior change, but it is assumed that no one relies on this behavior in QCBOR because most GetXXXX functions don't do it. Checking for extraneous tags is done with QCBORDecode_GetNthTagOfLast(). This works for of the GetXxxx functions and is what should be to replace reliance old QCBORDecode_GetByteString() behavior.
* Spiffy decode GetString() now ignores extra tag numbers
* fix use when tags are disabled
* improve tests
* fix #ifdef fan out
---------
Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index e5ea0a9..2b2311a 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -2502,7 +2502,7 @@
// Complier should make this just a 64-bit integer parameter
const QCBOR_Private_TagSpec TagSpec =
{
- QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ QCBOR_TAG_REQUIREMENT_TAG | QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS,
{QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
{QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
};
@@ -2517,7 +2517,7 @@
{
const QCBOR_Private_TagSpec TagSpec =
{
- QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ QCBOR_TAG_REQUIREMENT_NOT_A_TAG | QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS,
{QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
{QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
};
@@ -2531,7 +2531,7 @@
{
const QCBOR_Private_TagSpec TagSpec =
{
- QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ QCBOR_TAG_REQUIREMENT_NOT_A_TAG | QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS,
{QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
{QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
};
@@ -2546,7 +2546,7 @@
// Complier should make this just 64-bit integer parameter
const QCBOR_Private_TagSpec TagSpec =
{
- QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ QCBOR_TAG_REQUIREMENT_NOT_A_TAG | QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS,
{QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
{QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
};
@@ -2563,7 +2563,7 @@
// to passing a 64-bit integer
const QCBOR_Private_TagSpec TagSpec =
{
- QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ QCBOR_TAG_REQUIREMENT_NOT_A_TAG | QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS,
{QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
{QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
};
@@ -2578,7 +2578,7 @@
{
const QCBOR_Private_TagSpec TagSpec =
{
- QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ QCBOR_TAG_REQUIREMENT_NOT_A_TAG | QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS,
{QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
{QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
};
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 0d689d8..1d20077 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -3788,10 +3788,11 @@
* This checks the data item type as possibly representing the tag
* number or as the tag content type.
*
- * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
- * data type against the allowed tag content types. It will also error out
- * if the caller tries to require a tag because there is no way that can
- * ever be fulfilled.
+ * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
+ * data type against the allowed tag content types, but also checks
+ * against the tagged types. The QCBOR_TYPEs checked will never be
+ * associated with tag numbers, but this checking is needed for the
+ * text and byte string use cases .
*/
static QCBORError
QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
@@ -3826,17 +3827,20 @@
return QCBOR_ERR_UNEXPECTED_TYPE;
}
- /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
- * and it hasn't matched the content, so the end
- * result is whether it matches the tag. This is
- * the tag optional case that the CBOR standard discourages.
+ /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either
+ * the tag or the content and it hasn't matched the content, so the
+ * end result is whether it matches the tag. This is the tag
+ * optional case that the CBOR standard discourages.
*/
return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
#else /* QCBOR_DISABLE_TAGS */
if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
- return QCBOR_ERR_UNEXPECTED_TYPE;
+ /* This is only checking base QCBOR types, not those associated
+ * with tag numbers since you can get here with tag numbers.
+ */
+ return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
}
return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index e9745e3..6d3cc9a 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -4106,6 +4106,14 @@
};
+static const uint8_t spTaggedString[] = {
+ 0xd8, 0xf0, 0x61, 0x40,
+};
+
+static const uint8_t spTaggedInt[] = {
+ 0xd8, 0xf4, 0x01,
+};
+
static int32_t CheckCSRMaps(QCBORDecodeContext *pDC);
@@ -4114,6 +4122,9 @@
QCBORDecodeContext DCtx;
QCBORItem Item;
QCBORError uError;
+ UsefulBufC UBC;
+ int64_t nInt;
+
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTagInput),
@@ -4581,7 +4592,6 @@
if(QCBORDecode_GetNthTagOfLast(&DCtx, 3) != CBOR_TAG_INVALID64) {
return 234;
}
- int64_t nInt;
QCBORDecode_GetInt64(&DCtx, &nInt);
if(QCBORDecode_GetNthTagOfLast(&DCtx, 0) != 7) {
return 240;
@@ -4597,6 +4607,8 @@
}
#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyTagInput),
QCBOR_DECODE_MODE_NORMAL);
@@ -4666,6 +4678,42 @@
return 305;
}
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTaggedString),
+ QCBOR_DECODE_MODE_NORMAL);
+
+ /* See that QCBORDecode_GetTextString() ignores tags */
+ QCBORDecode_GetTextString(&DCtx, &UBC);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 400;
+ }
+ if(UBC.len != 1) {
+ return 401;
+ }
+
+ uint64_t uTagNumber = QCBORDecode_GetNthTagOfLast(&DCtx, 0);
+ if(uTagNumber != 240) {
+ return 404;
+ }
+
+
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTaggedInt),
+ QCBOR_DECODE_MODE_NORMAL);
+ /* See that QCBORDecode_GetInt64() ignores tags */
+ QCBORDecode_GetInt64(&DCtx, &nInt);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 410;
+ }
+ if(nInt != 1) {
+ return 411;
+ }
+
+ uTagNumber = QCBORDecode_GetNthTagOfLast(&DCtx, 0);
+ if(uTagNumber != 244) {
+ return 414;
+ }
+
return 0;
}