Improve error handling for not well-formed CBOR
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 2f2614d..8a79bd8 100644
--- a/test/qcbor_decode_tests.c
+++ b/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
@@ -654,20 +655,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,29 +1326,330 @@
}
+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; // CBOR to decode
QCBORError nError; // The error expected
};
struct FailInput Failures[] = {
- { {(uint8_t[]){0xa1, 0x00}, 2}, QCBOR_ERR_HIT_END }, // map with odd number of entries
- { {(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_BAD_INT }, // 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_BAD_INT }, // 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[]){0x61}, 1}, QCBOR_ERR_HIT_END }, // Short UTF-8 string
- { {(uint8_t[]){0x7c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28
- { {(uint8_t[]){0xff}, 1}, QCBOR_ERR_BAD_BREAK } , // 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
@@ -1363,29 +1661,29 @@
// 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++) {
+
+ // Set up the decoding context including a mem pool so that
+ // indefinite length items can be checked
QCBORDecodeContext DCtx;
- QCBORItem Item;
- QCBORError 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
+ do {
+ QCBORItem Item;
+
nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
- if(QCBOR_SUCCESS == nCBORError) {
- // Must end in an error, so if success keep going
- continue;
- }
+ } while(nCBORError == QCBOR_SUCCESS);
- if(nCBORError != pF->nError) {
- // Not success, nor error expected so a test failure
- // Return code is 1000 plus index into Failures of test that failed
- return 1000 + (int)(pF - &Failures[0]);
- } else {
- // Got the error expected
- break;
- }
+ // Must get the expected error or the this test fails
+ if(nCBORError != pF->nError) {
+ // return index of CBOR + 1000
+ return 1000 + (int)(pF - &Failures[0]);
}
}