diff options
Diffstat (limited to 'lib/ext/qcbor/test/qcbor_decode_tests.c')
-rw-r--r-- | lib/ext/qcbor/test/qcbor_decode_tests.c | 625 |
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; |