From 1437b2e5ec39bfeb3d714e5505fb387ae3b9a6ea Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 2 Oct 2026 13:18:38 -0700 Subject: [PATCH 1/2] Validator: allow UnixTime_t tags (tag 1) to contain floating point This was a mistake in the original content. Even RFC 7049 said: > The tagged item can be a positive or negative > integer (major types 0 and 1), or a floating-point number (major type > 7 with additional information 25, 26, or 27) For #339. Signed-off-by: Thiago Macieira --- src/cborvalidation.c | 5 +++-- tests/parser/tst_parser.cpp | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cborvalidation.c b/src/cborvalidation.c index 2ad0c18c..d94d204a 100644 --- a/src/cborvalidation.c +++ b/src/cborvalidation.c @@ -129,7 +129,7 @@ 1 - integer + numeric (integer or floating-point) Epoch-based date/time @@ -238,7 +238,8 @@ struct KnownTagData { uint32_t tag; uint32_t types; }; static const struct KnownTagData knownTagData[] = { { 0, (uint32_t)CborTextStringType }, - { 1, (uint32_t)(CborIntegerType+1) }, + { 1, (uint32_t)(CborIntegerType+1) | ((uint32_t)CborHalfFloatType << 8) | + ((uint32_t)CborFloatType << 16) | ((uint32_t)CborDoubleType << 24)}, { 2, (uint32_t)CborByteStringType }, { 3, (uint32_t)CborByteStringType }, { 4, (uint32_t)CborArrayType }, diff --git a/tests/parser/tst_parser.cpp b/tests/parser/tst_parser.cpp index f9374583..43407acb 100644 --- a/tests/parser/tst_parser.cpp +++ b/tests/parser/tst_parser.cpp @@ -1686,6 +1686,14 @@ void tst_Parser::strictValidation_data() QTest::newRow("tag-1-unsigned") << raw("\xc1\x00") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-1-negative") << raw("\xc1\x20") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-1-bytearray") << raw("\xc1\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + QTest::newRow("tag-1-string") << raw("\xc1\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + QTest::newRow("tag-1-array") << raw("\xc1\x80") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + QTest::newRow("tag-1-map") << raw("\xc1\xa0") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + QTest::newRow("tag-1-tag-unsigned") << raw("\xc1\xc1\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + QTest::newRow("tag-1-boolean") << raw("\xc1\xf4") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + QTest::newRow("tag-1-fp16") << raw("\xc1\xf9\0\0") << int(CborValidateStrictMode) << CborNoError; + QTest::newRow("tag-1-float") << raw("\xc1\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError; + QTest::newRow("tag-1-double") << raw("\xc1\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-2-bytearray") << raw("\xc2\x40") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-2-string") << raw("\xc2\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; QTest::newRow("tag-3-bytearray") << raw("\xc3\x40") << int(CborValidateStrictMode) << CborNoError; From 577d42bc480d50f0ee9b626e88b6564013db6148 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 2 Oct 2026 13:20:28 -0700 Subject: [PATCH 2/2] Validator: allow ExpectedBaseXXTags (tags 21-23) to tag any value They were meant to tag byte strings, directly or indirectly. But the wording in RFC 7049 and 8949 is > The data item tagged can be a byte string or any other data item. That means it can be used to tag numbers and text strings, which in my opinion makes no sense, but let's allow them. For the testing, we can reuse and combine with the data for the other tag that accepted anything: the CBOR signature one. For #339. Signed-off-by: Thiago Macieira --- src/cborvalidation.c | 12 ++++---- tests/parser/tst_parser.cpp | 57 ++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/cborvalidation.c b/src/cborvalidation.c index d94d204a..519e4eae 100644 --- a/src/cborvalidation.c +++ b/src/cborvalidation.c @@ -169,17 +169,17 @@ 21 - byte string, array, map + any Expected conversion to base64url encoding 22 - byte string, array, map + any Expected conversion to base64 encoding 23 - byte string, array, map + any Expected conversion to base16 encoding @@ -247,9 +247,9 @@ static const struct KnownTagData knownTagData[] = { { 16, (uint32_t)CborArrayType }, { 17, (uint32_t)CborArrayType }, { 18, (uint32_t)CborArrayType }, - { 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, + { 21, 0U /* any type allowed */ }, + { 22, 0U /* any type allowed */ }, + { 23, 0U /* any type allowed */ }, { 24, (uint32_t)CborByteStringType }, { 32, (uint32_t)CborTextStringType }, { 33, (uint32_t)CborTextStringType }, diff --git a/tests/parser/tst_parser.cpp b/tests/parser/tst_parser.cpp index 43407acb..425feb9a 100644 --- a/tests/parser/tst_parser.cpp +++ b/tests/parser/tst_parser.cpp @@ -1679,6 +1679,30 @@ void tst_Parser::strictValidation_data() QTest::newRow("nonunique-content-map-SS") << raw("\xa2\x61z\1\x61z\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique; QTest::newRow("nonunique-content-map-AA") << raw("\xa2\x81\x65Hello\1\x81\x65Hello\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique; + auto addTagAnyAllowed = [](int tagnumber, const QByteArray &tag) { + auto addRow = [&](const char *name, const QByteArray &payload) { + QTest::addRow("tag-%d-%s", tagnumber, name) + << (tag + payload) << int(CborValidateStrictMode) << CborNoError; + }; + addRow("unsigned", raw("\0")); + addRow("negative", "\x20"); + addRow("bytearray", "\x40"); + addRow("string", "\x60"); + addRow("array", "\x80"); + addRow("map", "\xa0"); + QTest::addRow("tag-%d-tag-0-unsigned", tagnumber) + << (tag + raw("\xc0\x00")) << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; + addRow("tag-0-string", raw("\xc0\x60")); + addRow("simple0", raw("\xe0")); + addRow("false", raw("\xf4")); + addRow("true", raw("\xf5")); + addRow("null", raw("\xf6")); + addRow("undefined", raw("\xf7")); + addRow("simple32", raw("\xf8\x20")); + addRow("half", raw("\xf9\0\0")); + addRow("float", raw("\xfa\0\0\0\0")); + addRow("double", raw("\xfb\0\0\0\0\0\0\0\0")); + }; QTest::newRow("tag-0-unsigned") << raw("\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; QTest::newRow("tag-0-bytearray") << raw("\xc0\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; QTest::newRow("tag-0-string") << raw("\xc0\x60") << int(CborValidateStrictMode) << CborNoError; @@ -1702,18 +1726,9 @@ void tst_Parser::strictValidation_data() QTest::newRow("tag-4-array") << raw("\xc4\x82\0\1") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-5-string") << raw("\xc5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; QTest::newRow("tag-5-array") << raw("\xc5\x82\0\1") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-21-bytearray") << raw("\xd5\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-21-string") << raw("\xd5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-21-array") << raw("\xd5\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-21-map") << raw("\xd5\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-22-bytearray") << raw("\xd6\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-22-string") << raw("\xd6\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-22-array") << raw("\xd6\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-22-map") << raw("\xd6\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-23-bytearray") << raw("\xd7\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-23-string") << raw("\xd7\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-23-array") << raw("\xd7\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-23-map") << raw("\xd7\xa0") << int(CborValidateStrictMode) << CborNoError; + addTagAnyAllowed(CborExpectedBase64urlTag, "\xd5"); + addTagAnyAllowed(CborExpectedBase64Tag, "\xd6"); + addTagAnyAllowed(CborExpectedBase16Tag, "\xd7"); QTest::newRow("tag-24-bytearray") << raw("\xd8\x18\x40") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-24-string") << raw("\xd8\x18\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; QTest::newRow("tag-32-bytearray") << raw("\xd8\x20\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; @@ -1726,23 +1741,7 @@ void tst_Parser::strictValidation_data() QTest::newRow("tag-35-string") << raw("\xd8\x23\x60") << int(CborValidateStrictMode) << CborNoError; QTest::newRow("tag-36-bytearray") << raw("\xd8\x24\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; QTest::newRow("tag-36-string") << raw("\xd8\x24\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-unsigned") << raw("\xd9\xd9\xf7\x00") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-negative") << raw("\xd9\xd9\xf7\x20") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-bytearray") << raw("\xd9\xd9\xf7\x40") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-string") << raw("\xd9\xd9\xf7\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-array") << raw("\xd9\xd9\xf7\x80") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-map") << raw("\xd9\xd9\xf7\xa0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-tag-0-unsigned") << raw("\xd9\xd9\xf7\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType; - QTest::newRow("tag-55799-tag-0-string") << raw("\xd9\xd9\xf7\xc0\x60") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-simple0") << raw("\xd9\xd9\xf7\xe0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-false") << raw("\xd9\xd9\xf7\xf4") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-true") << raw("\xd9\xd9\xf7\xf5") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-null") << raw("\xd9\xd9\xf7\xf6") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-undefined") << raw("\xd9\xd9\xf7\xf7") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-simple32") << raw("\xd9\xd9\xf7\xf8\x20") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-half") << raw("\xd9\xd9\xf7\xf9\0\0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-float") << raw("\xd9\xd9\xf7\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError; - QTest::newRow("tag-55799-double") << raw("\xd9\xd9\xf7\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError; + addTagAnyAllowed(CborSignatureTag, raw("\xd9\xd9\xf7")); // excluded non-finite QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;