aboutsummaryrefslogtreecommitdiff
path: root/lib/ext/qcbor/test/qcbor_decode_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext/qcbor/test/qcbor_decode_tests.c')
-rw-r--r--lib/ext/qcbor/test/qcbor_decode_tests.c625
1 files changed, 560 insertions, 65 deletions
diff --git a/lib/ext/qcbor/test/qcbor_decode_tests.c b/lib/ext/qcbor/test/qcbor_decode_tests.c
index 680c86b4a0..7de8c6cc8f 100644
--- a/lib/ext/qcbor/test/qcbor_decode_tests.c
+++ b/lib/ext/qcbor/test/qcbor_decode_tests.c
@@ -34,6 +34,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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 @@ static int IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx)
}
+// 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 @@ int SimpleArrayTest()
}
+/*
+ [
+ 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 ParseTooDeepArrayTest()
int ShortBufferParseTest()
{
- int nResult = 0;
- QCBORDecodeContext DCtx;
- int num;
-
- for(num = sizeof(spExpectedEncodedInts)-1; num; num--) {
- int n;
+ int nResult = 0;
- QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL);
+ for(int nNum = sizeof(spExpectedEncodedInts)-1; nNum; nNum--) {
+ QCBORDecodeContext DCtx;
- n = IntegerValuesParseTestInternal(&DCtx);
+ QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, nNum}, QCBOR_DECODE_MODE_NORMAL);
- //printf("Len %d, result: %d\n", num, n);
+ const QCBORError nErr = IntegerValuesParseTestInternal(&DCtx);
- 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 @@ int ParseSimpleTest()
}
+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;
-
- struct FailInput *pFEnd = &Failures[0] + sizeof(Failures)/sizeof(struct FailInput);
+ // 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++) {
- 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;
+ }
+
+ // 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));
- while(1) {
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 @@ static uint8_t spDateTestInput[] = {
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 @@ int DateParseTest()
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;