QCBOR: Improve handling of end of data and error; add indefinite length encoding
* Minor improvements / fixes in run_test framework
* Add CBOR indefinite length encoding
* Recheck pointer math in UsefulBuf and remove "TODO"
* Better error handling of not-well-formed CBOR when decoding
* Better handling of end of data when decoding
* Better handling of encode error when out of space in output buffer
Change-Id: Ib8dc2af95bc533b7905648d8f8c3b1bf1c42ba44
Signed-off-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/lib/ext/qcbor/test/float_tests.c b/lib/ext/qcbor/test/float_tests.c
index 4f12ca6..eaf75aa 100644
--- a/lib/ext/qcbor/test/float_tests.c
+++ b/lib/ext/qcbor/test/float_tests.c
@@ -73,7 +73,7 @@
UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
QCBORDecodeContext DC;
- QCBORDecode_Init(&DC, HalfPrecision, QCBOR_DECODE_MODE_NORMAL);
+ QCBORDecode_Init(&DC, HalfPrecision, 0);
QCBORItem Item;
@@ -194,7 +194,7 @@
// Now parse the hand-constructed CBOR. This will invoke the conversion to a float
QCBORDecodeContext DC;
- QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), QCBOR_DECODE_MODE_NORMAL);
+ QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
QCBORItem Item;
diff --git a/lib/ext/qcbor/test/not_well_formed_cbor.h b/lib/ext/qcbor/test/not_well_formed_cbor.h
new file mode 100644
index 0000000..d5bd233
--- /dev/null
+++ b/lib/ext/qcbor/test/not_well_formed_cbor.h
@@ -0,0 +1,325 @@
+/*==============================================================================
+ not_well_formed_cbor.h -- vectors to test for handling of not-well-formed CBOR
+
+ This is part of QCBOR -- https://github.com/laurencelundblade/QCBOR
+
+ Copyright (c) 2019, Laurence Lundblade. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+
+ See BSD-3-Clause license in README.md
+
+ Created on 7/27/19
+ ==============================================================================*/
+
+#ifndef not_well_formed_cbor_h
+#define not_well_formed_cbor_h
+
+#include <stdint.h> // for size_t and uint8_t
+
+
+struct someBinaryBytes {
+ const uint8_t *p; // Pointer to the bytes
+ size_t n; // Length of the bytes
+};
+
+
+static const struct someBinaryBytes paNotWellFormedCBOR[] = {
+
+ // Indefinite length strings must be closed off
+
+ // An indefinite length byte string not closed off
+ {(uint8_t[]){0x5f, 0x41, 0x00}, 3},
+ // An indefinite length text string not closed off
+ {(uint8_t[]){0x7f, 0x61, 0x00}, 3},
+
+
+ // All the chunks in an indefinite length string must be of the
+ // type of indefinite length string and indefinite
+
+ // indefinite length byte string with text string chunk
+ {(uint8_t[]){0x5f, 0x61, 0x00, 0xff}, 4},
+ // indefinite length text string with a byte string chunk
+ {(uint8_t[]){0x7f, 0x41, 0x00, 0xff}, 4},
+ // indefinite length byte string with an positive integer chunk
+ {(uint8_t[]){0x5f, 0x00, 0xff}, 3},
+ // indefinite length byte string with an negative integer chunk
+ {(uint8_t[]){0x5f, 0x21, 0xff}, 3},
+ // indefinite length byte string with an array chunk
+ {(uint8_t[]){0x5f, 0x80, 0xff}, 3},
+ // indefinite length byte string with an map chunk
+ {(uint8_t[]){0x5f, 0xa0, 0xff}, 3},
+ // indefinite length byte string with tagged integer chunk
+ {(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4},
+ // indefinite length byte string with an simple type chunk
+ {(uint8_t[]){0x5f, 0xe0, 0xff}, 3},
+ // indefinite length byte string with indefinite string inside
+ {(uint8_t[]){0x5f, 0x5f, 0x41, 0x00, 0xff, 0xff}, 6},
+ // indefinite length text string with indefinite string inside
+ {(uint8_t[]){0x7f, 0x7f, 0x61, 0x00, 0xff, 0xff}, 6},
+
+ // Definite length maps and arrays must be closed by having the
+ // right number of items
+
+ // A definite length array that is supposed to have 1 item, but has none
+ {(uint8_t[]){0x81}, 1},
+ // A definite length array that is supposed to have 2 items, but has only 1
+ {(uint8_t[]){0x82, 0x00}, 2},
+ // A definite length array that is supposed to have 511 items, but has only 1
+ {(uint8_t[]){0x9a, 0x01, 0xff, 0x00}, 4},
+ // A definite length map that is supposed to have 1 item, but has none
+ {(uint8_t[]){0xa1}, 1},
+ // A definite length map that is supposed to have s item, but has only 1
+ {(uint8_t[]){0xa2, 0x01, 0x02}, 3},
+
+
+ // Indefinite length maps and arrays must be ended by a break
+
+ // Indefinite length array with zero items and no break
+ {(uint8_t[]){0x9f}, 1},
+ // Indefinite length array with two items and no break
+ {(uint8_t[]){0x9f, 0x01, 0x02}, 3},
+ // Indefinite length map with zero items and no break
+ {(uint8_t[]){0xbf}, 1},
+ // Indefinite length map with two items and no break
+ {(uint8_t[]){0xbf, 0x01, 0x02, 0x01, 0x02}, 5},
+
+
+ // Some extra test vectors for unclosed arrays and maps
+
+ // Unclosed indefinite array containing a close definite array
+ {(uint8_t[]){0x9f, 0x80, 0x00}, 3},
+ // Definite length array containing an unclosed indefinite array
+ {(uint8_t[]){0x81, 0x9f}, 2},
+ // Deeply nested definite length arrays with deepest one unclosed
+ {(uint8_t[]){0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81}, 9},
+ // Deeply nested indefinite length arrays with deepest one unclosed
+ {(uint8_t[]){0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 9},
+ // Mixed nesting with indefinite unclosed
+ {(uint8_t[]){0x9f, 0x81, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff}, 9},
+ // Mixed nesting with definite unclosed
+ {(uint8_t[]){0x9f, 0x82, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 10},
+
+
+ // The "argument" for the data item is missing bytes
+
+ // Positive integer missing 1 byte argument
+ {(uint8_t[]){0x18}, 1},
+ // Positive integer missing 2 byte argument
+ {(uint8_t[]){0x19}, 1},
+ // Positive integer missing 4 byte argument
+ {(uint8_t[]){0x1a}, 1},
+ // Positive integer missing 8 byte argument
+ {(uint8_t[]){0x1b}, 1},
+ // Positive integer missing 1 byte of 2 byte argument
+ {(uint8_t[]){0x19, 0x01}, 2},
+ // Positive integer missing 2 bytes of 4 byte argument
+ {(uint8_t[]){0x1a, 0x01, 0x02}, 3},
+ // Positive integer missing 1 bytes of 7 byte argument
+ {(uint8_t[]){0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 8},
+ // Negative integer missing 1 byte argument
+ {(uint8_t[]){0x38}, 1},
+ // Binary string missing 1 byte argument
+ {(uint8_t[]){0x58}, 1},
+ // Text string missing 1 byte argument
+ {(uint8_t[]){0x78}, 1},
+ // Array missing 1 byte argument
+ {(uint8_t[]){0x98}, 1},
+ // Map missing 1 byte argument
+ {(uint8_t[]){0xb8}, 1},
+ // Tag missing 1 byte argument
+ {(uint8_t[]){0xd8}, 1},
+ // Simple missing 1 byte argument
+ {(uint8_t[]){0xf8}, 1},
+ // Half-precision missing 1 byte
+ {(uint8_t[]){0xf9, 0x00}, 2},
+ // Float missing 2 bytes
+ {(uint8_t[]){0xfa, 0x00, 0x00}, 3},
+ // Double missing 5 bytes
+ {(uint8_t[]){0xfb, 0x00, 0x00, 0x00}, 4},
+
+ // Breaks must not occur in definite length arrays and maps
+
+ // Array of length 1 with sole member replaced by a break
+ {(uint8_t[]){0x81, 0xff}, 2},
+ // Array of length 2 with 2nd member replaced by a break
+ {(uint8_t[]){0x82, 0x00, 0xff}, 3},
+ // Map of length 1 with sole member label replaced by a break
+ {(uint8_t[]){0xa1, 0xff}, 2},
+ // Map of length 1 with sole member label replaced by break
+ // Alternate representation that some decoders handle difference
+ {(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},
+
+
+ // Breaks must not occur on their own out of an indefinite length
+ // data item
+
+ // A bare break is not well formed
+ {(uint8_t[]){0xff}, 1},
+ // A bare break after a zero length definite length array
+ {(uint8_t[]){0x80, 0xff}, 2},
+ // A bare break after a zero length indefinite length map
+ {(uint8_t[]){0x9f, 0xff, 0xff}, 3},
+
+
+ // Forbidden two-byte encodings of simple types
+
+ // Must use 0xe0 instead
+ {(uint8_t[]){0xf8, 0x00}, 2},
+ // Should use 0xe1 instead
+ {(uint8_t[]){0xf8, 0x01}, 2},
+ // Should use 0xe2 instead
+ {(uint8_t[]){0xf8, 0x02}, 2},
+ // Should use 0xe3 instead
+ {(uint8_t[]){0xf8, 0x03}, 2},
+ // Should use 0xe4 instead
+ {(uint8_t[]){0xf8, 0x04}, 2},
+ // Should use 0xe5 instead
+ {(uint8_t[]){0xf8, 0x05}, 2},
+ // Should use 0xe6 instead
+ {(uint8_t[]){0xf8, 0x06}, 2},
+ // Should use 0xe7 instead
+ {(uint8_t[]){0xf8, 0x07}, 2},
+ // Should use 0xe8 instead
+ {(uint8_t[]){0xf8, 0x08}, 2},
+ // Should use 0xe9 instead
+ {(uint8_t[]){0xf8, 0x09}, 2},
+ // Should use 0xea instead
+ {(uint8_t[]){0xf8, 0x0a}, 2},
+ // Should use 0xeb instead
+ {(uint8_t[]){0xf8, 0x0b}, 2},
+ // Should use 0xec instead
+ {(uint8_t[]){0xf8, 0x0c}, 2},
+ // Should use 0xed instead
+ {(uint8_t[]){0xf8, 0x0d}, 2},
+ // Should use 0xee instead
+ {(uint8_t[]){0xf8, 0x0e}, 2},
+ // Should use 0xef instead
+ {(uint8_t[]){0xf8, 0x0f}, 2},
+ // Should use 0xf0 instead
+ {(uint8_t[]){0xf8, 0x10}, 2},
+ // Should use 0xf1 instead
+ {(uint8_t[]){0xf8, 0x11}, 2},
+ // Should use 0xf2 instead
+ {(uint8_t[]){0xf8, 0x12}, 2},
+ // Must use 0xf3 instead
+ {(uint8_t[]){0xf8, 0x13}, 2},
+ // Must use 0xf4 instead
+ {(uint8_t[]){0xf8, 0x14}, 2},
+ // Must use 0xf5 instead
+ {(uint8_t[]){0xf8, 0x15}, 2},
+ // Must use 0xf6 instead
+ {(uint8_t[]){0xf8, 0x16}, 2},
+ // Must use 0xf7 instead
+ {(uint8_t[]){0xf8, 0x17}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x18}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x19}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x1a}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x1b}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x1c}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x1d}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x1e}, 2},
+ // Reserved (as defined in RFC 8126), considered not-well-formed
+ {(uint8_t[]){0xf8, 0x1f}, 2},
+
+ // Integers with "argument" equal to an indefinite length
+
+ // Positive integer with "argument" an indefinite length
+ {(uint8_t[]){0x1f}, 1},
+ // Negative integer with "argument" an indefinite length
+ {(uint8_t[]){0x3f}, 1},
+ // CBOR tag with "argument" an indefinite length
+ {(uint8_t[]){0xdf, 0x00}, 2},
+ // CBOR tag with "argument" an indefinite length alternate vector
+ {(uint8_t[]){0xdf}, 1},
+
+
+ // Missing content bytes from a definite length string
+
+ // A byte string is of length 1 without the 1 byte
+ {(uint8_t[]){0x41}, 1},
+ // A text string is of length 1 without the 1 byte
+ {(uint8_t[]){0x61}, 1},
+ // Byte string should have 2^32-1 bytes, but has one
+ {(uint8_t[]){0x5a, 0xff, 0xff, 0xff, 0xff, 0x00}, 6},
+ // Byte string should have 2^32-1 bytes, but has one
+ {(uint8_t[]){0x7a, 0xff, 0xff, 0xff, 0xff, 0x00}, 6},
+
+
+ // Use of unassigned additional information values
+
+ // Major type positive integer with reserved value 28
+ {(uint8_t[]){0x1c}, 1},
+ // Major type positive integer with reserved value 29
+ {(uint8_t[]){0x1d}, 1},
+ // Major type positive integer with reserved value 30
+ {(uint8_t[]){0x1e}, 1},
+ // Major type negative integer with reserved value 28
+ {(uint8_t[]){0x3c}, 1},
+ // Major type negative integer with reserved value 29
+ {(uint8_t[]){0x3d}, 1},
+ // Major type negative integer with reserved value 30
+ {(uint8_t[]){0x3e}, 1},
+ // Major type byte string with reserved value 28 length
+ {(uint8_t[]){0x5c}, 1},
+ // Major type byte string with reserved value 29 length
+ {(uint8_t[]){0x5d}, 1},
+ // Major type byte string with reserved value 30 length
+ {(uint8_t[]){0x5e}, 1},
+ // Major type text string with reserved value 28 length
+ {(uint8_t[]){0x7c}, 1},
+ // Major type text string with reserved value 29 length
+ {(uint8_t[]){0x7d}, 1},
+ // Major type text string with reserved value 30 length
+ {(uint8_t[]){0x7e}, 1},
+ // Major type array with reserved value 28 length
+ {(uint8_t[]){0x9c}, 1},
+ // Major type array with reserved value 29 length
+ {(uint8_t[]){0x9d}, 1},
+ // Major type array with reserved value 30 length
+ {(uint8_t[]){0x9e}, 1},
+ // Major type map with reserved value 28 length
+ {(uint8_t[]){0xbc}, 1},
+ // Major type map with reserved value 29 length
+ {(uint8_t[]){0xbd}, 1},
+ // Major type map with reserved value 30 length
+ {(uint8_t[]){0xbe}, 1},
+ // Major type tag with reserved value 28 length
+ {(uint8_t[]){0xdc}, 1},
+ // Major type tag with reserved value 29 length
+ {(uint8_t[]){0xdd}, 1},
+ // Major type tag with reserved value 30 length
+ {(uint8_t[]){0xde}, 1},
+ // Major type simple with reserved value 28 length
+ {(uint8_t[]){0xfc}, 1},
+ // Major type simple with reserved value 29 length
+ {(uint8_t[]){0xfd}, 1},
+ // Major type simple with reserved value 30 length
+ {(uint8_t[]){0xfe}, 1},
+
+
+ // Maps must have an even number of data items (key & value)
+
+ // Map with 1 item when it should have 2
+ {(uint8_t[]){0xa1, 0x00}, 2},
+ // Map with 3 item when it should have 4
+ {(uint8_t[]){0xa2, 0x00, 0x00, 0x00}, 2},
+ // Map with 1 item when it should have 2
+ {(uint8_t[]){0xbf, 0x00, 0xff}, 3},
+ // Map with 3 item when it should have 4
+ {(uint8_t[]){0xbf, 0x00, 0x00, 0x00, 0xff}, 5},
+
+};
+
+#endif /* not_well_formed_cbor_h */
diff --git a/lib/ext/qcbor/test/qcbor_decode_tests.c b/lib/ext/qcbor/test/qcbor_decode_tests.c
index 680c86b..7de8c6c 100644
--- a/lib/ext/qcbor/test/qcbor_decode_tests.c
+++ b/lib/ext/qcbor/test/qcbor_decode_tests.c
@@ -34,6 +34,7 @@
#include "qcbor.h"
#include <string.h>
#include <math.h> // for fabs()
+#include "not_well_formed_cbor.h"
#ifdef PRINT_FUNCTIONS_FOR_DEBUGGING
@@ -418,21 +419,43 @@
}
+// The largest negative int possible in CBOR.
+// Not possible in C.
+static const uint8_t spTooBigNegative[] = {
+ 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
/*
Tests the decoding of lots of different integers sizes
and values.
*/
-
int IntegerValuesParseTest()
{
- int n;
+ int nReturn;
QCBORDecodeContext DCtx;
- QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts), QCBOR_DECODE_MODE_NORMAL);
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts),
+ QCBOR_DECODE_MODE_NORMAL);
- n = IntegerValuesParseTestInternal(&DCtx);
+ // The really big test of all successes
+ nReturn = IntegerValuesParseTestInternal(&DCtx);
+ if(nReturn) {
+ return nReturn;
+ }
- return(n);
+ // The one large negative integer that can be parsed
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooBigNegative),
+ QCBOR_DECODE_MODE_NORMAL);
+
+ QCBORItem item;
+ if(QCBORDecode_GetNext(&DCtx, &item) != QCBOR_ERR_INT_OVERFLOW) {
+ nReturn = -4000;
+ }
+
+ return(nReturn);
}
@@ -592,6 +615,149 @@
}
+/*
+ [
+ 0,
+ [],
+ [
+ [],
+ [
+ 0
+ ],
+ {},
+ {
+ 1: {},
+ 2: {},
+ 3: []
+ }
+ ]
+ ]
+ */
+static uint8_t sEmpties[] = {0x83, 0x00, 0x80, 0x84, 0x80, 0x81, 0x00, 0xa0,
+ 0xa3, 0x01, 0xa0, 0x02, 0xa0, 0x03, 0x80};
+
+int EmptyMapsAndArraysTest()
+{
+ QCBORDecodeContext DCtx;
+ QCBORItem Item;
+
+ QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmpties), QCBOR_DECODE_MODE_NORMAL);
+
+ // Array with 3 items
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_ARRAY ||
+ Item.uNestingLevel != 0 ||
+ Item.uNextNestLevel != 1 ||
+ Item.val.uCount != 3) {
+ return -1;
+ }
+
+ // An integer 0
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_INT64 ||
+ Item.uNestingLevel != 1 ||
+ Item.uNextNestLevel != 1 ||
+ Item.val.uint64 != 0) {
+ return -2;
+ }
+
+ // An empty array
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_ARRAY ||
+ Item.uNestingLevel != 1 ||
+ Item.uNextNestLevel != 1 ||
+ Item.val.uCount != 0) {
+ return -3;
+ }
+
+ // An array with 4 items
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_ARRAY ||
+ Item.uNestingLevel != 1 ||
+ Item.uNextNestLevel != 2 ||
+ Item.val.uCount != 4) {
+ return -4;
+ }
+
+ // An empty array
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_ARRAY ||
+ Item.uNestingLevel != 2 ||
+ Item.uNextNestLevel != 2 ||
+ Item.val.uCount != 0) {
+ return -5;
+ }
+
+ // An array with 1 item
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_ARRAY ||
+ Item.uNestingLevel != 2 ||
+ Item.uNextNestLevel != 3 ||
+ Item.val.uCount != 1) {
+ return -6;
+ }
+
+ // An integer 0
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_INT64 ||
+ Item.uNestingLevel != 3 ||
+ Item.uNextNestLevel != 2 ||
+ Item.val.uint64 != 0) {
+ return -7;
+ }
+
+ // An empty map
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_MAP ||
+ Item.uNestingLevel != 2 ||
+ Item.uNextNestLevel != 2 ||
+ Item.val.uCount != 0) {
+ return -8;
+ }
+
+ // An map with 3 items
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_MAP ||
+ Item.uNestingLevel != 2 ||
+ Item.uNextNestLevel != 3 ||
+ Item.val.uCount != 3) {
+ return -9;
+ }
+
+ // An empty map
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_MAP ||
+ Item.uNestingLevel != 3 ||
+ Item.uNextNestLevel != 3 ||
+ Item.val.uCount != 0) {
+ return -10;
+ }
+
+ // An empty map
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_MAP ||
+ Item.uNestingLevel != 3 ||
+ Item.uNextNestLevel != 3 ||
+ Item.val.uCount != 0) {
+ return -11;
+ }
+
+ // An empty array
+ if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+ Item.uDataType != QCBOR_TYPE_ARRAY ||
+ Item.uNestingLevel != 3 ||
+ Item.uNextNestLevel != 0 ||
+ Item.val.uCount != 0) {
+ return -12;
+ }
+
+ if(QCBORDecode_Finish(&DCtx) != QCBOR_SUCCESS) {
+ return -13;
+ }
+
+ return 0;
+}
+
static uint8_t spDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
@@ -654,20 +820,16 @@
int ShortBufferParseTest()
{
- int nResult = 0;
- QCBORDecodeContext DCtx;
- int num;
+ int nResult = 0;
- for(num = sizeof(spExpectedEncodedInts)-1; num; num--) {
- int n;
+ for(int nNum = sizeof(spExpectedEncodedInts)-1; nNum; nNum--) {
+ QCBORDecodeContext DCtx;
- QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL);
+ QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, nNum}, QCBOR_DECODE_MODE_NORMAL);
- n = IntegerValuesParseTestInternal(&DCtx);
+ const QCBORError nErr = IntegerValuesParseTestInternal(&DCtx);
- //printf("Len %d, result: %d\n", num, n);
-
- if(n != QCBOR_ERR_HIT_END) {
+ if(nErr != QCBOR_ERR_HIT_END && nErr != QCBOR_ERR_NO_MORE_ITEMS) {
nResult = -1;
goto Done;
}
@@ -1329,86 +1491,401 @@
}
+static int IsNotWellFormedError(QCBORError nErr)
+{
+ switch(nErr){
+ case QCBOR_ERR_INDEFINITE_STRING_CHUNK:
+ case QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN:
+ case QCBOR_ERR_UNSUPPORTED:
+ case QCBOR_ERR_HIT_END:
+ case QCBOR_ERR_BAD_TYPE_7:
+ case QCBOR_ERR_BAD_BREAK:
+ case QCBOR_ERR_EXTRA_BYTES:
+ case QCBOR_ERR_BAD_INT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+int NotWellFormedTests()
+{
+ // Loop over all the not-well-formed instance of CBOR
+ // that are test vectors in not_well_formed_cbor.h
+ const uint16_t nArraySize = sizeof(paNotWellFormedCBOR)/sizeof(struct someBinaryBytes);
+ for(uint16_t nIterate = 0; nIterate < nArraySize; nIterate++) {
+ const struct someBinaryBytes *pBytes = &paNotWellFormedCBOR[nIterate];
+ const UsefulBufC Input = (UsefulBufC){pBytes->p, pBytes->n};
+
+ // Set up decoder context. String allocator needed for indefinite string test cases
+ QCBORDecodeContext DCtx;
+ QCBORDecode_Init(&DCtx, Input, QCBOR_DECODE_MODE_NORMAL);
+ UsefulBuf_MAKE_STACK_UB(Pool, 100);
+ QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+
+ // Loop getting items until no more to get
+ QCBORError nCBORError;
+ do {
+ QCBORItem Item;
+
+ nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
+ } while(nCBORError == QCBOR_SUCCESS);
+
+ // Every test vector must fail with
+ // a not-well-formed error. If not
+ // this test fails.
+ if(!IsNotWellFormedError(nCBORError)) {
+ // Return index of failure in the error code
+ return 2000 + nIterate;
+ }
+ }
+ return 0;
+}
+
+
struct FailInput {
- UsefulBufC Input;
- int nError;
+ UsefulBufC Input; // CBOR to decode
+ QCBORError nError; // The error expected
};
-
struct FailInput Failures[] = {
- { {(uint8_t[]){0x18}, 1}, QCBOR_ERR_HIT_END }, // 1 byte integer missing the byte
- { {(uint8_t[]){0x1c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
- { {(uint8_t[]){0x1d}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 29
- { {(uint8_t[]){0x1e}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 30
- { {(uint8_t[]){0x1f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length integer
- { {(uint8_t[]){0x3c}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte
- { {(uint8_t[]){0x3d}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte
- { {(uint8_t[]){0x3e}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte
- { {(uint8_t[]){0x3f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length negative integer
- { {(uint8_t[]){0x41}, 1}, QCBOR_ERR_HIT_END }, // Short byte string
- { {(uint8_t[]){0x5c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
- { {(uint8_t[]){0x5f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length byte string
- { {(uint8_t[]){0x61}, 1}, QCBOR_ERR_HIT_END }, // Short UTF-8 string
- { {(uint8_t[]){0x7c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
- { {(uint8_t[]){0x7f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length UTF-8 string
- { {(uint8_t[]){0xff}, 1}, QCBOR_ERR_UNSUPPORTED } , // break
- { {(uint8_t[]){0xf8, 0x00}, 2}, QCBOR_ERR_BAD_TYPE_7 }, // An invalid encoding of a simple type
- { {(uint8_t[]){0xf8, 0x1f}, 2}, QCBOR_ERR_BAD_TYPE_7 }, // An invalid encoding of a simple type
+ // Most of this is copied from not_well_formed.h. Here the error code
+ // returned is also checked.
+
+ // Indefinite length strings must be closed off
+ // An indefinite length byte string not closed off
+ { {(uint8_t[]){0x5f, 0x41, 0x00}, 3}, QCBOR_ERR_HIT_END },
+ // An indefinite length text string not closed off
+ { {(uint8_t[]){0x7f, 0x61, 0x00}, 3}, QCBOR_ERR_HIT_END },
+
+
+ // All the chunks in an indefinite length string must be of the type of indefinite length string
+ // indefinite length byte string with text string chunk
+ { {(uint8_t[]){0x5f, 0x61, 0x00, 0xff}, 4}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length text string with a byte string chunk
+ { {(uint8_t[]){0x7f, 0x41, 0x00, 0xff}, 4}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length byte string with an positive integer chunk
+ { {(uint8_t[]){0x5f, 0x00, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length byte string with an negative integer chunk
+ { {(uint8_t[]){0x5f, 0x21, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length byte string with an array chunk
+ { {(uint8_t[]){0x5f, 0x80, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length byte string with an map chunk
+ { {(uint8_t[]){0x5f, 0xa0, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length byte string with tagged integer chunk
+ { {(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ // indefinite length byte string with an simple type chunk
+ { {(uint8_t[]){0x5f, 0xe0, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK },
+ { {(uint8_t[]){0x5f, 0x5f, 0x41, 0x00, 0xff, 0xff}, 6}, QCBOR_ERR_INDEFINITE_STRING_CHUNK},
+ // indefinite length text string with indefinite string inside
+ { {(uint8_t[]){0x7f, 0x7f, 0x61, 0x00, 0xff, 0xff}, 6}, QCBOR_ERR_INDEFINITE_STRING_CHUNK},
+
+
+ // Definte length maps and arrays must be closed by having the right number of items
+ // A definte length array that is supposed to have 1 item, but has none
+ { {(uint8_t[]){0x81}, 1}, QCBOR_ERR_HIT_END },
+ // A definte length array that is supposed to have 2 items, but has only 1
+ { {(uint8_t[]){0x82, 0x00}, 2}, QCBOR_ERR_HIT_END },
+ // A definte length array that is supposed to have 511 items, but has only 1
+ { {(uint8_t[]){0x9a, 0x01, 0xff, 0x00}, 4}, QCBOR_ERR_HIT_END },
+ // A definte length map that is supposed to have 1 item, but has none
+ { {(uint8_t[]){0xa1}, 1}, QCBOR_ERR_HIT_END },
+ // A definte length map that is supposed to have s item, but has only 1
+ { {(uint8_t[]){0xa2, 0x01, 0x02}, 3}, QCBOR_ERR_HIT_END },
+
+
+ // Indefinte length maps and arrays must be ended by a break
+ // Indefinite length array with zero items and no break
+ { {(uint8_t[]){0x9f}, 1}, QCBOR_ERR_HIT_END },
+ // Indefinite length array with two items and no break
+ { {(uint8_t[]){0x9f, 0x01, 0x02}, 3}, QCBOR_ERR_HIT_END },
+ // Indefinite length map with zero items and no break
+ { {(uint8_t[]){0xbf}, 1}, QCBOR_ERR_HIT_END },
+ // Indefinite length map with two items and no break
+ { {(uint8_t[]){0xbf, 0x01, 0x02, 0x01, 0x02}, 5}, QCBOR_ERR_HIT_END },
+
+
+ // Nested maps and arrays must be closed off (some extra nested test vectors)
+ // Unclosed indefinite array containing a close definite array
+ { {(uint8_t[]){0x9f, 0x80, 0x00}, 3}, QCBOR_ERR_HIT_END },
+ // Definite length array containing an unclosed indefinite array
+ { {(uint8_t[]){0x81, 0x9f}, 2}, QCBOR_ERR_HIT_END },
+ // Deeply nested definite length arrays with deepest one unclosed
+ { {(uint8_t[]){0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81}, 9}, QCBOR_ERR_HIT_END },
+ // Deeply nested indefinite length arrays with deepest one unclosed
+ { {(uint8_t[]){0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 9}, QCBOR_ERR_HIT_END },
+ // Mixed nesting with indefinite unclosed
+ { {(uint8_t[]){0x9f, 0x81, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff}, 9}, QCBOR_ERR_BAD_BREAK }, // TODO: think through this one
+ // Mixed nesting with definite unclosed
+ { {(uint8_t[]){0x9f, 0x82, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 10}, QCBOR_ERR_BAD_BREAK }, // TODO: think through this one
+
+
+ // The "argument" for the data item is incomplete
+ // Positive integer missing 1 byte argument
+ { {(uint8_t[]){0x18}, 1}, QCBOR_ERR_HIT_END },
+ // Positive integer missing 2 byte argument
+ { {(uint8_t[]){0x19}, 1}, QCBOR_ERR_HIT_END },
+ // Positive integer missing 4 byte argument
+ { {(uint8_t[]){0x1a}, 1}, QCBOR_ERR_HIT_END },
+ // Positive integer missing 8 byte argument
+ { {(uint8_t[]){0x1b}, 1}, QCBOR_ERR_HIT_END },
+ // Positive integer missing 1 byte of 2 byte argument
+ { {(uint8_t[]){0x19, 0x01}, 2}, QCBOR_ERR_HIT_END },
+ // Positive integer missing 2 bytes of 4 byte argument
+ { {(uint8_t[]){0x1a, 0x01, 0x02}, 3}, QCBOR_ERR_HIT_END },
+ // Positive integer missing 1 bytes of 7 byte argument
+ { {(uint8_t[]){0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 8}, QCBOR_ERR_HIT_END },
+ // Negative integer missing 1 byte argument
+ { {(uint8_t[]){0x38}, 1}, QCBOR_ERR_HIT_END },
+ // Binary string missing 1 byte argument
+ { {(uint8_t[]){0x58}, 1}, QCBOR_ERR_HIT_END },
+ // Text string missing 1 byte argument
+ { {(uint8_t[]){0x78}, 1}, QCBOR_ERR_HIT_END },
+ // Array missing 1 byte argument
+ { {(uint8_t[]){0x98}, 1}, QCBOR_ERR_HIT_END },
+ // Map missing 1 byte argument
+ { {(uint8_t[]){0xb8}, 1}, QCBOR_ERR_HIT_END },
+ // Tag missing 1 byte argument
+ { {(uint8_t[]){0xd8}, 1}, QCBOR_ERR_HIT_END },
+ // Simple missing 1 byte argument
+ { {(uint8_t[]){0xf8}, 1}, QCBOR_ERR_HIT_END },
+
+
+ // Breaks must not occur in definite length arrays and maps
+ // Array of length 1 with sole member replaced by a break
+ { {(uint8_t[]){0x81, 0xff}, 2}, QCBOR_ERR_BAD_BREAK },
+ // Array of length 2 with 2nd member replaced by a break
+ { {(uint8_t[]){0x82, 0x00, 0xff}, 3}, QCBOR_ERR_BAD_BREAK },
+ // Map of length 1 with sole member label replaced by a break
+ { {(uint8_t[]){0xa1, 0xff}, 2}, QCBOR_ERR_BAD_BREAK },
+ // Map of length 1 with sole member label replaced by break
+ // Alternate representation that some decoders handle difference
+ { {(uint8_t[]){0xa1, 0xff, 0x00}, 3}, QCBOR_ERR_BAD_BREAK },
+ // Array of length 1 with 2nd member value replaced by a break
+ { {(uint8_t[]){0xa1, 0x00, 0xff}, 3}, QCBOR_ERR_BAD_BREAK },
+ // Map of length 2 with 2nd member replaced by a break
+ { {(uint8_t[]){0xa2, 0x00, 0x00, 0xff}, 4}, QCBOR_ERR_BAD_BREAK },
+
+
+ // Breaks must not occur on their own out of an indefinite length data item
+ // A bare break is not well formed
+ { {(uint8_t[]){0xff}, 1}, QCBOR_ERR_BAD_BREAK },
+ // A bare break after a zero length definite length array
+ { {(uint8_t[]){0x80, 0xff}, 2}, QCBOR_ERR_BAD_BREAK },
+ // A bare break after a zero length indefinite length map
+ { {(uint8_t[]){0x9f, 0xff, 0xff}, 3}, QCBOR_ERR_BAD_BREAK },
+
+
+ // Forbidden two byte encodings of simple types
+ // Must use 0xe0 instead
+ { {(uint8_t[]){0xf8, 0x00}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe1 instead
+ { {(uint8_t[]){0xf8, 0x01}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe2 instead
+ { {(uint8_t[]){0xf8, 0x02}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe3 instead
+ { {(uint8_t[]){0xf8, 0x03}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe4 instead
+ { {(uint8_t[]){0xf8, 0x04}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe5 instead
+ { {(uint8_t[]){0xf8, 0x05}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe6 instead
+ { {(uint8_t[]){0xf8, 0x06}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe7 instead
+ { {(uint8_t[]){0xf8, 0x07}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe8 instead
+ { {(uint8_t[]){0xf8, 0x08}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xe9 instead
+ { {(uint8_t[]){0xf8, 0x09}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xea instead
+ { {(uint8_t[]){0xf8, 0x0a}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xeb instead
+ { {(uint8_t[]){0xf8, 0x0b}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xec instead
+ { {(uint8_t[]){0xf8, 0x0c}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xed instead
+ { {(uint8_t[]){0xf8, 0x0d}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xee instead
+ { {(uint8_t[]){0xf8, 0x0e}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xef instead
+ { {(uint8_t[]){0xf8, 0x0f}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xf0 instead
+ { {(uint8_t[]){0xf8, 0x10}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xf1 instead
+ { {(uint8_t[]){0xf8, 0x11}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Should use 0xf2 instead
+ { {(uint8_t[]){0xf8, 0x12}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Must use 0xf3 instead
+ { {(uint8_t[]){0xf8, 0x13}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Must use 0xf4 instead
+ { {(uint8_t[]){0xf8, 0x14}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Must use 0xf5 instead
+ { {(uint8_t[]){0xf8, 0x15}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Must use 0xf6 instead
+ { {(uint8_t[]){0xf8, 0x16}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Must use 0xf7 instead
+ { {(uint8_t[]){0xf8, 0x17}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+ // Must use 0xf8 instead
+ { {(uint8_t[]){0xf8, 0x18}, 2}, QCBOR_ERR_BAD_TYPE_7 },
+
+
+ // Integers with additional info indefinite length
+ // Positive integer with additional info indefinite length
+ { {(uint8_t[]){0x1f}, 1}, QCBOR_ERR_BAD_INT },
+ // Negative integer with additional info indefinite length
+ { {(uint8_t[]){0x3f}, 1}, QCBOR_ERR_BAD_INT },
+ // CBOR tag with "argument" an indefinite length
+ { {(uint8_t[]){0xdf, 0x00}, 2}, QCBOR_ERR_BAD_INT },
+ // CBOR tag with "argument" an indefinite length alternate vector
+ { {(uint8_t[]){0xdf}, 1}, QCBOR_ERR_BAD_INT },
+
+
+ // Missing bytes from a deterministic length string
+ // A byte string is of length 1 without the 1 byte
+ { {(uint8_t[]){0x41}, 1}, QCBOR_ERR_HIT_END },
+ // A text string is of length 1 without the 1 byte
+ { {(uint8_t[]){0x61}, 1}, QCBOR_ERR_HIT_END },
+ // Byte string should have 2^32-1 bytes, but has one
+ { {(uint8_t[]){0x5a, 0xff, 0xff, 0xff, 0xff, 0x00}, 6}, QCBOR_ERR_HIT_END },
+ // Byte string should have 2^32-1 bytes, but has one
+ { {(uint8_t[]){0x7a, 0xff, 0xff, 0xff, 0xff, 0x00}, 6}, QCBOR_ERR_HIT_END },
+
+
+ // Use of unassigned additional information values
+ // Major type positive integer with reserved value 28
+ { {(uint8_t[]){0x1c}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type positive integer with reserved value 29
+ { {(uint8_t[]){0x1d}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type positive integer with reserved value 30
+ { {(uint8_t[]){0x1e}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type negative integer with reserved value 28
+ { {(uint8_t[]){0x3c}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type negative integer with reserved value 29
+ { {(uint8_t[]){0x3d}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type negative integer with reserved value 30
+ { {(uint8_t[]){0x3e}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type byte string with reserved value 28 length
+ { {(uint8_t[]){0x5c}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type byte string with reserved value 29 length
+ { {(uint8_t[]){0x5d}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type byte string with reserved value 30 length
+ { {(uint8_t[]){0x5e}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type text string with reserved value 28 length
+ { {(uint8_t[]){0x7c}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type text string with reserved value 29 length
+ { {(uint8_t[]){0x7d}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type text string with reserved value 30 length
+ { {(uint8_t[]){0x7e}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type array with reserved value 28 length
+ { {(uint8_t[]){0x9c}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type array with reserved value 29 length
+ { {(uint8_t[]){0x9d}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type array with reserved value 30 length
+ { {(uint8_t[]){0x9e}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type map with reserved value 28 length
+ { {(uint8_t[]){0xbc}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type map with reserved value 29 length
+ { {(uint8_t[]){0xbd}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type map with reserved value 30 length
+ { {(uint8_t[]){0xbe}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type tag with reserved value 28 length
+ { {(uint8_t[]){0xdc}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type tag with reserved value 29 length
+ { {(uint8_t[]){0xdd}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type tag with reserved value 30 length
+ { {(uint8_t[]){0xde}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type simple with reserved value 28 length
+ { {(uint8_t[]){0xfc}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type simple with reserved value 29 length
+ { {(uint8_t[]){0xfd}, 1}, QCBOR_ERR_UNSUPPORTED },
+ // Major type simple with reserved value 30 length
+ { {(uint8_t[]){0xfe}, 1}, QCBOR_ERR_UNSUPPORTED },
+
+
+ // Maps must have an even number of data items (key & value)
+ // Map with 1 item when it should have 2
+ { {(uint8_t[]){0xa1, 0x00}, 2}, QCBOR_ERR_HIT_END },
+ // Map with 3 item when it should have 4
+ { {(uint8_t[]){0xa2, 0x00, 0x00, 0x00}, 2}, QCBOR_ERR_HIT_END },
+ // Map with 1 item when it should have 2
+ { {(uint8_t[]){0xbf, 0x00, 0xff}, 3}, QCBOR_ERR_BAD_BREAK },
+ // Map with 3 item when it should have 4
+ { {(uint8_t[]){0xbf, 0x00, 0x00, 0x00, 0xff}, 5}, QCBOR_ERR_BAD_BREAK },
+
+
+ // In addition to not-well-formed, some invalid CBOR
{ {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, // Text-based date, with an integer
{ {(uint8_t[]){0xc1, 0x41, 0x33}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // Epoch date, with an byte string
{ {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // tagged as both epoch and string dates
- { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG } // big num tagged an int, not a byte string
-
+ { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, // big num tagged an int, not a byte string
};
-
-int FailureTests()
+int DecodeFailureTests()
{
- int nResult = 0;
+ // Loop over the failures
+ const struct FailInput * const pFEnd = &Failures[0] +
+ sizeof(Failures)/sizeof(struct FailInput);
+ for(const struct FailInput *pF = &Failures[0]; pF < pFEnd ;pF++) {
- struct FailInput *pFEnd = &Failures[0] + sizeof(Failures)/sizeof(struct FailInput);
-
- for(struct FailInput *pF = &Failures[0]; pF < pFEnd ;pF++) {
+ // Set up the decoding context including a memory pool so that
+ // indefinite length items can be checked
QCBORDecodeContext DCtx;
- QCBORItem Item;
- int nCBORError;
-
QCBORDecode_Init(&DCtx, pF->Input, QCBOR_DECODE_MODE_NORMAL);
+ UsefulBuf_MAKE_STACK_UB(Pool, 100);
+ QCBORError nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+ if(nCBORError) {
+ return -9;
+ }
- while(1) {
+ // Iterate until there is an error of some sort error
+ QCBORItem Item;
+ do {
+ // Set to something none-zero other than QCBOR_TYPE_NONE
+ memset(&Item, 0x33, sizeof(Item));
+
nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
- if(QCBOR_ERR_HIT_END == nCBORError) {
- break;
- }
- if(nCBORError != pF->nError) {
- nResult = 1;
- break;
- }
+ } while(nCBORError == QCBOR_SUCCESS);
+
+ // Must get the expected error or the this test fails
+ // The data and label type must also be QCBOR_TYPE_NONE
+ if(nCBORError != pF->nError ||
+ Item.uDataType != QCBOR_TYPE_NONE ||
+ Item.uLabelType != QCBOR_TYPE_NONE) {
+ // return index of CBOR + 1000
+ return 1000 + (int)(pF - &Failures[0]);
}
}
+ // Corrupt the UsefulInputBuf and see that
+ // it reflected correctly for CBOR decoding
{
QCBORDecodeContext DCtx;
- QCBORItem Item;
- int nCBORError;
+ QCBORItem Item;
+ QCBORError nCBORError;
- QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL);
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues),
+ QCBOR_DECODE_MODE_NORMAL);
if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
return nCBORError;
if(Item.uDataType != QCBOR_TYPE_ARRAY ||
- Item.val.uCount != 10)
+ Item.val.uCount != 10) {
+ // This wasn't supposed to happen
return -1;
+ }
- DCtx.InBuf.magic = 0; // Corrupt the UsefulInputBuf
+ DCtx.InBuf.magic = 0; // Reach in and corrupt the UsefulInputBuf
nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
- if(nCBORError != QCBOR_ERR_HIT_END)
- return -1;
+ if(nCBORError != QCBOR_ERR_HIT_END) {
+ // Did not get back the error expected
+ return -2;
+ }
}
-
- return nResult;
+ return 0;
}
@@ -1499,8 +1976,14 @@
0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1
0xc1, // tag for epoch date
- 0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large
+ 0xfa, 0x7f, 0x7f, 0xff, 0xff, // 3.4028234663852886e+38 too large
+ 0xc1, // tag for epoch date
+ 0xfb, 0x43, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9223372036854775808.000000 just barely too large
+ //0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large
+
+ 0xc1, // tag for epoch date
+ 0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe // 9223372036854773760 largest supported
};
@@ -1575,6 +2058,18 @@
return -10;
}
+ // Epoch date double that is just slightly too large
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
+ return -11;
+ }
+
+ // Largest double epoch date supported
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_SUCCESS ||
+ Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
+ Item.val.epochDate.nSeconds != 9223372036854773760 ||
+ Item.val.epochDate.nSeconds == 0) {
+ return -12;
+ }
// TODO: could use a few more tests with float, double, and half precsion and negative (but coverage is still pretty good)
return 0;
diff --git a/lib/ext/qcbor/test/qcbor_decode_tests.h b/lib/ext/qcbor/test/qcbor_decode_tests.h
index 3ef0ca3..6423ccf 100644
--- a/lib/ext/qcbor/test/qcbor_decode_tests.h
+++ b/lib/ext/qcbor/test/qcbor_decode_tests.h
@@ -33,8 +33,6 @@
#ifndef __QCBOR__qcbort_decode_tests__
#define __QCBOR__qcbort_decode_tests__
-#include "qcbor.h"
-
/*
Notes:
@@ -49,8 +47,6 @@
*/
-
-
/*
Parse a well-known set of integers including those around the boundaries and
make sure the expected values come out
@@ -58,9 +54,6 @@
int IntegerValuesParseTest(void);
-
-
-
/*
Decode a simple CBOR encoded array and make sure it returns all the correct values.
This is a decode test.
@@ -69,6 +62,12 @@
/*
+ Tests with empty maps and arrays
+ */
+int EmptyMapsAndArraysTest(void);
+
+
+/*
Make sure a maximally deep array can be parsed and that the
reported nesting level is correct. This uses test vector
of CBOR encoded data with a depth of 10. This a parse test.
@@ -112,29 +111,30 @@
int ParseMapTest(void);
-
-int FloatValuesTest1(void);
-
-
-
-int SimpleValuesTest1(void);
-
-
/*
-
+Test the decoder mode where maps are treated as arrays.
*/
int ParseMapAsArrayTest(void);
-
+/*
+ Test parsing of some simple values like true, false, null...
+ */
int ParseSimpleTest(void);
+/*
+ This tests all the not-well-formed CBOR from the CBOR RFC.
+ (This is the CBORbis RFC which is not yet published at the
+ time this test was added).
+ */
+int NotWellFormedTests(void);
+
/*
Tests a number of failure cases on bad CBOR to get the right error code
*/
-int FailureTests(void);
+int DecodeFailureTests(void);
/*
@@ -176,6 +176,9 @@
int BignumParseTest(void);
+/*
+ Test of mode where only string labels are allowed
+ */
int StringDecoderModeFailTest(void);
@@ -232,6 +235,4 @@
int SetUpAllocatorTest(void);
-
-
#endif /* defined(__QCBOR__qcbort_decode_tests__) */
diff --git a/lib/ext/qcbor/test/qcbor_encode_tests.c b/lib/ext/qcbor/test/qcbor_encode_tests.c
index 458331c..7866b37 100644
--- a/lib/ext/qcbor/test/qcbor_encode_tests.c
+++ b/lib/ext/qcbor/test/qcbor_encode_tests.c
@@ -653,7 +653,7 @@
}
/*
- 98 2F # array(47)
+ 98 30 # array(48)
3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807)
3B 0000000100000000 # negative(4294967296)
3A FFFFFFFF # negative(4294967295)
@@ -682,6 +682,7 @@
18 18 # unsigned(24)
18 19 # unsigned(25)
18 1A # unsigned(26)
+ 18 1F # unsigned(31)
18 FE # unsigned(254)
18 FF # unsigned(255)
19 0100 # unsigned(256)
@@ -703,7 +704,7 @@
1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615)
*/
static const uint8_t spExpectedEncodedInts[] = {
- 0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
+ 0x98, 0x30, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff,
0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff,
@@ -714,19 +715,19 @@
0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38,
0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00,
0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18,
- 0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00,
- 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff,
- 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00,
- 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02,
- 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff,
- 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a,
- 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff,
- 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
- 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff};
+ 0x1a, 0x18, 0x1f, 0x18, 0xfe, 0x18, 0xff, 0x19,
+ 0x01, 0x00, 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe,
+ 0x19, 0xff, 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00,
+ 0x1a, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01,
+ 0x00, 0x02, 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a,
+ 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00,
+ 0x00, 0x1a, 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff,
+ 0xff, 0xff, 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff,
+ 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x01, 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff};
/*
@@ -773,6 +774,7 @@
QCBOREncode_AddInt64(&ECtx, 24);
QCBOREncode_AddInt64(&ECtx, 25);
QCBOREncode_AddInt64(&ECtx, 26);
+ QCBOREncode_AddInt64(&ECtx, 31);
QCBOREncode_AddInt64(&ECtx, 254);
QCBOREncode_AddInt64(&ECtx, 255);
QCBOREncode_AddInt64(&ECtx, 256);
@@ -852,6 +854,266 @@
return(nReturn);
}
+/*
+ 9F # array(5)
+ F5 # primitive(21)
+ F4 # primitive(20)
+ F6 # primitive(22)
+ F7 # primitive(23)
+ BF # map(1)
+ 65 # text(5)
+ 554E446566 # "UNDef"
+ F7 # primitive(23)
+ FF # break
+ FF # break
+ */
+static const uint8_t spExpectedEncodedSimpleIndefiniteLength[] = {
+ 0x9f, 0xf5, 0xf4, 0xf6, 0xf7, 0xbf, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7, 0xff, 0xff};
+
+int SimpleValuesIndefiniteLengthTest1()
+{
+ QCBOREncodeContext ECtx;
+ int nReturn = 0;
+
+ QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+ QCBOREncode_OpenArrayIndefiniteLength(&ECtx);
+
+ QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_TRUE);
+ QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_FALSE);
+ QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_NULL);
+ QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF);
+
+ QCBOREncode_OpenMapIndefiniteLength(&ECtx);
+
+ QCBOREncode_AddSimpleToMap(&ECtx, "UNDef", CBOR_SIMPLEV_UNDEF);
+ QCBOREncode_CloseMapIndefiniteLength(&ECtx);
+
+ QCBOREncode_CloseArrayIndefiniteLength(&ECtx);
+
+ UsefulBufC ECBOR;
+ if(QCBOREncode_Finish(&ECtx, &ECBOR)) {
+ nReturn = -1;
+ }
+
+ if(CheckResults(ECBOR, spExpectedEncodedSimpleIndefiniteLength))
+ return -2;
+
+ return(nReturn);
+}
+
+/*
+A5 # map(5)
+ 63 # text(3)
+ 617272 # "arr"
+ 98 1F # array(31)
+ 00 # unsigned(0)
+ 01 # unsigned(1)
+ 02 # unsigned(2)
+ 03 # unsigned(3)
+ 04 # unsigned(4)
+ 05 # unsigned(5)
+ 06 # unsigned(6)
+ 07 # unsigned(7)
+ 08 # unsigned(8)
+ 09 # unsigned(9)
+ 0A # unsigned(10)
+ 0B # unsigned(11)
+ 0C # unsigned(12)
+ 0D # unsigned(13)
+ 0E # unsigned(14)
+ 0F # unsigned(15)
+ 10 # unsigned(16)
+ 11 # unsigned(17)
+ 12 # unsigned(18)
+ 13 # unsigned(19)
+ 14 # unsigned(20)
+ 15 # unsigned(21)
+ 16 # unsigned(22)
+ 17 # unsigned(23)
+ 18 18 # unsigned(24)
+ 18 19 # unsigned(25)
+ 18 1A # unsigned(26)
+ 18 1B # unsigned(27)
+ 18 1C # unsigned(28)
+ 18 1D # unsigned(29)
+ 18 1E # unsigned(30)
+ 63 # text(3)
+ 6D6170 # "map"
+ B8 1F # map(31)
+ 61 # text(1)
+ 61 # "a"
+ 00 # unsigned(0)
+ 61 # text(1)
+ 62 # "b"
+ 01 # unsigned(1)
+ 61 # text(1)
+ 63 # "c"
+ 02 # unsigned(2)
+ 61 # text(1)
+ 64 # "d"
+ 03 # unsigned(3)
+ 61 # text(1)
+ 65 # "e"
+ 04 # unsigned(4)
+ 61 # text(1)
+ 66 # "f"
+ 05 # unsigned(5)
+ 61 # text(1)
+ 67 # "g"
+ 06 # unsigned(6)
+ 61 # text(1)
+ 68 # "h"
+ 07 # unsigned(7)
+ 61 # text(1)
+ 69 # "i"
+ 08 # unsigned(8)
+ 61 # text(1)
+ 6A # "j"
+ 09 # unsigned(9)
+ 61 # text(1)
+ 6B # "k"
+ 0A # unsigned(10)
+ 61 # text(1)
+ 6C # "l"
+ 0B # unsigned(11)
+ 61 # text(1)
+ 6D # "m"
+ 0C # unsigned(12)
+ 61 # text(1)
+ 6E # "n"
+ 0D # unsigned(13)
+ 61 # text(1)
+ 6F # "o"
+ 0E # unsigned(14)
+ 61 # text(1)
+ 70 # "p"
+ 0F # unsigned(15)
+ 61 # text(1)
+ 71 # "q"
+ 10 # unsigned(16)
+ 61 # text(1)
+ 72 # "r"
+ 11 # unsigned(17)
+ 61 # text(1)
+ 73 # "s"
+ 12 # unsigned(18)
+ 61 # text(1)
+ 74 # "t"
+ 13 # unsigned(19)
+ 61 # text(1)
+ 75 # "u"
+ 14 # unsigned(20)
+ 61 # text(1)
+ 76 # "v"
+ 15 # unsigned(21)
+ 61 # text(1)
+ 77 # "w"
+ 16 # unsigned(22)
+ 61 # text(1)
+ 78 # "x"
+ 17 # unsigned(23)
+ 61 # text(1)
+ 79 # "y"
+ 18 18 # unsigned(24)
+ 61 # text(1)
+ 7A # "z"
+ 18 19 # unsigned(25)
+ 61 # text(1)
+ 41 # "A"
+ 18 1A # unsigned(26)
+ 61 # text(1)
+ 42 # "B"
+ 18 1B # unsigned(27)
+ 61 # text(1)
+ 43 # "C"
+ 18 1C # unsigned(28)
+ 61 # text(1)
+ 44 # "D"
+ 18 1D # unsigned(29)
+ 61 # text(1)
+ 45 # "E"
+ 18 1E # unsigned(30)
+ 65 # text(5)
+ 6D696E3331 # "min31"
+ 38 1E # negative(30)
+ 66 # text(6)
+ 706C75733331 # "plus31"
+ 18 1F # unsigned(31)
+ 63 # text(3)
+ 737472 # "str"
+ 78 1F # text(31)
+ 7465737474657374746573747465737474657374746573747163626F723131 # "testtesttesttesttesttestqcbor11"
+ */
+static const uint8_t EncodeLengthThirtyone[] = {
+ 0xa5, 0x63, 0x61, 0x72, 0x72, 0x98, 0x1f, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18,
+ 0x1a, 0x18, 0x1b, 0x18, 0x1c, 0x18, 0x1d, 0x18, 0x1e, 0x63, 0x6d, 0x61,
+ 0x70, 0xb8, 0x1f, 0x61, 0x61, 0x00, 0x61, 0x62, 0x01, 0x61, 0x63, 0x02,
+ 0x61, 0x64, 0x03, 0x61, 0x65, 0x04, 0x61, 0x66, 0x05, 0x61, 0x67, 0x06,
+ 0x61, 0x68, 0x07, 0x61, 0x69, 0x08, 0x61, 0x6a, 0x09, 0x61, 0x6b, 0x0a,
+ 0x61, 0x6c, 0x0b, 0x61, 0x6d, 0x0c, 0x61, 0x6e, 0x0d, 0x61, 0x6f, 0x0e,
+ 0x61, 0x70, 0x0f, 0x61, 0x71, 0x10, 0x61, 0x72, 0x11, 0x61, 0x73, 0x12,
+ 0x61, 0x74, 0x13, 0x61, 0x75, 0x14, 0x61, 0x76, 0x15, 0x61, 0x77, 0x16,
+ 0x61, 0x78, 0x17, 0x61, 0x79, 0x18, 0x18, 0x61, 0x7a, 0x18, 0x19, 0x61,
+ 0x41, 0x18, 0x1a, 0x61, 0x42, 0x18, 0x1b, 0x61, 0x43, 0x18, 0x1c, 0x61,
+ 0x44, 0x18, 0x1d, 0x61, 0x45, 0x18, 0x1e, 0x65, 0x6d, 0x69, 0x6e, 0x33,
+ 0x31, 0x38, 0x1e, 0x66, 0x70, 0x6c, 0x75, 0x73, 0x33, 0x31, 0x18, 0x1f,
+ 0x63, 0x73, 0x74, 0x72, 0x78, 0x1f, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65,
+ 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x74, 0x65,
+ 0x73, 0x74, 0x74, 0x65, 0x73, 0x74, 0x71, 0x63, 0x62, 0x6f, 0x72, 0x31,
+ 0x31
+};
+
+int EncodeLengthThirtyoneTest()
+{
+ QCBOREncodeContext ECtx;
+ int nReturn = 0;
+
+ QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+ QCBOREncode_OpenMap(&ECtx);
+
+ // add array with 31 items
+ QCBOREncode_OpenArrayInMap(&ECtx, "arr");
+ for (size_t ix = 0; ix < 31; ix++) {
+ QCBOREncode_AddInt64(&ECtx, ix);
+ }
+ QCBOREncode_CloseArray(&ECtx);
+
+ // add map with 31 items
+ QCBOREncode_OpenMapInMap(&ECtx, "map");
+ for (size_t ix = 0; ix < 31; ix++) {
+ // make sure we have unique keys in the map (a-z then follow by A-Z)
+ char c = 'a';
+ if (ix < 26) c = c + ix;
+ else c = 'A' + (ix - 26);
+ char buffer[2] = { c, 0 };
+ QCBOREncode_AddInt64ToMap(&ECtx, buffer, ix);
+ }
+ QCBOREncode_CloseMap(&ECtx);
+
+ // add -31 and +31
+ QCBOREncode_AddInt64ToMap(&ECtx, "min31", -31);
+ QCBOREncode_AddInt64ToMap(&ECtx, "plus31", 31);
+
+ // add string with length 31
+ const char *str = "testtesttesttesttesttestqcbor11";
+ UsefulBufC str_b = { str, 31 };
+ QCBOREncode_AddTextToMap(&ECtx, "str", str_b);
+
+ QCBOREncode_CloseMap(&ECtx);
+
+ UsefulBufC ECBOR;
+ if(QCBOREncode_Finish(&ECtx, &ECBOR)) {
+ nReturn = -1;
+ }
+
+ if(CheckResults(ECBOR, EncodeLengthThirtyone))
+ return -2;
+
+ return(nReturn);
+}
+
/*
83 # array(3)
@@ -1006,7 +1268,7 @@
81 # array(1)
81 # array(1)
80 # array(0)
- 98 2F # array(47)
+ 98 30 # array(48)
3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807)
3B 0000000100000000 # negative(4294967296)
3A FFFFFFFF # negative(4294967295)
@@ -1035,6 +1297,7 @@
18 18 # unsigned(24)
18 19 # unsigned(25)
18 1A # unsigned(26)
+ 18 1F # unsigned(31)
18 FE # unsigned(254)
18 FF # unsigned(255)
19 0100 # unsigned(256)
@@ -1056,7 +1319,7 @@
1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615)
*/
static const uint8_t spEncodeRawExpected[] = {
- 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x98, 0x2f,
+ 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x98, 0x30,
0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, 0xff, 0x3a,
@@ -1068,18 +1331,19 @@
0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, 0xfd, 0x38,
0x18, 0x37, 0x36, 0x20, 0x00, 0x00, 0x01, 0x16,
0x17, 0x18, 0x18, 0x18, 0x19, 0x18, 0x1a, 0x18,
- 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, 0x19, 0x01,
- 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, 0xff, 0x1a,
- 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x01, 0x00,
- 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, 0x1a, 0x7f,
- 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, 0xff, 0xff,
- 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x00,
- 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, 0xfe, 0x1a,
- 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x7f,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ 0x1f, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00,
+ 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff,
+ 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00,
+ 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02,
+ 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff,
+ 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a,
+ 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff,
+ 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff};
int EncodeRawTest()
@@ -1588,7 +1852,7 @@
}
nReturn = QCBORDecode_GetNext(&DC, &Item);
- if(nReturn == QCBOR_ERR_HIT_END) {
+ if(nReturn == QCBOR_ERR_HIT_END || nReturn == QCBOR_ERR_NO_MORE_ITEMS) {
return 0;
}
if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
@@ -2050,6 +2314,20 @@
return -11;
}
+ // ------ QCBOR_ERR_UNSUPPORTED --------
+ QCBOREncode_Init(&EC, Large);
+ QCBOREncode_OpenArray(&EC);
+ QCBOREncode_AddSimple(&EC, 24); // CBOR_SIMPLEV_RESERVED_START
+ if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_UNSUPPORTED) {
+ return -12;
+ }
+
+ QCBOREncode_Init(&EC, Large);
+ QCBOREncode_OpenArray(&EC);
+ QCBOREncode_AddSimple(&EC, 31); // CBOR_SIMPLEV_RESERVED_END
+ if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_UNSUPPORTED) {
+ return -13;
+ }
+
return 0;
}
-
diff --git a/lib/ext/qcbor/test/qcbor_encode_tests.h b/lib/ext/qcbor/test/qcbor_encode_tests.h
index 33703d8..7909288 100644
--- a/lib/ext/qcbor/test/qcbor_encode_tests.h
+++ b/lib/ext/qcbor/test/qcbor_encode_tests.h
@@ -33,8 +33,6 @@
#ifndef __QCBOR__qcbor_encode_tests__
#define __QCBOR__qcbor_encode_tests__
-#include "qcbor.h"
-
/*
Notes:
@@ -62,7 +60,6 @@
int IntegerValuesTest1(void);
-
/*
Create nested arrays to the max depth allowed and make sure it succeeds.
This is an encoding test.
@@ -98,7 +95,6 @@
int MapEncodeTest(void);
-
/*
Encodes a goodly number of floats and doubles and checks encoding is right
*/
@@ -112,6 +108,18 @@
/*
+ Encodes basic maps and arrays with indefinite length
+ */
+int SimpleValuesIndefiniteLengthTest1(void);
+
+/*
+ Indefinite length arrays and maps use the 'magic' number 31, verify that
+ everything with length 31 still works properly
+ */
+int EncodeLengthThirtyoneTest(void);
+
+
+/*
Encodes most data formats that are supported */
int EncodeDateTest(void);
@@ -132,14 +140,32 @@
*/
int BstrWrapTest(void);
+
+/*
+ Test error cases for bstr wrapping encoding such as closing an open
+ array with CloseBstrWrap
+ */
int BstrWrapErrorTest(void);
+
+/*
+ Test complicated nested bstr wrapping
+ */
int BstrWrapNestTest(void);
+
+/*
+ Test encoding a COSE_Sign1 with bstr wrapping
+ */
int CoseSign1TBSTest(void);
-int EncodeErrorTests(void);
+/*
+ Test the error cases when encoding CBOR such as buffer too large,
+ buffer too small, array nesting too deep. Aims to cover the error
+ codes returned when encoding CBOR
+ */
+int EncodeErrorTests(void);
#endif /* defined(__QCBOR__qcbor_encode_tests__) */
diff --git a/lib/ext/qcbor/test/run_tests.c b/lib/ext/qcbor/test/run_tests.c
index 9a51290..52c4f8f 100644
--- a/lib/ext/qcbor/test/run_tests.c
+++ b/lib/ext/qcbor/test/run_tests.c
@@ -20,54 +20,9 @@
#include "UsefulBuf_Tests.h"
-
-// Used to test RunTests
-int fail_test()
-{
- return -44;
-}
-
-
-
-
/*
- Convert a number up to 999999999 to a string. This is so sprintf doesn't
- have to be linked in so as to minimized dependencies even in test code.
- */
-const char *NumToString(int32_t nNum, UsefulBuf StringMem)
-{
- const int32_t nMax = 1000000000;
-
- UsefulOutBuf OutBuf;
- UsefulOutBuf_Init(&OutBuf, StringMem);
-
- if(nNum < 0) {
- UsefulOutBuf_AppendByte(&OutBuf, '-');
- nNum = -nNum;
- }
- if(nNum > nMax-1) {
- return "XXX";
- }
-
- bool bDidSomeOutput = false;
- for(int n = nMax; n > 0; n/=10) {
- int x = nNum/n;
- if(x || bDidSomeOutput){
- bDidSomeOutput = true;
- UsefulOutBuf_AppendByte(&OutBuf, '0' + x);
- nNum -= x * n;
- }
- }
- if(!bDidSomeOutput){
- UsefulOutBuf_AppendByte(&OutBuf, '0');
- }
- UsefulOutBuf_AppendByte(&OutBuf, '\0');
-
- return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
-}
-
-
-
+ Test configuration
+ */
typedef int (test_fun_t)(void);
typedef const char * (test_fun2_t)(void);
@@ -88,7 +43,8 @@
bool bEnabled;
} test_entry2;
-test_entry2 s_tests2[] = {
+
+static test_entry2 s_tests2[] = {
TEST_ENTRY(UBUTest_CopyUtil),
TEST_ENTRY(UOBTest_NonAdversarial),
TEST_ENTRY(TestBasicSanity),
@@ -99,12 +55,15 @@
};
-test_entry s_tests[] = {
+static test_entry s_tests[] = {
+ TEST_ENTRY(EmptyMapsAndArraysTest),
+ TEST_ENTRY(NotWellFormedTests),
TEST_ENTRY(ParseMapAsArrayTest),
TEST_ENTRY(AllocAllStringsTest),
TEST_ENTRY(IndefiniteLengthNestTest),
TEST_ENTRY(NestedMapTestIndefLen),
TEST_ENTRY(ParseSimpleTest),
+ TEST_ENTRY(DecodeFailureTests),
TEST_ENTRY(EncodeRawTest),
TEST_ENTRY(RTICResultsTest),
TEST_ENTRY(MapEncodeTest),
@@ -142,15 +101,61 @@
TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
TEST_ENTRY(EncodeErrorTests),
TEST_ENTRY(SetUpAllocatorTest),
- //TEST_ENTRY(fail_test),
+ TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
+ TEST_ENTRY(EncodeLengthThirtyoneTest),
};
+
+
+/*
+ Convert a number up to 999999999 to a string. This is so sprintf doesn't
+ have to be linked in so as to minimized dependencies even in test code.
+
+ StringMem should be 12 bytes long, 9 for digits, 1 for minus and
+ 1 for \0 termination.
+ */
+static const char *NumToString(int32_t nNum, UsefulBuf StringMem)
+{
+ const int32_t nMax = 1000000000;
+
+ UsefulOutBuf OutBuf;
+ UsefulOutBuf_Init(&OutBuf, StringMem);
+
+ if(nNum < 0) {
+ UsefulOutBuf_AppendByte(&OutBuf, '-');
+ nNum = -nNum;
+ }
+ if(nNum > nMax-1) {
+ return "XXX";
+ }
+
+ bool bDidSomeOutput = false;
+ for(int n = nMax; n > 0; n/=10) {
+ int x = nNum/n;
+ if(x || bDidSomeOutput){
+ bDidSomeOutput = true;
+ UsefulOutBuf_AppendByte(&OutBuf, '0' + x);
+ nNum -= x * n;
+ }
+ }
+ if(!bDidSomeOutput){
+ UsefulOutBuf_AppendByte(&OutBuf, '0');
+ }
+ UsefulOutBuf_AppendByte(&OutBuf, '\0');
+
+ return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
+}
+
+
+/*
+ Public function. See run_test.h.
+ */
int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *poutCtx, int *pNumTestsRun)
{
int nTestsFailed = 0;
int nTestsRun = 0;
- UsefulBuf_MAKE_STACK_UB(StringStorage, 5);
+ UsefulBuf_MAKE_STACK_UB(StringStorage, 12);
test_entry2 *t2;
const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);
@@ -259,8 +264,11 @@
}
+#include "qcbor.h" // For size printing
-
+/*
+ Public function. See run_test.h.
+ */
static void PrintSize(const char *szWhat, uint32_t uSize, OutputStringCB pfOutput, void *pOutCtx)
{
UsefulBuf_MAKE_STACK_UB(buffer, 20);
@@ -271,6 +279,10 @@
(*pfOutput)("", pOutCtx, 1);
}
+
+/*
+ Public function. See run_test.h.
+ */
void PrintSizes(OutputStringCB pfOutput, void *pOutCtx)
{
// Type and size of return from sizeof() varies. These will never be large so cast is safe