Skip to content

Commit c85bcf5

Browse files
Validation: implement validation of tag/type matching
This implements: - CborValidateTagUse This modifies the parsetags.pl script to encode the types in a typemask. We can encode up to 4 types per tag; if there's a tag in the future that can match more than four (and still not "any"), we'll need to update the code. Two non-obvious details: - we encode "any" as ~0U (all bits set) - we encode CborIntegerType as 1 because CborIntegerType = 0 (that is necessary to distinguish it from no further types in the type mask) Signed-off-by: Thiago Macieira <[email protected]>
1 parent 0342d72 commit c85bcf5

File tree

3 files changed

+103
-20
lines changed

3 files changed

+103
-20
lines changed

src/cborvalidation.c

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -205,24 +205,24 @@
205205
</table>
206206
*/
207207

208-
struct KnownTagData { uint32_t tag; };
208+
struct KnownTagData { uint32_t tag; uint32_t types; };
209209
static const struct KnownTagData knownTagData[] = {
210-
{ 0 },
211-
{ 1 },
212-
{ 2 },
213-
{ 3 },
214-
{ 4 },
215-
{ 5 },
216-
{ 21 },
217-
{ 22 },
218-
{ 23 },
219-
{ 24 },
220-
{ 32 },
221-
{ 33 },
222-
{ 34 },
223-
{ 35 },
224-
{ 36 },
225-
{ 55799 }
210+
{ 0, (uint8_t)CborTextStringType },
211+
{ 1, (uint8_t)(CborIntegerType+1) },
212+
{ 2, (uint8_t)CborByteStringType },
213+
{ 3, (uint8_t)CborByteStringType },
214+
{ 4, (uint8_t)CborArrayType },
215+
{ 5, (uint8_t)CborArrayType },
216+
{ 21, (uint8_t)CborByteStringType | ((uint8_t)CborArrayType << 8) | ((uint8_t)CborMapType << 16) },
217+
{ 22, (uint8_t)CborByteStringType | ((uint8_t)CborArrayType << 8) | ((uint8_t)CborMapType << 16) },
218+
{ 23, (uint8_t)CborByteStringType | ((uint8_t)CborArrayType << 8) | ((uint8_t)CborMapType << 16) },
219+
{ 24, (uint8_t)CborByteStringType },
220+
{ 32, (uint8_t)CborTextStringType },
221+
{ 33, (uint8_t)CborTextStringType },
222+
{ 34, (uint8_t)CborTextStringType },
223+
{ 35, (uint8_t)CborTextStringType },
224+
{ 36, (uint8_t)CborTextStringType },
225+
{ 55799, 0U }
226226
};
227227

228228
static CborError validate_value(CborValue *it, int flags, int recursionLeft);
@@ -271,6 +271,22 @@ static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int
271271
return CborErrorUnknownTag;
272272
}
273273

274+
if (flags & CborValidateTagUse && tagData && tagData->types) {
275+
uint32_t allowedTypes = tagData->types;
276+
277+
/* correct Integer so it's not zero */
278+
if (type == CborIntegerType)
279+
++type;
280+
281+
while (allowedTypes) {
282+
if ((uint8_t)(allowedTypes & 0xff) == type)
283+
break;
284+
allowedTypes >>= 8;
285+
}
286+
if (!allowedTypes)
287+
return CborErrorInappropriateTagForType;
288+
}
289+
274290
return validate_value(it, flags, recursionLeft);
275291
}
276292

src/parsetags.pl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,26 @@
8787
print "\n} CborKnownTags;";
8888

8989
print "\n==== search table ====\n";
90-
print "struct KnownTagData { uint32_t tag; };";
90+
print "struct KnownTagData { uint32_t tag; uint32_t types; };";
9191
printf "static const struct KnownTagData knownTagData[] = {";
9292
$comma = "";
9393
for my $n (@tagnumbers) {
9494
my @types = @{$tags{$n}{types}};
9595

9696
my $typemask;
9797
my $shift = 0;
98+
for my $type (@types) {
99+
die("Too many match types for tag $n") if $shift == 32;
100+
my $actualtype = "Cbor${type}Type";
101+
$actualtype = "($actualtype+1)" if $type eq "Integer";
102+
$typemask .= " | " if $typemask ne "";
103+
$typemask .= "((uint8_t)$actualtype << $shift)" if $shift;
104+
$typemask .= "(uint8_t)$actualtype" unless $shift;
105+
$shift += 8;
106+
}
107+
$typemask = "0U" if $typemask eq "";
98108

99-
printf "%s\n { %d }", $comma, $n;
109+
printf "%s\n { %d, %s }", $comma, $n, $typemask;
100110
$comma = ",";
101111
}
102112
print "\n};";

tests/parser/tst_parser.cpp

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,10 +1613,67 @@ void tst_Parser::strictValidation_data()
16131613

16141614
QTest::newRow("tag-0") << raw("\xc0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
16151615
QTest::newRow("tag-24") << raw("\xd8\x18\x40") << int(CborValidateCanonicalFormat) << CborNoError;
1616-
QTest::newRow("tag-55799") << raw("\xd9\xd9\xf7\x60") << int(CborValidateCanonicalFormat) << CborNoError;
16171616
QTest::newRow("tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
16181617
QTest::newRow("tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
16191618

1619+
// strict mode
1620+
QTest::newRow("tag-0-unsigned") << raw("\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1621+
QTest::newRow("tag-0-bytearray") << raw("\xc0\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1622+
QTest::newRow("tag-0-string") << raw("\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
1623+
QTest::newRow("tag-0-tag-0-string") << raw("\xc0\xc0\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1624+
QTest::newRow("tag-1-unsigned") << raw("\xc1\x00") << int(CborValidateStrictMode) << CborNoError;
1625+
QTest::newRow("tag-1-negative") << raw("\xc1\x20") << int(CborValidateStrictMode) << CborNoError;
1626+
QTest::newRow("tag-1-bytearray") << raw("\xc1\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1627+
QTest::newRow("tag-2-bytearray") << raw("\xc2\x40") << int(CborValidateStrictMode) << CborNoError;
1628+
QTest::newRow("tag-2-string") << raw("\xc2\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1629+
QTest::newRow("tag-3-bytearray") << raw("\xc3\x40") << int(CborValidateStrictMode) << CborNoError;
1630+
QTest::newRow("tag-3-string") << raw("\xc3\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1631+
QTest::newRow("tag-4-string") << raw("\xc4\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1632+
QTest::newRow("tag-4-array") << raw("\xc4\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
1633+
QTest::newRow("tag-5-string") << raw("\xc5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1634+
QTest::newRow("tag-5-array") << raw("\xc5\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
1635+
QTest::newRow("tag-21-bytearray") << raw("\xd5\x40") << int(CborValidateStrictMode) << CborNoError;
1636+
QTest::newRow("tag-21-string") << raw("\xd5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1637+
QTest::newRow("tag-21-array") << raw("\xd5\x80") << int(CborValidateStrictMode) << CborNoError;
1638+
QTest::newRow("tag-21-map") << raw("\xd5\xa0") << int(CborValidateStrictMode) << CborNoError;
1639+
QTest::newRow("tag-22-bytearray") << raw("\xd6\x40") << int(CborValidateStrictMode) << CborNoError;
1640+
QTest::newRow("tag-22-string") << raw("\xd6\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1641+
QTest::newRow("tag-22-array") << raw("\xd6\x80") << int(CborValidateStrictMode) << CborNoError;
1642+
QTest::newRow("tag-22-map") << raw("\xd6\xa0") << int(CborValidateStrictMode) << CborNoError;
1643+
QTest::newRow("tag-23-bytearray") << raw("\xd7\x40") << int(CborValidateStrictMode) << CborNoError;
1644+
QTest::newRow("tag-23-string") << raw("\xd7\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1645+
QTest::newRow("tag-23-array") << raw("\xd7\x80") << int(CborValidateStrictMode) << CborNoError;
1646+
QTest::newRow("tag-23-map") << raw("\xd7\xa0") << int(CborValidateStrictMode) << CborNoError;
1647+
QTest::newRow("tag-24-bytearray") << raw("\xd8\x18\x40") << int(CborValidateStrictMode) << CborNoError;
1648+
QTest::newRow("tag-24-string") << raw("\xd8\x18\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1649+
QTest::newRow("tag-32-bytearray") << raw("\xd8\x20\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1650+
QTest::newRow("tag-32-string") << raw("\xd8\x20\x60") << int(CborValidateStrictMode) << CborNoError;
1651+
QTest::newRow("tag-33-bytearray") << raw("\xd8\x21\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1652+
QTest::newRow("tag-33-string") << raw("\xd8\x21\x60") << int(CborValidateStrictMode) << CborNoError;
1653+
QTest::newRow("tag-34-bytearray") << raw("\xd8\x22\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1654+
QTest::newRow("tag-34-string") << raw("\xd8\x22\x60") << int(CborValidateStrictMode) << CborNoError;
1655+
QTest::newRow("tag-35-bytearray") << raw("\xd8\x23\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1656+
QTest::newRow("tag-35-string") << raw("\xd8\x23\x60") << int(CborValidateStrictMode) << CborNoError;
1657+
QTest::newRow("tag-36-bytearray") << raw("\xd8\x24\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1658+
QTest::newRow("tag-36-string") << raw("\xd8\x24\x60") << int(CborValidateStrictMode) << CborNoError;
1659+
QTest::newRow("tag-55799-unsigned") << raw("\xd9\xd9\xf7\x00") << int(CborValidateStrictMode) << CborNoError;
1660+
QTest::newRow("tag-55799-negative") << raw("\xd9\xd9\xf7\x20") << int(CborValidateStrictMode) << CborNoError;
1661+
QTest::newRow("tag-55799-bytearray") << raw("\xd9\xd9\xf7\x40") << int(CborValidateStrictMode) << CborNoError;
1662+
QTest::newRow("tag-55799-string") << raw("\xd9\xd9\xf7\x60") << int(CborValidateStrictMode) << CborNoError;
1663+
QTest::newRow("tag-55799-array") << raw("\xd9\xd9\xf7\x80") << int(CborValidateStrictMode) << CborNoError;
1664+
QTest::newRow("tag-55799-map") << raw("\xd9\xd9\xf7\xa0") << int(CborValidateStrictMode) << CborNoError;
1665+
QTest::newRow("tag-55799-tag-0-unsigned") << raw("\xd9\xd9\xf7\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
1666+
QTest::newRow("tag-55799-tag-0-string") << raw("\xd9\xd9\xf7\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
1667+
QTest::newRow("tag-55799-simple0") << raw("\xd9\xd9\xf7\xe0") << int(CborValidateStrictMode) << CborNoError;
1668+
QTest::newRow("tag-55799-false") << raw("\xd9\xd9\xf7\xf4") << int(CborValidateStrictMode) << CborNoError;
1669+
QTest::newRow("tag-55799-true") << raw("\xd9\xd9\xf7\xf5") << int(CborValidateStrictMode) << CborNoError;
1670+
QTest::newRow("tag-55799-null") << raw("\xd9\xd9\xf7\xf6") << int(CborValidateStrictMode) << CborNoError;
1671+
QTest::newRow("tag-55799-undefined") << raw("\xd9\xd9\xf7\xf7") << int(CborValidateStrictMode) << CborNoError;
1672+
QTest::newRow("tag-55799-simple32") << raw("\xd9\xd9\xf7\xf8\x20") << int(CborValidateStrictMode) << CborNoError;
1673+
QTest::newRow("tag-55799-half") << raw("\xd9\xd9\xf7\xf9\0\0") << int(CborValidateStrictMode) << CborNoError;
1674+
QTest::newRow("tag-55799-float") << raw("\xd9\xd9\xf7\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
1675+
QTest::newRow("tag-55799-double") << raw("\xd9\xd9\xf7\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
1676+
16201677
// excluded non-finite
16211678
QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
16221679
QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;

0 commit comments

Comments
 (0)