| /*============================================================================== |
| Copyright (c) 2016-2018, The Linux Foundation. |
| Copyright (c) 2018-2021, Laurence Lundblade. |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are |
| met: |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above |
| copyright notice, this list of conditions and the following |
| disclaimer in the documentation and/or other materials provided |
| with the distribution. |
| * Neither the name of The Linux Foundation nor the names of its |
| contributors, nor the name "Laurence Lundblade" may be used to |
| endorse or promote products derived from this software without |
| specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| =============================================================================*/ |
| |
| #include "qcbor_decode_tests.h" |
| #include "qcbor/qcbor_encode.h" |
| #include "qcbor/qcbor_decode.h" |
| #include "qcbor/qcbor_spiffy_decode.h" |
| #include <string.h> |
| #include <math.h> // for fabs() |
| #include "not_well_formed_cbor.h" |
| |
| // Handy macro to compare a UsefulBuf to a C string |
| #define UsefulBufCompareToSZ(x, y) \ |
| UsefulBuf_Compare(x, UsefulBuf_FromSZ(y)) |
| |
| #ifdef PRINT_FUNCTIONS_FOR_DEBUGGING |
| #include <stdio.h> |
| |
| static void PrintUsefulBufC(const char *szLabel, UsefulBufC Buf) |
| { |
| if(szLabel) { |
| printf("%s ", szLabel); |
| } |
| |
| size_t i; |
| for(i = 0; i < Buf.len; i++) { |
| uint8_t Z = ((uint8_t *)Buf.ptr)[i]; |
| printf("%02x ", Z); |
| } |
| printf("\n"); |
| |
| fflush(stdout); |
| } |
| #endif /* PRINT_FUNCTIONS_FOR_DEBUGGING */ |
| |
| /* |
| [ |
| -9223372036854775808, |
| -4294967297, |
| -4294967296, |
| -4294967295, |
| -4294967294, |
| -2147483648, |
| -2147483647, |
| -65538, |
| -65537, |
| -65536, |
| -65535, |
| -65534, |
| -257, |
| -256, |
| -255, |
| -254, |
| -25, |
| -24, |
| -23, |
| -1, |
| 0, |
| 0, |
| 1, |
| 22, |
| 23, |
| 24, |
| 25, |
| 26, |
| 254, |
| 255, |
| 256, |
| 257, |
| 65534, |
| 65535, |
| 65536, |
| 65537, |
| 65538, |
| 2147483647, |
| 2147483647, |
| 2147483648, |
| 2147483649, |
| 4294967294, |
| 4294967295, |
| 4294967296, |
| 4294967297, |
| 9223372036854775807, |
| 18446744073709551615 |
| ] |
| */ |
| |
| static const uint8_t spExpectedEncodedInts[] = { |
| 0x98, 0x2f, 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, |
| 0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, |
| 0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, |
| 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, |
| 0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, |
| 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}; |
| |
| |
| // return CBOR error or -1 if type of value doesn't match |
| |
| static int32_t IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx) |
| { |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -9223372036854775807LL - 1) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -4294967297) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -4294967296) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -4294967295) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -4294967294) |
| return -1; |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -2147483648) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -2147483647) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -65538) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -65537) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -65536) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -65535) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -65534) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -257) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -256) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -255) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -254) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -25) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -24) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -23) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -1) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 0) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 0) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 1) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 22) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 23) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 24) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 25) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 26) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 254) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 255) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 256) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 257) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 65534) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 65535) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 65536) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 65537) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 65538) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 2147483647) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 2147483647) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 2147483648) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 2147483649) |
| return -1; |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 4294967294) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 4294967295) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 4294967296) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 4294967297) |
| return -1; |
| |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 9223372036854775807LL) |
| return -1; |
| |
| |
| if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_UINT64 || |
| Item.val.uint64 != 18446744073709551615ULL) |
| return -1; |
| |
| |
| if(QCBORDecode_Finish(pDCtx) != QCBOR_SUCCESS) { |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| /* One less than the smallest negative integer allowed in C. Decoding |
| this should fail. |
| -9223372036854775809 |
| */ |
| static const uint8_t spTooSmallNegative[] = { |
| 0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| }; |
| |
| |
| /* |
| Tests the decoding of lots of different integers sizes |
| and values. |
| */ |
| int32_t IntegerValuesParseTest() |
| { |
| int nReturn; |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| // The really big test of all successes |
| nReturn = IntegerValuesParseTestInternal(&DCtx); |
| if(nReturn) { |
| return nReturn; |
| } |
| |
| // The one large negative integer that can be parsed |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooSmallNegative), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| QCBORItem item; |
| if(QCBORDecode_GetNext(&DCtx, &item) != QCBOR_ERR_INT_OVERFLOW) { |
| nReturn = -4000; |
| } |
| |
| return(nReturn); |
| } |
| |
| |
| /* |
| Creates a simple CBOR array and returns it in *pEncoded. The array is |
| malloced and needs to be freed. This is used by several tests. |
| |
| Two of the inputs can be set. Two other items in the array are fixed. |
| |
| */ |
| |
| static uint8_t spSimpleArrayBuffer[50]; |
| |
| static int32_t CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen) |
| { |
| QCBOREncodeContext ECtx; |
| int nReturn = -1; |
| |
| *pEncoded = NULL; |
| *pEncodedLen = INT32_MAX; |
| |
| // loop runs CBOR encoding twice. First with no buffer to |
| // calculate the length so buffer can be allocated correctly, |
| // and last with the buffer to do the actual encoding |
| do { |
| QCBOREncode_Init(&ECtx, (UsefulBuf){*pEncoded, *pEncodedLen}); |
| QCBOREncode_OpenArray(&ECtx); |
| QCBOREncode_AddInt64(&ECtx, nInt1); |
| QCBOREncode_AddInt64(&ECtx, nInt2); |
| QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"galactic", 8})); |
| QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"haven token", 11})); |
| QCBOREncode_CloseArray(&ECtx); |
| |
| if(QCBOREncode_FinishGetSize(&ECtx, pEncodedLen)) |
| goto Done; |
| |
| if(*pEncoded != NULL) { |
| nReturn = 0; |
| goto Done; |
| } |
| |
| // Use static buffer to avoid dependency on malloc() |
| if(*pEncodedLen > sizeof(spSimpleArrayBuffer)) { |
| goto Done; |
| } |
| *pEncoded = spSimpleArrayBuffer; |
| |
| } while(1); |
| |
| Done: |
| return nReturn; |
| } |
| |
| |
| /* |
| Some basic CBOR with map and array used in a lot of tests. |
| The map labels are all strings |
| |
| { |
| "first integer": 42, |
| "an array of two strings": [ |
| "string1", "string2" |
| ], |
| "map in a map": { |
| "bytes 1": h'78787878', |
| "bytes 2": h'79797979', |
| "another int": 98, |
| "text 2": "lies, damn lies and statistics" |
| } |
| } |
| */ |
| static const uint8_t pValidMapEncoded[] = { |
| 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, |
| 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, |
| 0x2a, 0x77, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, |
| 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x77, |
| 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, |
| 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, |
| 0x67, 0x31, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, |
| 0x67, 0x32, 0x6c, 0x6d, 0x61, 0x70, 0x20, 0x69, |
| 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x70, 0xa4, |
| 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, |
| 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, |
| 0x74, 0x65, 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, |
| 0x79, 0x79, 0x6b, 0x61, 0x6e, 0x6f, 0x74, 0x68, |
| 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x18, 0x62, |
| 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, |
| 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, |
| 0x61, 0x6d, 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, |
| 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x61, |
| 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73 }; |
| |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| // Same as above, but with indefinite lengths. |
| static const uint8_t pValidMapIndefEncoded[] = { |
| 0xbf, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, |
| 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, |
| 0x2a, 0x77, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, |
| 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x77, |
| 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, |
| 0x73, 0x9f, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, |
| 0x67, 0x31, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, |
| 0x67, 0x32, 0xff, 0x6c, 0x6d, 0x61, 0x70, 0x20, |
| 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x70, |
| 0xbf, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, |
| 0x31, 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, |
| 0x79, 0x74, 0x65, 0x73, 0x20, 0x32, 0x44, 0x79, |
| 0x79, 0x79, 0x79, 0x6b, 0x61, 0x6e, 0x6f, 0x74, |
| 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x18, |
| 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, |
| 0x78, 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, |
| 0x64, 0x61, 0x6d, 0x6e, 0x20, 0x6c, 0x69, 0x65, |
| 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, |
| 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, |
| 0xff, 0xff}; |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| static int32_t ParseOrderedArray(const uint8_t *pEncoded, |
| size_t nLen, |
| int64_t *pInt1, |
| int64_t *pInt2, |
| const uint8_t **pBuf3, |
| size_t *pBuf3Len, |
| const uint8_t **pBuf4, |
| size_t *pBuf4Len) |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| int nReturn = -1; // assume error until success |
| |
| QCBORDecode_Init(&DCtx, |
| (UsefulBufC){pEncoded, nLen}, |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| // Make sure the first thing is a map |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_ARRAY) { |
| goto Done; |
| } |
| |
| // First integer |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_INT64) { |
| goto Done; |
| } |
| *pInt1 = Item.val.int64; |
| |
| // Second integer |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_INT64) { |
| goto Done; |
| } |
| *pInt2 = Item.val.int64; |
| |
| // First string |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING) { |
| goto Done; |
| } |
| *pBuf3 = Item.val.string.ptr; |
| *pBuf3Len = Item.val.string.len; |
| |
| // Second string |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING) { |
| goto Done; |
| } |
| *pBuf4 = Item.val.string.ptr; |
| *pBuf4Len = Item.val.string.len; |
| |
| nReturn = 0; |
| |
| Done: |
| return(nReturn); |
| } |
| |
| |
| |
| |
| int32_t SimpleArrayTest() |
| { |
| uint8_t *pEncoded; |
| size_t nEncodedLen; |
| |
| int64_t i1=0, i2=0; |
| size_t i3=0, i4=0; |
| const uint8_t *s3= (uint8_t *)""; |
| const uint8_t *s4= (uint8_t *)""; |
| |
| |
| if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) { |
| return(-1); |
| } |
| |
| ParseOrderedArray(pEncoded, nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4); |
| |
| if(i1 != 23 || |
| i2 != 6000 || |
| i3 != 8 || |
| i4 != 11 || |
| memcmp("galactic", s3, 8) !=0 || |
| memcmp("haven token", s4, 11) !=0) { |
| return(-1); |
| } |
| |
| return(0); |
| } |
| |
| |
| /* |
| [ |
| 0, |
| [], |
| [ |
| [], |
| [ |
| 0 |
| ], |
| {}, |
| { |
| 1: {}, |
| 2: {}, |
| 3: [] |
| } |
| ] |
| ] |
| */ |
| static uint8_t sEmpties[] = { |
| 0x83, 0x00, 0x80, 0x84, 0x80, 0x81, 0x00, 0xa0, |
| 0xa3, 0x01, 0xa0, 0x02, 0xa0, 0x03, 0x80}; |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| /* Same as above, but with indefinte lengths */ |
| static const uint8_t sEmptiesIndef[] = { |
| 0x9F, |
| 0x00, |
| 0x9F, |
| 0xFF, |
| 0x9F, |
| 0x9F, |
| 0xFF, |
| 0x9F, |
| 0x00, |
| 0xFF, |
| 0xBF, |
| 0xFF, |
| 0xBF, |
| 0x01, |
| 0xBF, |
| 0xFF, |
| 0x02, |
| 0xBF, |
| 0xFF, |
| 0x03, |
| 0x9F, |
| 0xFF, |
| 0xFF, |
| 0xFF, |
| 0xFF}; |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| static int32_t CheckEmpties(UsefulBufC input, bool bCheckCounts) |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| |
| QCBORDecode_Init(&DCtx, |
| input, |
| 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && Item.val.uCount != 0)) { |
| return -8; |
| } |
| |
| // A map with 3 items |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_MAP || |
| Item.uNestingLevel != 2 || |
| Item.uNextNestLevel != 3 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && 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 || |
| (bCheckCounts && Item.val.uCount != 0)) { |
| return -12; |
| } |
| |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_SUCCESS) { |
| return -13; |
| } |
| return 0; |
| } |
| |
| |
| int32_t EmptyMapsAndArraysTest() |
| { |
| int nResult; |
| nResult = CheckEmpties(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmpties), |
| true); |
| if(nResult) { |
| return nResult; |
| } |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| nResult = CheckEmpties(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmptiesIndef), |
| false); |
| |
| if(nResult) { |
| return nResult -100; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| return 0; |
| } |
| |
| |
| static const uint8_t sEmptyMap[] = { |
| 0xA1, //# map(1) |
| 0x02, //# unsigned(2) |
| 0xA0, //# map(0) |
| }; |
| |
| int32_t ParseEmptyMapInMapTest(void) |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| int nReturn = 0; |
| QCBORError uErr; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmptyMap), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| /* now open the first Map */ |
| uErr = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uErr != QCBOR_SUCCESS || |
| Item.uDataType != QCBOR_TYPE_MAP) { |
| nReturn = -3; |
| goto done; |
| } |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0) { |
| nReturn = -1; |
| goto done; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| Item.uNestingLevel != 1 || |
| Item.label.int64 != 2) { |
| nReturn = -2; |
| goto done; |
| } |
| |
| done: |
| return(nReturn); |
| } |
| |
| |
| /* [[[[[[[[[[]]]]]]]]]] */ |
| static const uint8_t spDeepArrays[] = { |
| 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, |
| 0x81, 0x80}; |
| |
| int32_t ParseDeepArrayTest() |
| { |
| QCBORDecodeContext DCtx; |
| int nReturn = 0; |
| int i; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDeepArrays), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| for(i = 0; i < 10; i++) { |
| QCBORItem Item; |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.uNestingLevel != i) { |
| nReturn = -1; |
| break; |
| } |
| } |
| |
| return(nReturn); |
| } |
| |
| /* Big enough to test nesting to the depth of 24 |
| [[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]] |
| */ |
| static const uint8_t spTooDeepArrays[] = { |
| 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, |
| 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, |
| 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, |
| 0x80}; |
| |
| int32_t ParseTooDeepArrayTest() |
| { |
| QCBORDecodeContext DCtx; |
| int nReturn = 0; |
| int i; |
| QCBORItem Item; |
| |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooDeepArrays), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| for(i = 0; i < QCBOR_MAX_ARRAY_NESTING1; i++) { |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.uNestingLevel != i) { |
| nReturn = -1; |
| break; |
| } |
| } |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP) |
| nReturn = -1; |
| |
| return(nReturn); |
| } |
| |
| |
| |
| |
| int32_t ShortBufferParseTest() |
| { |
| int nResult = 0; |
| |
| for(size_t nNum = sizeof(spExpectedEncodedInts)-1; nNum; nNum--) { |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, |
| (UsefulBufC){spExpectedEncodedInts, nNum}, |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| const int nErr = IntegerValuesParseTestInternal(&DCtx); |
| |
| if(nErr != QCBOR_ERR_HIT_END && nErr != QCBOR_ERR_NO_MORE_ITEMS) { |
| nResult = -1; |
| goto Done; |
| } |
| } |
| Done: |
| return nResult; |
| } |
| |
| |
| |
| int32_t ShortBufferParseTest2() |
| { |
| uint8_t *pEncoded; |
| int nReturn; |
| size_t nEncodedLen; |
| |
| int64_t i1, i2; |
| size_t i3, i4; |
| const uint8_t *s3, *s4; |
| |
| nReturn = 0; |
| |
| if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) { |
| return(-1); |
| } |
| |
| for(nEncodedLen--; nEncodedLen; nEncodedLen--) { |
| int nResult = ParseOrderedArray(pEncoded, (uint32_t)nEncodedLen, &i1, |
| &i2, &s3, &i3, &s4, &i4); |
| if(nResult == 0) { |
| nReturn = -1; |
| } |
| } |
| |
| return(nReturn); |
| } |
| |
| /* |
| Decode and thoroughly check a moderately complex |
| set of maps. Can be run in QCBOR_DECODE_MODE_NORMAL or in |
| QCBOR_DECODE_MODE_MAP_STRINGS_ONLY. |
| */ |
| static int32_t ParseMapTest1(QCBORDecodeMode nMode) |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| QCBORDecode_Init(&DCtx, |
| (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, |
| nMode); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 3) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "map in a map") || |
| Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 4) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 1"))|| |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "xxxx")) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "bytes 2") || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "yyyy")) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "another int") || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 98) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "lies, damn lies and statistics")) { |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| /* |
| Decode and thoroughly check a moderately complex |
| set of maps in the QCBOR_DECODE_MODE_MAP_AS_ARRAY mode. |
| */ |
| int32_t ParseMapAsArrayTest() |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), |
| QCBOR_DECODE_MODE_MAP_AS_ARRAY); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY || |
| Item.val.uCount != 6) { |
| return -1; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| Item.uLabelType != QCBOR_TYPE_NONE || |
| UsefulBufCompareToSZ(Item.val.string, "first integer")) { |
| return -2; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc) { |
| return -3; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING) { |
| return -4; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return -5; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.val.string.len != 7 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { |
| return -6; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { |
| return -7; |
| } |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "map in a map")) { |
| return -8; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY || |
| Item.val.uCount != 8) { |
| return -9; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| UsefulBufCompareToSZ(Item.val.string, "bytes 1") || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc) { |
| return -10; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "xxxx")) { |
| return -11; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| UsefulBufCompareToSZ(Item.val.string, "bytes 2") || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc) { |
| return -12; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "yyyy")) { |
| return -13; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "another int") || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING) { |
| return -14; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 98) { |
| return -15; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| UsefulBufCompareToSZ(Item.val.string, "text 2") || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc) { |
| return -16; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_NONE || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "lies, damn lies and statistics")) { |
| return -17; |
| } |
| |
| |
| /* |
| Test with map that nearly QCBOR_MAX_ITEMS_IN_ARRAY items in a |
| map that when interpreted as an array will be too many. Test |
| data just has the start of the map, not all the items in the map. |
| */ |
| static const uint8_t pTooLargeMap[] = {0xb9, 0xff, 0xfd}; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pTooLargeMap), |
| QCBOR_DECODE_MODE_MAP_AS_ARRAY); |
| |
| if((QCBOR_ERR_ARRAY_DECODE_TOO_LONG != QCBORDecode_GetNext(&DCtx, &Item))) { |
| return -50; |
| } |
| |
| // TODO: test decoding of labels that are arrays or such |
| // TODO: test spiffy decoding of QCBOR_DECODE_MODE_MAP_AS_ARRAY |
| |
| return 0; |
| } |
| |
| |
| /* |
| Fully or partially decode pValidMapEncoded. When |
| partially decoding check for the right error code. |
| How much partial decoding depends on nLevel. |
| |
| The partial decodes test error conditions of |
| incomplete encoded input. |
| |
| This could be combined with the above test |
| and made prettier and maybe a little more |
| thorough. |
| */ |
| static int32_t ExtraBytesTest(int nLevel) |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| QCBORDecode_Init(&DCtx, |
| (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| if(nLevel < 1) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) { |
| return -1; |
| } else { |
| return 0; |
| } |
| } |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 3) |
| return -2; |
| |
| if(nLevel < 2) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -3; |
| } else { |
| return 0; |
| } |
| } |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.uCount != 42 || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return -4; |
| } |
| |
| if(nLevel < 3) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -5; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return -6; |
| } |
| |
| |
| if(nLevel < 4) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -7; |
| } else { |
| return 0; |
| } |
| } |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return -8; |
| } |
| |
| if(nLevel < 5) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -9; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return -10; |
| } |
| |
| if(nLevel < 6) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -11; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "map in a map") || |
| Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 4) |
| return -12; |
| |
| if(nLevel < 7) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -13; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "bytes 1") || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| UsefulBufCompareToSZ(Item.val.string, "xxxx")) { |
| return -14; |
| } |
| |
| if(nLevel < 8) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -15; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "bytes 2") || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| UsefulBufCompareToSZ(Item.val.string, "yyyy")) { |
| return -16; |
| } |
| |
| if(nLevel < 9) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -17; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "another int") || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 98) |
| return -18; |
| |
| if(nLevel < 10) { |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -19; |
| } else { |
| return 0; |
| } |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.val.string, "lies, damn lies and statistics")) { |
| return -20; |
| } |
| |
| if(QCBORDecode_Finish(&DCtx)) { |
| return -21; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| int32_t ParseMapTest() |
| { |
| // Parse a moderatly complex map structure very thoroughly |
| int32_t nResult = ParseMapTest1(QCBOR_DECODE_MODE_NORMAL); |
| if(nResult) { |
| return nResult; |
| } |
| |
| // Again, but in strings-only mode. It should succeed since the input |
| // map has only string labels. |
| nResult = ParseMapTest1(QCBOR_DECODE_MODE_MAP_STRINGS_ONLY); |
| if(nResult) { |
| return nResult; |
| } |
| |
| // Again, but try to finish the decoding before the end of the |
| // input at 10 different place and see that the right error code |
| // is returned. |
| for(int i = 0; i < 10; i++) { |
| nResult = ExtraBytesTest(i); |
| if(nResult) { |
| break; |
| } |
| } |
| |
| return nResult; |
| } |
| |
| |
| /* The simple-values including some not well formed */ |
| static const uint8_t spSimpleValues[] = { |
| 0x8a, 0xf4, 0xf5, 0xf6, 0xf7, 0xff, 0xe0, 0xf3, |
| 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, |
| 0xf8, 0xff}; |
| |
| int32_t ParseSimpleTest() |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 10) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_FALSE) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_TRUE) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_NULL) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_UNDEF) |
| return -1; |
| |
| // A break |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_BREAK) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 0) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 19) |
| return -1; |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7) |
| return -1; |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7) |
| return -1; |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 32) |
| return -1; |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return (int32_t)nCBORError; |
| if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 255) |
| return -1; |
| |
| return 0; |
| |
| } |
| |
| |
| int32_t 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 = C_ARRAY_COUNT(paNotWellFormedCBOR, |
| 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); |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| UsefulBuf_MAKE_STACK_UB(Pool, 100); |
| QCBORDecode_SetMemPool(&DCtx, Pool, 0); |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| // Loop getting items until no more to get |
| QCBORError uCBORError; |
| do { |
| QCBORItem Item; |
| |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| } while(uCBORError == QCBOR_SUCCESS); |
| |
| // Every test vector must fail with |
| // a not-well-formed error. If not |
| // this test fails. |
| if(!QCBORDecode_IsNotWellFormedError(uCBORError) && |
| uCBORError != QCBOR_ERR_NO_MORE_ITEMS) { |
| /* Return index of failure and QCBOR error in the result */ |
| return (int32_t)(nIterate * 100 + uCBORError); |
| } |
| } |
| return 0; |
| } |
| |
| |
| // TODO: add a test index and report it so it is eaier to figure out which test failed. |
| struct FailInput { |
| UsefulBufC Input; |
| QCBORError nError; |
| }; |
| |
| |
| static int32_t ProcessFailures(const struct FailInput *pFailInputs, size_t nNumFails) |
| { |
| for(const struct FailInput *pF = pFailInputs; pF < pFailInputs + nNumFails; pF++) { |
| QCBORDecodeContext DCtx; |
| QCBORError uCBORError; |
| |
| QCBORDecode_Init(&DCtx, pF->Input, QCBOR_DECODE_MODE_NORMAL); |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| // Set up the decoding context including a memory pool so that |
| // indefinite length items can be checked |
| UsefulBuf_MAKE_STACK_UB(Pool, 100); |
| |
| uCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0); |
| if(uCBORError) { |
| return -9; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| // Iterate until there is an error of some sort error |
| QCBORItem Item; |
| do { |
| // Set to something none-zero, something other than QCBOR_TYPE_NONE |
| memset(&Item, 0x33, sizeof(Item)); |
| |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| } while(uCBORError == QCBOR_SUCCESS); |
| |
| |
| |
| // Must get the expected error or the this test fails |
| // The data and label type must also be QCBOR_TYPE_NONE |
| if(uCBORError != pF->nError || |
| Item.uDataType != QCBOR_TYPE_NONE || |
| Item.uLabelType != QCBOR_TYPE_NONE) { |
| // return index of CBOR + 100 |
| const size_t nIndex = (size_t)(pF - pFailInputs); |
| return (int32_t)(nIndex * 100 + uCBORError); |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| static const struct FailInput Failures[] = { |
| // Most of this is copied from not_well_formed.h. Here the error code |
| // returned is also checked. |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| // 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}, |
| |
| #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| { {(uint8_t[]){0x5f, 0x41, 0x00}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // An indefinite length text string not closed off |
| { {(uint8_t[]){0x7f, 0x61, 0x00}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| |
| |
| // 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_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length text string with a byte string chunk |
| { {(uint8_t[]){0x7f, 0x41, 0x00, 0xff}, 4}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length byte string with an positive integer chunk |
| { {(uint8_t[]){0x5f, 0x00, 0xff}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length byte string with an negative integer chunk |
| { {(uint8_t[]){0x5f, 0x21, 0xff}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length byte string with an array chunk |
| { {(uint8_t[]){0x5f, 0x80, 0xff}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length byte string with an map chunk |
| { {(uint8_t[]){0x5f, 0xa0, 0xff}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length byte string with tagged integer chunk |
| { {(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| // indefinite length byte string with an simple type chunk |
| { {(uint8_t[]){0x5f, 0xe0, 0xff}, 3}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED }, |
| { {(uint8_t[]){0x5f, 0x5f, 0x41, 0x00, 0xff, 0xff}, 6}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED}, |
| // indefinite length text string with indefinite string inside |
| { {(uint8_t[]){0x7f, 0x7f, 0x61, 0x00, 0xff, 0xff}, 6}, QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED}, |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| // 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_NO_MORE_ITEMS }, |
| // A definte length array that is supposed to have 2 items, but has only 1 |
| { {(uint8_t[]){0x82, 0x00}, 2}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // 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_NO_MORE_ITEMS }, |
| // A definte length map that is supposed to have s item, but has only 1 |
| { {(uint8_t[]){0xa2, 0x01, 0x02}, 3}, QCBOR_ERR_NO_MORE_ITEMS }, |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| // 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_NO_MORE_ITEMS }, |
| // Indefinite length array with two items and no break |
| { {(uint8_t[]){0x9f, 0x01, 0x02}, 3}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Indefinite length map with zero items and no break |
| { {(uint8_t[]){0xbf}, 1}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Indefinite length map with two items and no break |
| { {(uint8_t[]){0xbf, 0x01, 0x02, 0x01, 0x02}, 5}, QCBOR_ERR_NO_MORE_ITEMS }, |
| |
| |
| // Nested maps and arrays must be closed off (some extra nested test vectors) |
| // Unclosed indefinite array containing a closed definite length array |
| { {(uint8_t[]){0x9f, 0x80, 0x00}, 3}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Definite length array containing an unclosed indefinite length array |
| { {(uint8_t[]){0x81, 0x9f}, 2}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Unclosed indefinite map containing a closed definite length array |
| { {(uint8_t[]){0xbf, 0x01, 0x80, 0x00, 0xa0}, 5}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Definite length map containing an unclosed indefinite length array |
| { {(uint8_t[]){0xa1, 0x02, 0x9f}, 3}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Deeply nested definite length arrays with deepest one unclosed |
| { {(uint8_t[]){0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81}, 9}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Deeply nested indefinite length arrays with deepest one unclosed |
| { {(uint8_t[]){0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 9}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Mixed nesting with indefinite unclosed |
| { {(uint8_t[]){0x9f, 0x81, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff}, 9}, QCBOR_ERR_NO_MORE_ITEMS }, |
| // Mixed nesting with definite unclosed |
| { {(uint8_t[]){0x9f, 0x82, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 10}, QCBOR_ERR_BAD_BREAK }, |
| // Unclosed indefinite length map in definite length maps |
| { {(uint8_t[]){0xa1, 0x01, 0xa2, 0x02, 0xbf, 0xff, 0x02, 0xbf}, 8}, |
| QCBOR_ERR_NO_MORE_ITEMS}, |
| // Unclosed definite length map in indefinite length maps |
| { {(uint8_t[]){0xbf, 0x01, 0xbf, 0x02, 0xa1}, 5}, QCBOR_ERR_NO_MORE_ITEMS}, |
| // Unclosed indefinite length array in definite length maps |
| { {(uint8_t[]){0xa1, 0x01, 0xa2, 0x02, 0x9f, 0xff, 0x02, 0x9f}, 8}, |
| QCBOR_ERR_NO_MORE_ITEMS}, |
| // Unclosed definite length array in indefinite length maps |
| { {(uint8_t[]){0xbf, 0x01, 0xbf, 0x02, 0x81}, 5}, QCBOR_ERR_NO_MORE_ITEMS}, |
| // Unclosed indefinite length map in definite length arrays |
| { {(uint8_t[]){0x81, 0x82, 0xbf, 0xff, 0xbf}, 5}, QCBOR_ERR_NO_MORE_ITEMS}, |
| // Unclosed definite length map in indefinite length arrays |
| { {(uint8_t[]){0x9f, 0x9f, 0xa1}, 3}, QCBOR_ERR_NO_MORE_ITEMS}, |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| // 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 }, |
| // half-precision with 1 byte argument |
| { {(uint8_t[]){0xf9, 0x00}, 2}, QCBOR_ERR_HIT_END }, |
| // single-precision with 2 byte argument |
| { {(uint8_t[]){0xfa, 0x00, 0x00}, 3}, QCBOR_ERR_HIT_END }, |
| // double-precision with 3 byte argument |
| { {(uint8_t[]){0xfb, 0x00, 0x00, 0x00}, 4}, QCBOR_ERR_HIT_END }, |
| |
| |
| // Tag with no content |
| { {(uint8_t[]){0xc0}, 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 differently |
| { {(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 }, |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| // A bare break after a zero length indefinite length map |
| { {(uint8_t[]){0x9f, 0xff, 0xff}, 3}, QCBOR_ERR_BAD_BREAK }, |
| // A break inside a definite length array inside an indefenite length array |
| { {(uint8_t[]){0x9f, 0x81, 0xff}, 3}, QCBOR_ERR_BAD_BREAK }, |
| // Complicated mixed nesting with break outside indefinite length array |
| { {(uint8_t[]){0x9f, 0x82, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 10}, QCBOR_ERR_BAD_BREAK }, |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| // 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 }, |
| // Reserved |
| { {(uint8_t[]){0xf8, 0x1f}, 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 }, |
| |
| #if SIZE_MAX > 2147483647 |
| // Byte string should have 2^32-15 bytes, but has one |
| { {(uint8_t[]){0x5a, 0xff, 0xff, 0xff, 0xf0, 0x00}, 6}, QCBOR_ERR_HIT_END }, |
| // Byte string should have 2^32-15 bytes, but has one |
| { {(uint8_t[]){0x7a, 0xff, 0xff, 0xff, 0xf0, 0x00}, 6}, QCBOR_ERR_HIT_END }, |
| // Byte string should have 2^64 bytes, but has 3 |
| { {(uint8_t[]){0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0x01, 0x02, 0x03}, 6}, QCBOR_ERR_HIT_END }, |
| // Text string should have 2^64 bytes, but has 3 |
| { {(uint8_t[]){0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0x01, 0x02, 0x03}, 6}, QCBOR_ERR_HIT_END }, |
| #else |
| // Byte string should have 2^32-15 bytes, but has one |
| { {(uint8_t[]){0x5a, 0x00, 0x00, 0xff, 0xf0, 0x00}, 6}, QCBOR_ERR_HIT_END }, |
| // Byte string should have 2^32-15 bytes, but has one |
| { {(uint8_t[]){0x7a, 0x00, 0x00, 0xff, 0xf0, 0x00}, 6}, QCBOR_ERR_HIT_END }, |
| // Byte string should have 2^16 bytes, but has 3 |
| { {(uint8_t[]){0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03}, 6}, QCBOR_ERR_HIT_END }, |
| // Text string should have 2^64 bytes, but has 3 |
| { {(uint8_t[]){0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03}, 6}, QCBOR_ERR_HIT_END }, |
| #endif |
| |
| // 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 }, |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| // 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 }, |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| // In addition to not-well-formed, some invalid CBOR |
| // Text-based date, with an integer |
| { {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, |
| // Epoch date, with an byte string |
| { {(uint8_t[]){0xc1, 0x41, 0x33}, 3}, QCBOR_ERR_BAD_OPT_TAG }, |
| // tagged as both epoch and string dates |
| { {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_BAD_OPT_TAG }, |
| // big num tagged an int, not a byte string |
| { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, |
| }; |
| |
| int32_t DecodeFailureTests() |
| { |
| int32_t nResult; |
| |
| nResult = ProcessFailures(Failures,C_ARRAY_COUNT(Failures,struct FailInput)); |
| if(nResult) { |
| return nResult; |
| } |
| |
| // Corrupt the UsefulInputBuf and see that |
| // it reflected correctly for CBOR decoding |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError uQCBORError; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| if((uQCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)uQCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 10) { |
| // This wasn't supposed to happen |
| return -1; |
| } |
| |
| DCtx.InBuf.magic = 0; // Reach in and corrupt the UsefulInputBuf |
| |
| uQCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uQCBORError != QCBOR_ERR_NO_MORE_ITEMS) { |
| // Did not get back the error expected |
| return -2; |
| } |
| |
| |
| /* |
| The max size of a string for QCBOR is SIZE_MAX - 4 so this |
| tests here can be performed to see that the max length |
| error check works correctly. See DecodeBytes(). If the max |
| size was SIZE_MAX, it wouldn't be possible to test this. |
| |
| This test will automatocally adapt the all CPU sizes |
| through the use of SIZE_MAX. |
| */ |
| |
| UsefulBuf_MAKE_STACK_UB( HeadBuf, QCBOR_HEAD_BUFFER_SIZE); |
| UsefulBufC EncodedHead; |
| |
| // This makes a CBOR head with a text string that is very long |
| // but doesn't fill in the bytes of the text string as that is |
| // not needed to test this part of QCBOR. |
| EncodedHead = QCBOREncode_EncodeHead(HeadBuf, CBOR_MAJOR_TYPE_TEXT_STRING, 0, SIZE_MAX); |
| |
| QCBORDecode_Init(&DCtx, EncodedHead, QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBOR_ERR_STRING_TOO_LONG != QCBORDecode_GetNext(&DCtx, &Item)) { |
| return -4; |
| } |
| |
| return 0; |
| } |
| |
| |
| /* Try all 256 values of the byte at nLen including recursing for |
| each of the values to try values at nLen+1 ... up to nLenMax |
| */ |
| static void ComprehensiveInputRecurser(uint8_t *pBuf, size_t nLen, size_t nLenMax) |
| { |
| if(nLen >= nLenMax) { |
| return; |
| } |
| |
| for(int inputByte = 0; inputByte < 256; inputByte++) { |
| // Set up the input |
| pBuf[nLen] = (uint8_t)inputByte; |
| const UsefulBufC Input = {pBuf, nLen+1}; |
| |
| // Get ready to parse |
| QCBORDecodeContext DCtx; |
| QCBORDecode_Init(&DCtx, Input, QCBOR_DECODE_MODE_NORMAL); |
| |
| // Parse by getting the next item until an error occurs |
| // Just about every possible decoder error can occur here |
| // The goal of this test is not to check for the correct |
| // error since that is not really possible. It is to |
| // see that there is no crash on hostile input. |
| while(1) { |
| QCBORItem Item; |
| QCBORError nCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(nCBORError != QCBOR_SUCCESS) { |
| break; |
| } |
| } |
| |
| ComprehensiveInputRecurser(pBuf, nLen+1, nLenMax); |
| } |
| } |
| |
| |
| int32_t ComprehensiveInputTest() |
| { |
| // Size 2 tests 64K inputs and runs quickly |
| uint8_t pBuf[2]; |
| |
| ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf)); |
| |
| return 0; |
| } |
| |
| |
| int32_t BigComprehensiveInputTest() |
| { |
| // size 3 tests 16 million inputs and runs OK |
| // in seconds on fast machines. Size 4 takes |
| // 10+ minutes and 5 half a day on fast |
| // machines. This test is kept separate from |
| // the others so as to no slow down the use |
| // of them as a very frequent regression. |
| uint8_t pBuf[3]; // |
| |
| ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf)); |
| |
| return 0; |
| } |
| |
| |
| static const uint8_t spDateTestInput[] = { |
| 0xc0, // tag for string date |
| 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string |
| |
| 0xc0, // tag for string date |
| 0x00, // Wrong type for a string date |
| |
| 0xc1, // tag for epoch date |
| 0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT |
| |
| 0xc1, |
| 0x62, 'h', 'i', // wrong type tagged |
| |
| // CBOR_TAG_ENC_AS_B64 |
| 0xcf, 0xd8, 0x16, 0xc1, // 0xee, // Epoch date with extra tags |
| 0x1a, 0x53, 0x72, 0x4E, 0x01, |
| |
| 0xc1, // tag for epoch date |
| 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer |
| |
| 0xc1, // tag for epoch date |
| 0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // single with value 1.1 |
| |
| 0xc1, // tag for epoch date |
| 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 |
| |
| 0xc1, // tag for epoch date |
| 0xfa, 0x7f, 0xc0, 0x00, 0x00, // Single-precision NaN |
| |
| 0xc1, |
| 0xfb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // +infinity |
| |
| 0xc1, // tag for epoch date |
| 0xf9, 0xfc, 0x00, // -Infinity |
| }; |
| |
| |
| |
| // have to check float expected only to within an epsilon |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| static int CHECK_EXPECTED_DOUBLE(double val, double expected) { |
| |
| double diff = val - expected; |
| |
| diff = fabs(diff); |
| |
| return diff > 0.0000001; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| |
| |
| int32_t DateParseTest() |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError uError; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| // String date |
| if((uError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return -1; |
| } |
| if(Item.uDataType != QCBOR_TYPE_DATE_STRING || |
| UsefulBufCompareToSZ(Item.val.dateString, "1985-04-12")){ |
| return -2; |
| } |
| |
| // Wrong type for a string date |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError != QCBOR_ERR_BAD_OPT_TAG) { |
| return -3; |
| } |
| |
| // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT |
| if((uError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return -4; |
| } |
| if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || |
| Item.val.epochDate.nSeconds != 1400000000 || |
| Item.val.epochDate.fSecondsFraction != 0 ) { |
| return -5; |
| } |
| |
| // Wrong type for an epoch date |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_OPT_TAG) { |
| return -6; |
| } |
| |
| // Epoch date wrapped in an CBOR_TAG_ENC_AS_B64 and an unknown tag. |
| // The date is decoded and the two tags are returned. This is to |
| // make sure the wrapping of epoch date in another tag works OK. |
| if((uError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return -7; |
| } |
| if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || |
| Item.val.epochDate.nSeconds != 1400000001 || |
| Item.val.epochDate.fSecondsFraction != 0 || |
| !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_ENC_AS_B64)) { |
| return -8; |
| } |
| |
| // Epoch date that is too large for our representation |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { |
| return -9; |
| } |
| |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| // Epoch date in float format with fractional seconds |
| if((uError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return -10; |
| } |
| if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || |
| Item.val.epochDate.nSeconds != 1 || |
| CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) { |
| return -11; |
| } |
| |
| // Epoch date float that is too large for our representation |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { |
| return -12; |
| } |
| |
| // Epoch date double that is just slightly too large |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { |
| return -13; |
| } |
| |
| // 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 -14; |
| } |
| |
| // Nan |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { |
| return -15; |
| } |
| |
| // +Inifinity double-precision |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { |
| return -16; |
| } |
| |
| #ifndef QCBOR_DISABLE_PREFERRED_FLOAT |
| // -Inifinity half-precision |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { |
| return -17; |
| } |
| #else |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_HALF_PRECISION_DISABLED) { |
| return -18; |
| } |
| #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -19; |
| } |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -20; |
| } |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -21; |
| } |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -22; |
| } |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -23; |
| } |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -24; |
| } |
| #ifndef QCBOR_DISABLE_PREFERRED_FLOAT |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return -25; |
| } |
| #else |
| if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_HALF_PRECISION_DISABLED) { |
| return -26; |
| } |
| #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| return 0; |
| } |
| |
| /* |
| Test cases covered here. Some items cover more than one of these. |
| positive integer (zero counts as a positive integer) |
| negative integer |
| half-precision float |
| single-precision float |
| double-precision float |
| |
| float Overflow error |
| Wrong type error for epoch |
| Wrong type error for date string |
| float disabled error |
| half-precision disabled error |
| -Infinity |
| Slightly too large integer |
| Slightly too far from zero |
| |
| Get epoch by int |
| Get string by int |
| Get epoch by string |
| Get string by string |
| Fail to get epoch by wrong int label |
| Fail to get string by wrong string label |
| Fail to get epoch by string because it is invalid |
| Fail to get epoch by int because it is invalid |
| |
| Untagged values |
| */ |
| static const uint8_t spSpiffyDateTestInput[] = { |
| 0x86, |
| |
| 0xc1, |
| 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // -9.2233720368547748E+18, too negative |
| |
| 0xc1, // tag for epoch date |
| 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too-large integer |
| |
| 0xc1, // tag for epoch date |
| 0xf9, 0xfc, 0x00, // Half-precision -Infinity |
| |
| 0xc1, // tag for epoch date |
| 0x80, // Erroneous empty array as content for date |
| |
| 0xc0, // tag for string date |
| 0xa0, // Erroneous empty map as content for date |
| |
| 0xa9, // Open a map for tests involving labels. |
| |
| 0x00, |
| 0xc0, // tag for string date |
| 0x6a, '1','9','8','5','-','0','4','-','1','2', // Tagged date string |
| |
| 0x01, |
| 0xda, 0x03, 0x03, 0x03, 0x03, // An additional tag |
| 0xc1, // tag for epoch date |
| 0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT |
| |
| // Untagged integer 0 |
| 0x08, |
| 0x00, |
| |
| // Utagged date string with string label y |
| 0x61, 0x79, |
| 0x6a, '2','0','8','5','-','0','4','-','1','2', // Untagged date string |
| |
| // Untagged -1000 with label z |
| 0x61, 0x7a, |
| 0xda, 0x01, 0x01, 0x01, 0x01, // An additional tag |
| 0x39, 0x03, 0xe7, |
| |
| 0x07, |
| 0xc1, // tag for epoch date |
| 0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // 9223372036854773760 largest supported |
| |
| 0x05, |
| 0xc1, |
| 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // -9223372036854773760 largest negative |
| |
| // Untagged single-precision float with value 3.14 with string label x |
| 0x61, 0x78, |
| 0xFA, 0x40, 0x48, 0xF5, 0xC3, |
| |
| // Untagged half-precision float with value -2 |
| 0x09, |
| 0xF9, 0xC0, 0x00, |
| }; |
| |
| int32_t SpiffyDateDecodeTest() |
| { |
| QCBORDecodeContext DC; |
| QCBORError uError; |
| int64_t nEpochDate2, nEpochDate3, nEpochDate5, |
| nEpochDate4, nEpochDate6, nEpochDateFail, |
| nEpochDate1400000000; |
| UsefulBufC StringDate1, StringDate2; |
| uint64_t uTag1, uTag2; |
| |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyDateTestInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_EnterArray(&DC, NULL); |
| |
| // Too-negative float, -9.2233720368547748E+18 |
| QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| if(uError != QCBOR_ERR_DATE_OVERFLOW) { |
| return 1111; |
| } |
| #else |
| if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return 1112; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| // Too-large integer |
| QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_DATE_OVERFLOW) { |
| return 1; |
| } |
| |
| // Half-precision minus infinity |
| QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| #ifndef QCBOR_DISABLE_PREFERRED_FLOAT |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_DATE_OVERFLOW; |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_FLOAT_DATE_DISABLED; |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| #else /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_HALF_PRECISION_DISABLED; |
| #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| if(uError != uExpectedforHalfMinusInfinity) { |
| return 2; |
| } |
| |
| // Bad content for epoch date |
| QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_BAD_OPT_TAG) { |
| return 3; |
| } |
| |
| // Bad content for string date |
| QCBORDecode_GetDateString(&DC, QCBOR_TAG_REQUIREMENT_TAG, &StringDate1); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_BAD_OPT_TAG) { |
| return 4; |
| } |
| |
| QCBORDecode_EnterMap(&DC, NULL); |
| |
| // Get largest negative double precision epoch date allowed |
| QCBORDecode_GetEpochDateInMapN(&DC, |
| 5, |
| QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG | |
| QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS, |
| &nEpochDate2); |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| if(nEpochDate2 != -9223372036854773760LL) { |
| return 101; |
| } |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return 102; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| // Get largest double precision epoch date allowed |
| QCBORDecode_GetEpochDateInMapN(&DC, 7, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, |
| &nEpochDate2); |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| if(nEpochDate2 != 9223372036854773760ULL) { |
| return 111; |
| } |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return 112; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| // A single-precision date |
| QCBORDecode_GetEpochDateInMapSZ(&DC, "x", QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, |
| &nEpochDate5); |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| if(nEpochDate5 != 3) { |
| return 103; |
| } |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return 104; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| // A half-precision date with value -2 FFF |
| QCBORDecode_GetEpochDateInMapN(&DC, 9, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, |
| &nEpochDate4); |
| #if !defined(QCBOR_DISABLE_FLOAT_HW_USE) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT) |
| if(nEpochDate4 != -2) { |
| return 105; |
| } |
| #else |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError == QCBOR_SUCCESS) { |
| return 106; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| |
| // Fail to get an epoch date by string label |
| QCBORDecode_GetEpochDateInMapSZ(&DC, "no-label", |
| QCBOR_TAG_REQUIREMENT_NOT_A_TAG, |
| &nEpochDate6); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 107; |
| } |
| |
| // Fail to get an epoch date by integer label |
| QCBORDecode_GetEpochDateInMapN(&DC, 99999, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, |
| &nEpochDate6); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 108; |
| } |
| |
| // Fail to get a string date by string label |
| QCBORDecode_GetDateStringInMapSZ(&DC, "no-label", |
| QCBOR_TAG_REQUIREMENT_NOT_A_TAG, |
| &StringDate1); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 109; |
| } |
| |
| // Fail to get a string date by integer label |
| QCBORDecode_GetDateStringInMapN(&DC, 99999, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, |
| &StringDate1); |
| uError = QCBORDecode_GetAndResetError(&DC); |
| if(uError != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 110; |
| } |
| |
| // The rest of these succeed even if float features are disabled |
| |
| // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT |
| QCBORDecode_GetEpochDateInMapN(&DC, |
| 1, |
| QCBOR_TAG_REQUIREMENT_TAG | |
| QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS, |
| &nEpochDate1400000000); |
| uTag1 = QCBORDecode_GetNthTagOfLast(&DC, 0); |
| // Tagged date string |
| QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, |
| &StringDate1); |
| // Untagged integer 0 |
| QCBORDecode_GetEpochDateInMapN(&DC, 8, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, |
| &nEpochDate3); |
| // Untagged date string |
| QCBORDecode_GetDateStringInMapSZ(&DC, "y", QCBOR_TAG_REQUIREMENT_NOT_A_TAG, |
| &StringDate2); |
| // Untagged -1000 with label z |
| QCBORDecode_GetEpochDateInMapSZ(&DC, |
| "z", |
| QCBOR_TAG_REQUIREMENT_NOT_A_TAG | |
| QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS, |
| &nEpochDate6); |
| uTag2 = QCBORDecode_GetNthTagOfLast(&DC, 0); |
| |
| QCBORDecode_ExitMap(&DC); |
| QCBORDecode_ExitArray(&DC); |
| uError = QCBORDecode_Finish(&DC); |
| if(uError) { |
| return 1000 + (int32_t)uError; |
| } |
| |
| if(nEpochDate1400000000 != 1400000000) { |
| return 200; |
| } |
| |
| if(uTag1 != 0x03030303) { |
| return 201; |
| } |
| |
| if(nEpochDate3 != 0) { |
| return 202; |
| } |
| |
| if(nEpochDate6 != -1000) { |
| return 203; |
| } |
| |
| if(uTag2 != 0x01010101) { |
| return 204; |
| } |
| |
| if(UsefulBuf_Compare(StringDate1, UsefulBuf_FromSZ("1985-04-12"))) { |
| return 205; |
| } |
| |
| if(UsefulBuf_Compare(StringDate2, UsefulBuf_FromSZ("2085-04-12"))) { |
| return 206; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| // Input for one of the tagging tests |
| static const uint8_t spTagInput[] = { |
| 0xd9, 0xd9, 0xf7, // CBOR magic number |
| 0x81, // Array of one |
| 0xd8, 0x04, // non-preferred serialization of tag 4, decimal fraction |
| 0x82, // Array of two that is the faction 1/3 |
| 0x01, |
| 0x03, |
| |
| /* |
| More than 4 tags on an item 225(226(227(228(229([]))))) |
| */ |
| 0xd8, 0xe1, |
| 0xd8, 0xe2, |
| 0xd8, 0xe3, |
| 0xd8, 0xe4, |
| 0xd8, 0xe5, |
| 0x80, |
| |
| /* tag 10489608748473423768( |
| 2442302356( |
| 21590( |
| 240( |
| [])))) |
| */ |
| 0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0xda, 0x91, 0x92, 0x93, 0x94, |
| 0xd9, 0x54, 0x56, |
| 0xd8, 0xf0, |
| 0x80, |
| |
| /* tag 21590( |
| 10489608748473423768( |
| 2442302357( |
| 65534( |
| [])))) |
| */ |
| 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x56, |
| 0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0xda, 0x91, 0x92, 0x93, 0x95, |
| 0xd9, 0xff, 0xfe, |
| 0x80, |
| |
| /* Make sure to blow past the limit of tags that must be mapped. |
| works in conjuntion with entries above. |
| 269488144(269488145(269488146(269488147([])))) |
| */ |
| 0xda, 0x10, 0x10, 0x10, 0x10, |
| 0xda, 0x10, 0x10, 0x10, 0x11, |
| 0xda, 0x10, 0x10, 0x10, 0x12, |
| 0xda, 0x10, 0x10, 0x10, 0x13, |
| 0x80, |
| |
| /* An invalid decimal fraction with an additional tag */ |
| 0xd9, 0xff, 0xfa, |
| 0xd8, 0x02, // non-preferred serialization of tag 2, a big num |
| 0x00, // the integer 0; should be a byte string |
| }; |
| |
| /* |
| DB 9192939495969798 # tag(10489608748473423768) |
| 80 # array(0) |
| */ |
| static const uint8_t spEncodedLargeTag[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, |
| 0x96, 0x97, 0x98, 0x80}; |
| |
| /* |
| DB 9192939495969798 # tag(10489608748473423768) |
| D8 88 # tag(136) |
| C6 # tag(6) |
| C7 # tag(7) |
| 80 # array(0) |
| */ |
| static const uint8_t spLotsOfTags[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, |
| 0x97, 0x98, 0xd8, 0x88, 0xc6, 0xc7, 0x80}; |
| |
| /* |
| 55799(55799(55799({ |
| 6(7(-23)): 5859837686836516696(7({ |
| 7(-20): 11({ |
| 17(-18): 17(17(17("Organization"))), |
| 9(-17): 773("SSG"), |
| -15: 16(17(6(7("Confusion")))), |
| 17(-16): 17("San Diego"), |
| 17(-14): 17("US") |
| }), |
| 23(-19): 19({ |
| -11: 9({ |
| -9: -7 |
| }), |
| 90599561(90599561(90599561(-10))): 12(h'0102030405060708090A') |
| }) |
| })), |
| 16(-22): 23({ |
| 11(8(7(-5))): 8(-3) |
| }) |
| }))) |
| */ |
| static const uint8_t spCSRWithTags[] = { |
| 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xa2, |
| 0xc6, 0xc7, 0x36, |
| 0xdb, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0xc7, 0xa2, |
| 0xda, 0x00, 0x00, 0x00, 0x07, 0x33, |
| 0xcb, 0xa5, |
| 0xd1, 0x31, |
| 0xd1, 0xd1, 0xd1, 0x6c, |
| 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, |
| 0xc9, 0x30, |
| 0xd9, 0x03, 0x05, 0x63, |
| 0x53, 0x53, 0x47, |
| 0x2e, |
| 0xd0, 0xd1, 0xc6, 0xc7, |
| 0x69, |
| 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, |
| 0xd1, 0x2f, |
| 0xd1, 0x69, |
| 0x53, 0x61, 0x6e, 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, |
| 0xd1, 0x2d, |
| 0xd1, 0x62, |
| 0x55, 0x53, |
| 0xd7, 0x32, |
| 0xd3, 0xa2, |
| 0x2a, |
| 0xc9, 0xa1, |
| 0x28, |
| 0x26, |
| 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0x29, |
| 0xcc, 0x4a, |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,0x07, 0x08, 0x09, 0x0a, |
| 0xd0, 0x35, |
| 0xd7, 0xa1, |
| 0xcb, 0xc8, 0xc7, 0x24, |
| 0xc8, 0x22}; |
| |
| |
| static const uint8_t spSpiffyTagInput[] = { |
| 0x85, // Open array |
| |
| 0xc0, // tag for string date |
| 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string |
| |
| 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string |
| |
| 0x4a, '1','9','8','5','-','0','4','-','1','2', // Date string in byte string |
| |
| 0xd8, 0x23, // tag for regex |
| 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string |
| |
| 0xc0, // tag for string date |
| 0x4a, '1','9','8','5','-','0','4','-','1','2', // Date string in byte string |
| }; |
| |
| |
| static int32_t CheckCSRMaps(QCBORDecodeContext *pDC); |
| |
| |
| int32_t OptTagParseTest() |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError uError; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTagInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| /* |
| This test matches the magic number tag and the fraction tag |
| 55799([...]) |
| */ |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError != QCBOR_SUCCESS) { |
| return -2; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || |
| !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC)) { |
| return -3; |
| } |
| |
| /* |
| 4([1,3]) |
| */ |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| #ifdef QCBOR_DISABLE_EXP_AND_MANTISSA |
| if(uError != QCBOR_SUCCESS || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DECIMAL_FRACTION) || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 0) != CBOR_TAG_DECIMAL_FRACTION || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 1) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 2) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 3) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 4) != CBOR_TAG_INVALID64 || |
| Item.val.uCount != 2) { |
| return -4; |
| } |
| // consume the items in the array |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| if(uError != QCBOR_SUCCESS || |
| Item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 0) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 1) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 2) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 3) != CBOR_TAG_INVALID64 || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 4) != CBOR_TAG_INVALID64 ) { |
| return -5; |
| } |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| |
| /* |
| More than 4 tags on an item 225(226(227(228(229([]))))) |
| */ |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError != QCBOR_ERR_TOO_MANY_TAGS) { |
| return -6; |
| } |
| |
| if(QCBORDecode_GetNthTag(&DCtx, &Item, 0) != CBOR_TAG_INVALID64) { |
| return -106; |
| } |
| |
| |
| /* tag 10489608748473423768( |
| 2442302356( |
| 21590( |
| 240( |
| [])))) |
| */ |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError != QCBOR_SUCCESS || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 3) != 10489608748473423768ULL || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 2) != 2442302356ULL || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 1) != 21590ULL || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 0) != 240ULL) { |
| return -7; |
| } |
| |
| /* tag 21590( |
| 10489608748473423768( |
| 2442302357( |
| 21591( |
| [])))) |
| */ |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError != QCBOR_SUCCESS || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 0) != 65534ULL || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 1) != 2442302357ULL || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 2) != 10489608748473423768ULL || |
| QCBORDecode_GetNthTag(&DCtx, &Item, 3) != 21590ULL) { |
| return -8; |
| } |
| |
| /* Make sure to blow past the limit of tags that must be mapped. |
| works in conjuntion with entries above. |
| 269488144(269488145(269488146(269488147([])))) |
| */ |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError != QCBOR_ERR_TOO_MANY_TAGS) { |
| return -9; |
| } |
| |
| uError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uError == QCBOR_SUCCESS) { |
| return -10; |
| } |
| |
| // ---------------------------------- |
| // This test sets up a caller-config list that includes the very large |
| // tage and then matches it. Caller-config lists are no longer |
| // used or needed. This tests backwards compatibility with them. |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), |
| QCBOR_DECODE_MODE_NORMAL); |
| const uint64_t puList[] = {0x9192939495969798, 257}; |
| const QCBORTagListIn TL = {2, puList}; |
| QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TL); |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item)) { |
| return -8; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 0x9192939495969798) || |
| QCBORDecode_IsTagged(&DCtx, &Item, 257) || |
| QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_BIGFLOAT) || |
| Item.val.uCount != 0) { |
| return -9; |
| } |
| |
| //------------------------ |
| // Sets up a caller-configured list and look up something not in it |
| // Another backwards compatibility test. |
| const uint64_t puLongList[17] = {1,2,1}; |
| const QCBORTagListIn TLLong = {17, puLongList}; |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), |
| QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TLLong); |
| if(QCBORDecode_GetNext(&DCtx, &Item)) { |
| return -11; |
| } |
| |
| uint64_t puTags[4]; |
| QCBORTagListOut Out = {0, 4, puTags}; |
| |
| |
| // This tests retrievel of the full tag list |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), |
| QCBOR_DECODE_MODE_NORMAL); |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -12; |
| } |
| if(puTags[0] != 0x9192939495969798 || |
| puTags[1] != 0x88 || |
| puTags[2] != 0x06 || |
| puTags[3] != 0x07) { |
| return -13; |
| } |
| |
| // ---------------------- |
| // This tests too small of an out list |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), |
| QCBOR_DECODE_MODE_NORMAL); |
| QCBORTagListOut OutSmall = {0, 3, puTags}; |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &OutSmall) != QCBOR_ERR_TOO_MANY_TAGS) { |
| return -14; |
| } |
| |
| |
| |
| // --------------- |
| // Decode a version of the "CSR" that has had a ton of tags randomly inserted |
| // It is a bit of a messy test and maybe could be improved, but |
| // it is retained as a backwards compatibility check. |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), |
| QCBOR_DECODE_MODE_NORMAL); |
| int n = CheckCSRMaps(&DCtx); |
| if(n) { |
| return n-2000; |
| } |
| |
| Out = (QCBORTagListOut){0, 16, puTags}; |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| /* With the spiffy decode revision, this tag list is not used. |
| It doesn't matter if a tag is in this list or not so some |
| tests that couldn't process a tag because it isn't in this list |
| now can process these unlisted tags. The tests have been |
| adjusted for this. */ |
| const uint64_t puTagList[] = {773, 1, 90599561}; |
| const QCBORTagListIn TagList = {3, puTagList}; |
| QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList); |
| |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -100; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) || |
| QCBORDecode_IsTagged(&DCtx, &Item, 90599561) || |
| QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DATE_EPOCH) || |
| Item.val.uCount != 2 || |
| puTags[0] != CBOR_TAG_CBOR_MAGIC || |
| puTags[1] != CBOR_TAG_CBOR_MAGIC || |
| puTags[2] != CBOR_TAG_CBOR_MAGIC || |
| Out.uNumUsed != 3) { |
| return -101; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -102; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) || |
| QCBORDecode_IsTagged(&DCtx, &Item, 6) || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 7) || |
| Item.val.uCount != 2 || |
| puTags[0] != 5859837686836516696 || |
| puTags[1] != 7 || |
| Out.uNumUsed != 2) { |
| return -103; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -104; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 5 || |
| puTags[0] != 0x0b || |
| Out.uNumUsed != 1) { |
| return -105; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -106; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_COSE_MAC0) || |
| Item.val.string.len != 12 || |
| puTags[0] != CBOR_TAG_COSE_MAC0 || |
| puTags[1] != CBOR_TAG_COSE_MAC0 || |
| puTags[2] != CBOR_TAG_COSE_MAC0 || |
| Out.uNumUsed != 3) { |
| return -105; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -107; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 773) || |
| Item.val.string.len != 3 || |
| puTags[0] != 773 || |
| Out.uNumUsed != 1) { |
| return -108; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -109; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 16) || |
| Item.val.string.len != 9 || |
| puTags[0] != 16 || |
| puTags[3] != 7 || |
| Out.uNumUsed != 4) { |
| return -110; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -111; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 17) || |
| Item.val.string.len != 9 || |
| puTags[0] != 17 || |
| Out.uNumUsed != 1) { |
| return -112; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -111; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 17) || |
| Item.val.string.len != 2 || |
| puTags[0] != 17 || |
| Out.uNumUsed != 1) { |
| return -112; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -113; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 19) || |
| Item.val.uCount != 2 || |
| puTags[0] != 19 || |
| Out.uNumUsed != 1) { |
| return -114; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -115; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 9) || |
| Item.val.uCount != 1 || |
| puTags[0] != 9 || |
| Out.uNumUsed != 1) { |
| return -116; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -116; |
| } |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != -7 || |
| Out.uNumUsed != 0) { |
| return -117; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -118; |
| } |
| if(Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.val.string.len != 10 || |
| puTags[0] != 12 || |
| Out.uNumUsed != 1) { |
| return -119; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -120; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_ENC_AS_B16) || |
| Item.val.uCount != 1 || |
| puTags[0] != 0x17 || |
| Out.uNumUsed != 1) { |
| return -121; |
| } |
| |
| if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { |
| return -122; |
| } |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| !QCBORDecode_IsTagged(&DCtx, &Item, 8) || |
| Item.val.int64 != -3 || |
| puTags[0] != 8 || |
| Out.uNumUsed != 1) { |
| return -123; |
| } |
| |
| if(QCBORDecode_Finish(&DCtx)) { |
| return -124; |
| } |
| |
| UsefulBufC DateString; |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyTagInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| // tagged date string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_TAG, &DateString); |
| // untagged date string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_SUCCESS) { |
| return 100; |
| } |
| // untagged byte string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 101; |
| } |
| // tagged regex |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 102; |
| } |
| // tagged date string with a byte string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_BAD_OPT_TAG) { |
| return 103; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_SUCCESS) { |
| return 104; |
| } |
| |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyTagInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| // tagged date string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &DateString); |
| // untagged date string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_SUCCESS) { |
| return 200; |
| } |
| // untagged byte string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 201; |
| } |
| // tagged regex |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 202; |
| } |
| // tagged date string with a byte string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_BAD_OPT_TAG) { |
| return 203; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_SUCCESS) { |
| return 204; |
| } |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyTagInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| // tagged date string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 300; |
| } |
| // untagged date string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 301; |
| } |
| // untagged byte string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 302; |
| } |
| // tagged regex |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 303; |
| } |
| // tagged date string with a byte string |
| QCBORDecode_GetDateString(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &DateString); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_BAD_OPT_TAG) { |
| return 304; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| if(QCBORDecode_Finish(&DCtx) != QCBOR_SUCCESS) { |
| return 305; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| static const uint8_t spBigNumInput[] = { |
| 0x83, |
| 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0xA4, |
| 0x63, 0x42, 0x4E, 0x2B, |
| 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x18, 0x40, |
| 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x63, 0x42, 0x4E, 0x2D, |
| 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x38, 0x3F, |
| 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| /* The expected big num */ |
| static const uint8_t spBigNum[] = { |
| 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00}; |
| |
| |
| int32_t BignumParseTest() |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| |
| // |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -1; |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -2; |
| } |
| |
| // |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -3; |
| if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || |
| UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ |
| return -4; |
| } |
| |
| // |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -5; |
| if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || |
| UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ |
| return -6; |
| } |
| |
| // |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -7; |
| if(Item.uDataType != QCBOR_TYPE_MAP) { |
| return -8; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -9; |
| if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || |
| Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ |
| return -10; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -11; |
| if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || |
| Item.uLabelType != QCBOR_TYPE_INT64 || |
| Item.label.int64 != 64 || |
| UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ |
| return -12; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -13; |
| if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || |
| Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ |
| return -14; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) |
| return -15; |
| if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || |
| Item.uLabelType != QCBOR_TYPE_INT64 || |
| Item.label.int64 != -64 || |
| UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ |
| return -16; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| static int32_t CheckItemWithIntLabel(QCBORDecodeContext *pCtx, |
| uint8_t uDataType, |
| uint8_t uNestingLevel, |
| uint8_t uNextNest, |
| int64_t nLabel, |
| QCBORItem *pItem) |
| { |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| if((nCBORError = QCBORDecode_GetNext(pCtx, &Item))) return -1; |
| if(Item.uDataType != uDataType) return -1; |
| if(uNestingLevel > 0) { |
| if(Item.uLabelType != QCBOR_TYPE_INT64 && |
| Item.uLabelType != QCBOR_TYPE_UINT64) { |
| return -1; |
| } |
| if(Item.uLabelType == QCBOR_TYPE_INT64) { |
| if(Item.label.int64 != nLabel) return -1; |
| } else { |
| if(Item.label.uint64 != (uint64_t)nLabel) return -1; |
| } |
| } |
| if(Item.uNestingLevel != uNestingLevel) return -1; |
| if(Item.uNextNestLevel != uNextNest) return -1; |
| |
| if(pItem) { |
| *pItem = Item; |
| } |
| return 0; |
| } |
| |
| |
| // Same code checks definite and indefinite length versions of the map |
| static int32_t CheckCSRMaps(QCBORDecodeContext *pDC) |
| { |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 0, 1, 0, NULL)) return -1; |
| |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 1, 2, -23, NULL)) return -2; |
| |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 2, 3, -20, NULL)) return -3; |
| |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -18, NULL)) return -4; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -17, NULL)) return -5; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -15, NULL)) return -6; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -16, NULL)) return -7; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 2, -14, NULL)) return -8; |
| |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 2, 3, -19, NULL)) return -9; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 3, 4, -11, NULL)) return -10; |
| |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_INT64, 4, 3, -9, NULL)) return -11; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_BYTE_STRING, 3, 1, -10, NULL)) return -12; |
| |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 1, 2, -22, NULL)) return -13; |
| if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_INT64, 2, 0, -5, NULL)) return -14; |
| |
| if(QCBORDecode_Finish(pDC)) return -20; |
| |
| return 0; |
| } |
| |
| |
| /* |
| { |
| -23: { |
| -20: { |
| -18: "Organization", |
| -17: "SSG", |
| -15: "Confusion", |
| -16: "San Diego", |
| -14: "US" |
| }, |
| -19: { |
| -11: { |
| -9: -7 |
| }, |
| -10: '\u0001\u0002\u0003\u0004\u0005\u0006\a\b\t\n' |
| } |
| }, |
| -22: { |
| -5: -3 |
| } |
| } |
| */ |
| static const uint8_t spCSRInput[] = { |
| 0xa2, 0x36, 0xa2, 0x33, 0xa5, 0x31, 0x6c, 0x4f, |
| 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, |
| 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47, |
| 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, |
| 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e, |
| 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62, |
| 0x55, 0x53, 0x32, 0xa2, 0x2a, 0xa1, 0x28, 0x26, |
| 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, |
| 0x07, 0x08, 0x09, 0x0a, 0x35, 0xa1, 0x24, 0x22}; |
| |
| // Same map as above, but using indefinite lengths |
| static const uint8_t spCSRInputIndefLen[] = { |
| 0xbf, 0x36, 0xbf, 0x33, 0xbf, 0x31, 0x6c, 0x4f, |
| 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, |
| 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47, |
| 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, |
| 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e, |
| 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62, |
| 0x55, 0x53, 0xff, 0x32, 0xbf, 0x2a, 0xbf, 0x28, |
| 0x26, 0xff, 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, |
| 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0xff, 0xff, |
| 0x35, 0xbf, 0x24, 0x22, 0xff, 0xff}; |
| |
| |
| int32_t NestedMapTest() |
| { |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| return CheckCSRMaps(&DCtx); |
| } |
| |
| |
| |
| int32_t StringDecoderModeFailTest() |
| { |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), |
| QCBOR_DECODE_MODE_MAP_STRINGS_ONLY); |
| |
| QCBORItem Item; |
| QCBORError nCBORError; |
| |
| if(QCBORDecode_GetNext(&DCtx, &Item)) { |
| return -1; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP) { |
| return -2; |
| } |
| |
| nCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(nCBORError != QCBOR_ERR_MAP_LABEL_TYPE) { |
| return -3; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| int32_t NestedMapTestIndefLen() |
| { |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInputIndefLen), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| return CheckCSRMaps(&DCtx); |
| } |
| |
| |
| |
| static UsefulBufC make_nested_indefinite_arrays(int n, UsefulBuf Storage) |
| { |
| UsefulOutBuf UOB; |
| UsefulOutBuf_Init(&UOB, Storage); |
| |
| int i; |
| for(i = 0; i < n; i++) { |
| UsefulOutBuf_AppendByte(&UOB, 0x9f); |
| } |
| |
| for(i = 0; i < n; i++) { |
| UsefulOutBuf_AppendByte(&UOB, 0xff); |
| } |
| return UsefulOutBuf_OutUBuf(&UOB); |
| } |
| |
| |
| static int32_t parse_indeflen_nested(UsefulBufC Nested, int nNestLevel) |
| { |
| QCBORDecodeContext DC; |
| QCBORDecode_Init(&DC, Nested, 0); |
| |
| int j; |
| for(j = 0; j < nNestLevel; j++) { |
| QCBORItem Item; |
| QCBORError nReturn = QCBORDecode_GetNext(&DC, &Item); |
| if(j >= QCBOR_MAX_ARRAY_NESTING) { |
| // Should be in error |
| if(nReturn != QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP) { |
| return -4; |
| } else { |
| return 0; // Decoding doesn't recover after an error |
| } |
| } else { |
| // Should be no error |
| if(nReturn) { |
| return -9; // Should not have got an error |
| } |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -7; |
| } |
| } |
| QCBORError nReturn = QCBORDecode_Finish(&DC); |
| if(nReturn) { |
| return -3; |
| } |
| return 0; |
| } |
| |
| |
| int32_t IndefiniteLengthNestTest() |
| { |
| UsefulBuf_MAKE_STACK_UB(Storage, 50); |
| int i; |
| for(i=1; i < QCBOR_MAX_ARRAY_NESTING+4; i++) { |
| const UsefulBufC Nested = make_nested_indefinite_arrays(i, Storage); |
| int nReturn = parse_indeflen_nested(Nested, i); |
| if(nReturn) { |
| return nReturn; |
| } |
| } |
| return 0; |
| } |
| |
| // [1, [2, 3]] |
| static const uint8_t spIndefiniteArray[] = {0x9f, 0x01, 0x82, 0x02, 0x03, 0xff}; |
| // No closing break |
| static const uint8_t spIndefiniteArrayBad1[] = {0x9f}; |
| // Not enough closing breaks |
| static const uint8_t spIndefiniteArrayBad2[] = {0x9f, 0x9f, 0x02, 0xff}; |
| // Too many closing breaks |
| static const uint8_t spIndefiniteArrayBad3[] = {0x9f, 0x02, 0xff, 0xff}; |
| // Unclosed indeflen inside def len |
| static const uint8_t spIndefiniteArrayBad4[] = {0x81, 0x9f}; |
| // confused tag |
| static const uint8_t spIndefiniteArrayBad5[] = {0x9f, 0xd1, 0xff}; |
| |
| int32_t IndefiniteLengthArrayMapTest() |
| { |
| QCBORError nResult; |
| // --- first test ----- |
| UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArray); |
| |
| // Decode it and see if it is OK |
| QCBORDecodeContext DC; |
| QCBORItem Item; |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.uNestingLevel != 0 || |
| Item.uNextNestLevel != 1) { |
| return -111; |
| } |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.uNestingLevel != 1 || |
| Item.uNextNestLevel != 1) { |
| return -2; |
| } |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.uNestingLevel != 1 || |
| Item.uNextNestLevel != 2) { |
| return -3; |
| } |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.uNestingLevel != 2 || |
| Item.uNextNestLevel != 2) { |
| return -4; |
| } |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.uNestingLevel != 2 || |
| Item.uNextNestLevel != 0) { |
| return -5; |
| } |
| |
| if(QCBORDecode_Finish(&DC)) { |
| return -6; |
| } |
| |
| // --- next test ----- |
| IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad1); |
| |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -7; |
| } |
| |
| nResult = QCBORDecode_Finish(&DC); |
| if(nResult != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -8; |
| } |
| |
| |
| // --- next test ----- |
| IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad2); |
| |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -9; |
| } |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -10; |
| } |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_INT64) { |
| return -11; |
| } |
| |
| nResult = QCBORDecode_Finish(&DC); |
| if(nResult != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -12; |
| } |
| |
| |
| // --- next test ----- |
| IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad3); |
| |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -13; |
| } |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult != QCBOR_SUCCESS) { |
| return -14; |
| } |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult != QCBOR_ERR_BAD_BREAK) { |
| return -140; |
| } |
| |
| |
| // --- next test ----- |
| IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad4); |
| |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -15; |
| } |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -16; |
| } |
| |
| nResult = QCBORDecode_Finish(&DC); |
| if(nResult != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return -17; |
| } |
| |
| // --- next test ----- |
| IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad5); |
| |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -18; |
| } |
| |
| nResult = QCBORDecode_GetNext(&DC, &Item); |
| if(nResult != QCBOR_ERR_BAD_BREAK) { |
| return -19; |
| } |
| |
| return 0; |
| } |
| |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| |
| static const uint8_t spIndefiniteLenString[] = { |
| 0x81, // Array of length one |
| 0x7f, // text string marked with indefinite length |
| 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment |
| 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment |
| 0xff // ending break |
| }; |
| |
| static const uint8_t spIndefiniteLenStringBad2[] = { |
| 0x81, // Array of length one |
| 0x7f, // text string marked with indefinite length |
| 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment |
| 0x44, 0x6d, 0x69, 0x6e, 0x67, // second segment of wrong type |
| 0xff // ending break |
| }; |
| |
| static const uint8_t spIndefiniteLenStringBad3[] = { |
| 0x81, // Array of length one |
| 0x7f, // text string marked with indefinite length |
| 0x01, 0x02, // Not a string |
| 0xff // ending break |
| }; |
| |
| static const uint8_t spIndefiniteLenStringBad4[] = { |
| 0x81, // Array of length one |
| 0x7f, // text string marked with indefinite length |
| 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment |
| 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment |
| // missing end of string |
| }; |
| |
| static const uint8_t spIndefiniteLenStringLabel[] = { |
| 0xa1, // Array of length one |
| 0x7f, // text string marked with indefinite length |
| 0x65, 0x73, 0x74, 0x72, 0x75, 0x75, // first segment |
| 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment |
| 0xff, // ending break |
| 0x01 // integer being labeled. |
| }; |
| |
| /** |
| Make an indefinite length string |
| |
| @param Storage Storage for string, must be 144 bytes in size |
| @return The indefinite length string |
| |
| This makes an array with one indefinite length string that has 7 chunks |
| from size of 1 byte up to 64 bytes. |
| */ |
| static UsefulBufC MakeIndefiniteBigBstr(UsefulBuf Storage) |
| { |
| UsefulOutBuf UOB; |
| |
| UsefulOutBuf_Init(&UOB, Storage); |
| UsefulOutBuf_AppendByte(&UOB, 0x81); |
| UsefulOutBuf_AppendByte(&UOB, 0x5f); |
| |
| uint8_t uStringByte = 0; |
| // Use of type int is intentional |
| for(int uChunkSize = 1; uChunkSize <= 128; uChunkSize *= 2) { |
| // Not using preferred encoding here, but that is OK. |
| UsefulOutBuf_AppendByte(&UOB, 0x58); |
| UsefulOutBuf_AppendByte(&UOB, (uint8_t)uChunkSize); |
| for(int j = 0; j < uChunkSize; j++) { |
| UsefulOutBuf_AppendByte(&UOB, uStringByte); |
| uStringByte++; |
| } |
| } |
| UsefulOutBuf_AppendByte(&UOB, 0xff); |
| |
| return UsefulOutBuf_OutUBuf(&UOB); |
| } |
| |
| static int CheckBigString(UsefulBufC BigString) |
| { |
| if(BigString.len != 255) { |
| return 1; |
| } |
| |
| for(uint8_t i = 0; i < 255; i++){ |
| if(((const uint8_t *)BigString.ptr)[i] != i) { |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| |
| int32_t IndefiniteLengthStringTest() |
| { |
| QCBORDecodeContext DC; |
| QCBORItem Item; |
| // big enough for MakeIndefiniteBigBstr() + MemPool overhead |
| UsefulBuf_MAKE_STACK_UB(MemPool, 350); |
| |
| // --- Simple normal indefinite length string ------ |
| UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenString); |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { |
| return -1; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -2; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.uDataAlloc) { |
| return -3; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -4; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || !Item.uDataAlloc) { |
| return -5; |
| } |
| if(QCBORDecode_Finish(&DC)) { |
| return -6; |
| } |
| |
| // ----- types mismatch --- |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad2), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { |
| return -7; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -8; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -9; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_INDEFINITE_STRING_CHUNK) { |
| return -10; |
| } |
| |
| // ----- not a string --- |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad3), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { |
| return -11; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -12; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -13; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_INDEFINITE_STRING_CHUNK) { |
| return -14; |
| } |
| |
| // ----- no end ----- |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad4), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { |
| return -15; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -16; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -17; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_HIT_END) { |
| return -18; |
| } |
| |
| // ------ Don't set a string allocator and see an error ----- |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -19; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_NO_STRING_ALLOCATOR) { |
| return -20; |
| } |
| |
| // ----- Mempool is way too small ----- |
| UsefulBuf_MAKE_STACK_UB(MemPoolTooSmall, QCBOR_DECODE_MIN_MEM_POOL_SIZE-1); |
| |
| QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); |
| if(!QCBORDecode_SetMemPool(&DC, MemPoolTooSmall, false)) { |
| return -21; |
| } |
| |
| // ----- Mempool is way too small ----- |
| UsefulBuf_MAKE_STACK_UB(BigIndefBStrStorage, 290); |
| const UsefulBufC BigIndefBStr = MakeIndefiniteBigBstr(BigIndefBStrStorage); |
| |
| // 80 is big enough for MemPool overhead, but not BigIndefBStr |
| UsefulBuf_MAKE_STACK_UB(MemPoolSmall, 80); |
| |
| QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL); |
| if(QCBORDecode_SetMemPool(&DC, MemPoolSmall, false)) { |
| return -22; |
| } |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return -23; |
| } |
| if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_STRING_ALLOCATE) { |
| return -24; |
| } |
| |
| // ---- big bstr ----- |
| QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { |
| return -25; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -26; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.uDataAlloc) { |
| return -26; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)) { |
| return -27; |
| } |
| if(Item.uDataType != QCBOR_TYPE_BYTE_STRING || !Item.uDataAlloc || Item.uNestingLevel != 1) { |
| return -28; |
| } |
| if(CheckBigString(Item.val.string)) { |
| return -3; |
| } |
| if(QCBORDecode_Finish(&DC)) { |
| return -29; |
| } |
| |
| // --- label is an indefinite length string ------ |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL); |
| |
| if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { |
| return -30; |
| } |
| |
| QCBORDecode_GetNext(&DC, &Item); |
| if(Item.uDataType != QCBOR_TYPE_MAP) { |
| return -31; |
| } |
| |
| if(QCBORDecode_GetNext(&DC, &Item)){ |
| return -32; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.uDataAlloc || !Item.uLabelAlloc || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("struuming"))) { |
| return -33; |
| } |
| |
| if(QCBORDecode_Finish(&DC)) { |
| return -34; |
| } |
| |
| return 0; |
| } |
| |
| |
| int32_t AllocAllStringsTest() |
| { |
| QCBORDecodeContext DC; |
| QCBORError nCBORError; |
| |
| |
| // First test, use the "CSRMap" as easy input and checking |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| UsefulBuf_MAKE_STACK_UB(Pool, sizeof(spCSRInput) + QCBOR_DECODE_MIN_MEM_POOL_SIZE); |
| |
| nCBORError = QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying. |
| if(nCBORError) { |
| return -1; |
| } |
| |
| if(CheckCSRMaps(&DC)) { |
| return -2; |
| } |
| |
| // Next parse, save pointers to a few strings, destroy original and |
| // see all is OK. |
| UsefulBuf_MAKE_STACK_UB(CopyOfStorage, sizeof(pValidMapEncoded) + QCBOR_DECODE_MIN_MEM_POOL_SIZE); |
| const UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded)); |
| |
| QCBORDecode_Init(&DC, CopyOf, QCBOR_DECODE_MODE_NORMAL); |
| UsefulBuf_Set(Pool, '/'); |
| QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying. |
| |
| QCBORItem Item1, Item2, Item3, Item4; |
| if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) |
| return (int32_t)nCBORError; |
| if(Item1.uDataType != QCBOR_TYPE_MAP || |
| Item1.val.uCount != 3) |
| return -3; |
| if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) |
| return (int32_t)nCBORError; |
| if((nCBORError = QCBORDecode_GetNext(&DC, &Item2))) |
| return (int32_t)nCBORError; |
| if((nCBORError = QCBORDecode_GetNext(&DC, &Item3))) |
| return (int32_t)nCBORError; |
| if((nCBORError = QCBORDecode_GetNext(&DC, &Item4))) |
| return (int32_t)nCBORError; |
| |
| UsefulBuf_Set(CopyOfStorage, '_'); |
| |
| if(Item1.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item1.uDataType != QCBOR_TYPE_INT64 || |
| Item1.val.int64 != 42 || |
| Item1.uDataAlloc != 0 || |
| Item1.uLabelAlloc == 0 || |
| UsefulBufCompareToSZ(Item1.label.string, "first integer")) { |
| return -4; |
| } |
| |
| |
| if(Item2.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item2.label.string, "an array of two strings") || |
| Item2.uDataType != QCBOR_TYPE_ARRAY || |
| Item2.uDataAlloc != 0 || |
| Item2.uLabelAlloc == 0 || |
| Item2.val.uCount != 2) |
| return -5; |
| |
| if(Item3.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item3.uDataAlloc == 0 || |
| Item3.uLabelAlloc != 0 || |
| UsefulBufCompareToSZ(Item3.val.string, "string1")) { |
| return -6; |
| } |
| |
| if(Item4.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item4.uDataAlloc == 0 || |
| Item4.uLabelAlloc != 0 || |
| UsefulBufCompareToSZ(Item4.val.string, "string2")) { |
| return -7; |
| } |
| |
| // Next parse with a pool that is too small |
| UsefulBuf_MAKE_STACK_UB(SmallPool, QCBOR_DECODE_MIN_MEM_POOL_SIZE + 1); |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), |
| QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_SetMemPool(&DC, SmallPool, 1); // Turn on copying. |
| if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) |
| return -8; |
| if(Item1.uDataType != QCBOR_TYPE_MAP || |
| Item1.val.uCount != 3) { |
| return -9; |
| } |
| if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item1))){ |
| if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item2))) { |
| if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item3))) { |
| nCBORError = QCBORDecode_GetNext(&DC, &Item4); |
| } |
| } |
| } |
| if(nCBORError != QCBOR_ERR_STRING_ALLOCATE) { |
| return -10; |
| } |
| |
| return 0; |
| } |
| |
| |
| int32_t MemPoolTest(void) |
| { |
| // Set up the decoder with a tiny bit of CBOR to parse because |
| // nothing can be done with it unless that is set up. |
| QCBORDecodeContext DC; |
| const uint8_t pMinimalCBOR[] = {0xa0}; // One empty map |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalCBOR),0); |
| |
| // Set up an memory pool of 100 bytes |
| // Then fish into the internals of the decode context |
| // to get the allocator function so it can be called directly. |
| // Also figure out how much pool is available for use |
| // buy subtracting out the overhead. |
| UsefulBuf_MAKE_STACK_UB(Pool, 100); |
| QCBORError nError = QCBORDecode_SetMemPool(&DC, Pool, 0); |
| if(nError) { |
| return -9; |
| } |
| QCBORStringAllocate pAlloc = DC.StringAllocator.pfAllocator; |
| void *pAllocCtx = DC.StringAllocator.pAllocateCxt; |
| size_t uAvailPool = Pool.len - QCBOR_DECODE_MIN_MEM_POOL_SIZE; |
| |
| // First test -- ask for one more byte than available and see failure |
| UsefulBuf Allocated = (*pAlloc)(pAllocCtx, NULL, uAvailPool+1); |
| if(!UsefulBuf_IsNULL(Allocated)) { |
| return -1; |
| } |
| |
| // Re do the set up for the next test that will do a successful alloc, |
| // a fail, a free and then success |
| QCBORDecode_SetMemPool(&DC, Pool, 0); |
| pAlloc = DC.StringAllocator.pfAllocator; |
| pAllocCtx = DC.StringAllocator.pAllocateCxt; |
| uAvailPool = Pool.len - QCBOR_DECODE_MIN_MEM_POOL_SIZE; |
| |
| // Allocate one byte less than available and see success |
| Allocated = (pAlloc)(pAllocCtx, NULL, uAvailPool-1); |
| if(UsefulBuf_IsNULL(Allocated)) { // expected to succeed |
| return -2; |
| } |
| // Ask for some more and see failure |
| UsefulBuf Allocated2 = (*pAlloc)(pAllocCtx, NULL, uAvailPool/2); |
| if(!UsefulBuf_IsNULL(Allocated2)) { // expected to fail |
| return -3; |
| } |
| // Free the first allocate, retry the second and see success |
| (*pAlloc)(pAllocCtx, Allocated.ptr, 0); // Free |
| Allocated = (*pAlloc)(pAllocCtx, NULL, uAvailPool/2); |
| if(UsefulBuf_IsNULL(Allocated)) { // succeed because of the free |
| return -4; |
| } |
| |
| // Re do set up for next test that involves a successful alloc, |
| // and a successful realloc and a failed realloc |
| QCBORDecode_SetMemPool(&DC, Pool, 0); |
| pAlloc = DC.StringAllocator.pfAllocator; |
| pAllocCtx = DC.StringAllocator.pAllocateCxt; |
| |
| // Allocate half the pool and see success |
| Allocated = (*pAlloc)(pAllocCtx, NULL, uAvailPool/2); |
| if(UsefulBuf_IsNULL(Allocated)) { // expected to succeed |
| return -5; |
| } |
| // Reallocate to take up the whole pool and see success |
| Allocated2 = (*pAlloc)(pAllocCtx, Allocated.ptr, uAvailPool); |
| if(UsefulBuf_IsNULL(Allocated2)) { |
| return -6; |
| } |
| // Make sure its the same pointer and the size is right |
| if(Allocated2.ptr != Allocated.ptr || Allocated2.len != uAvailPool) { |
| return -7; |
| } |
| // Try to allocate more to be sure there is failure after a realloc |
| UsefulBuf Allocated3 = (*pAlloc)(pAllocCtx, Allocated.ptr, uAvailPool+1); |
| if(!UsefulBuf_IsNULL(Allocated3)) { |
| return -8; |
| } |
| |
| return 0; |
| } |
| |
| |
| /* Just enough of an allocator to test configuration of one */ |
| static UsefulBuf AllocateTestFunction(void *pCtx, void *pOldMem, size_t uNewSize) |
| { |
| (void)pOldMem; // unused variable |
| |
| if(uNewSize) { |
| // Assumes the context pointer is the buffer and |
| // nothing too big will ever be asked for. |
| // This is only good for this basic test! |
| return (UsefulBuf) {pCtx, uNewSize}; |
| } else { |
| return NULLUsefulBuf; |
| } |
| } |
| |
| |
| int32_t SetUpAllocatorTest(void) |
| { |
| // Set up the decoder with a tiny bit of CBOR to parse because |
| // nothing can be done with it unless that is set up. |
| QCBORDecodeContext DC; |
| const uint8_t pMinimalCBOR[] = {0x62, 0x48, 0x69}; // "Hi" |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalCBOR),0); |
| |
| uint8_t pAllocatorBuffer[50]; |
| |
| // This is really just to test that this call works. |
| // The full functionality of string allocators is tested |
| // elsewhere with the MemPool internal allocator. |
| QCBORDecode_SetUpAllocator(&DC, AllocateTestFunction, pAllocatorBuffer, 1); |
| |
| QCBORItem Item; |
| if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_SUCCESS) { |
| return -1; |
| } |
| |
| if(Item.uDataAlloc == 0 || |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.val.string.ptr != pAllocatorBuffer) { |
| return -2; |
| } |
| |
| if(QCBORDecode_Finish(&DC) != QCBOR_SUCCESS) { |
| return -3; |
| } |
| |
| return 0; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| |
| /* exponent, mantissa |
| [ |
| 4([-1, 3]), |
| 4([-20, 4759477275222530853136]), |
| 4([9223372036854775807, -4759477275222530853137]), |
| 5([300, 100]), |
| 5([-20, 4759477275222530853136]), |
| 5([-9223372036854775807, -4759477275222530853137]) |
| 5([ 9223372036854775806, -4759477275222530853137]) |
| 5([ 9223372036854775806, 9223372036854775806])] |
| ] |
| */ |
| static const uint8_t spExpectedExponentsAndMantissas[] = { |
| 0x88, |
| 0xC4, 0x82, 0x20, |
| 0x03, |
| 0xC4, 0x82, 0x33, |
| 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, |
| 0xC4, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, |
| 0xC5, 0x82, 0x19, 0x01, 0x2C, |
| 0x18, 0x64, |
| 0xC5, 0x82, 0x33, |
| 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, |
| 0xC5, 0x82, 0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, |
| 0xC5, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, |
| 0xC5, 0x82, 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE |
| }; |
| |
| |
| int32_t ExponentAndMantissaDecodeTests(void) |
| { |
| QCBORDecodeContext DC; |
| QCBORError uErr; |
| QCBORItem item; |
| |
| static const uint8_t spBigNumMantissa[] = {0x01, 0x02, 0x03, 0x04, 0x05, |
| 0x06, 0x07, 0x08, 0x09, 0x010}; |
| UsefulBufC BN = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumMantissa); |
| |
| |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedExponentsAndMantissas), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 1; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_ARRAY) { |
| return 2; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 3; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION || |
| item.val.expAndMantissa.Mantissa.nInt != 3 || |
| item.val.expAndMantissa.nExponent != -1) { |
| return 4; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 5; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM || |
| item.val.expAndMantissa.nExponent != -20 || |
| UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { |
| return 6; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 7; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM || |
| item.val.expAndMantissa.nExponent != 9223372036854775807 || |
| UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { |
| return 8; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 9; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_BIGFLOAT || |
| item.val.expAndMantissa.Mantissa.nInt != 100 || |
| item.val.expAndMantissa.nExponent != 300) { |
| return 10; |
| } |
| |
| // 5([-20, 4759477275222530853136]), |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 11; |
| } |
| if(item.uDataType != QCBOR_TYPE_BIGFLOAT_POS_BIGNUM || |
| item.val.expAndMantissa.nExponent != -20 || |
| UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { |
| return 12; |
| } |
| |
| // 5([-9223372036854775807, -4759477275222530853137]) |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 13; |
| } |
| if(item.uDataType != QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM || |
| item.val.expAndMantissa.nExponent != -9223372036854775807 || |
| UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { |
| return 14; |
| } |
| |
| // 5([ 9223372036854775806, -4759477275222530853137]) |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 15; |
| } |
| if(item.uDataType != QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM || |
| item.val.expAndMantissa.nExponent != 9223372036854775806 || |
| UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { |
| return 16; |
| } |
| |
| // 5([ 9223372036854775806, 9223372036854775806])] |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 17; |
| } |
| if(item.uDataType != QCBOR_TYPE_BIGFLOAT || |
| item.val.expAndMantissa.nExponent != 9223372036854775806 || |
| item.val.expAndMantissa.Mantissa.nInt!= 9223372036854775806 ) { |
| return 18; |
| } |
| |
| uErr = QCBORDecode_Finish(&DC); |
| if(uErr != QCBOR_SUCCESS) { |
| return 18; |
| } |
| |
| /* Now encode some stuff and then decode it */ |
| uint8_t pBuf[40]; |
| QCBOREncodeContext EC; |
| UsefulBufC Encoded; |
| |
| QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(pBuf)); |
| QCBOREncode_OpenArray(&EC); |
| QCBOREncode_AddDecimalFraction(&EC, 999, 1000); // 999 * (10 ^ 1000) |
| QCBOREncode_AddBigFloat(&EC, 100, INT32_MIN); |
| QCBOREncode_AddDecimalFractionBigNum(&EC, BN, false, INT32_MAX); |
| QCBOREncode_CloseArray(&EC); |
| QCBOREncode_Finish(&EC, &Encoded); |
| |
| |
| QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL); |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 100; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 101; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION || |
| item.val.expAndMantissa.nExponent != 1000 || |
| item.val.expAndMantissa.Mantissa.nInt != 999) { |
| return 102; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 103; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_BIGFLOAT || |
| item.val.expAndMantissa.nExponent != INT32_MIN || |
| item.val.expAndMantissa.Mantissa.nInt != 100) { |
| return 104; |
| } |
| |
| uErr = QCBORDecode_GetNext(&DC, &item); |
| if(uErr != QCBOR_SUCCESS) { |
| return 105; |
| } |
| |
| if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM || |
| item.val.expAndMantissa.nExponent != INT32_MAX || |
| UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { |
| return 106; |
| } |
| |
| |
| int64_t nExp, nMant; |
| UsefulBuf_MAKE_STACK_UB( MantBuf, 20); |
| UsefulBufC Mant; |
| bool bIsNeg; |
| |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedExponentsAndMantissas), |
| QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_EnterArray(&DC, NULL); |
| |
| // 4([-1, 3]), |
| QCBORDecode_GetDecimalFraction(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nExp, &nMant); |
| |
| // 4([-20, 4759477275222530853136]), |
| QCBORDecode_GetDecimalFractionBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, |
| &Mant, &bIsNeg, &nExp); |
| |
| // 4([9223372036854775807, -4759477275222530853137]), |
| QCBORDecode_GetDecimalFractionBig(&DC, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, |
| MantBuf, &Mant, &bIsNeg, &nExp); |
| |
| // 5([300, 100]), |
| QCBORDecode_GetBigFloat(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nExp, &nMant); |
| |
| // 5([-20, 4759477275222530853136]), |
| QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, |
| &bIsNeg, &nExp); |
| |
| // 5([-9223372036854775807, -4759477275222530853137]) |
| QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, |
| &bIsNeg, &nExp); |
| |
| // 5([ 9223372036854775806, -4759477275222530853137]) |
| QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, |
| &bIsNeg, &nExp); |
| |
| // 5([ 9223372036854775806, 9223372036854775806])] |
| QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, |
| &bIsNeg, &nExp); |
| |
| QCBORDecode_ExitArray(&DC); |
| |
| uErr = QCBORDecode_Finish(&DC); |
| if(uErr != QCBOR_SUCCESS) { |
| return 200; |
| } |
| |
| return 0; |
| } |
| |
| |
| static const struct FailInput ExponentAndMantissaFailures[] = { |
| // Exponent > INT64_MAX |
| { {(uint8_t[]){0xC4, 0x82, 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 0xFF, 0xFF, 0x1B, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 0xFF, 0xFF,}, 20}, QCBOR_ERR_BAD_EXP_AND_MANTISSA}, |
| // Mantissa > INT64_MAX |
| { {(uint8_t[]){0xC4, 0x82, 0x1B, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 0xFF, 0xFF, 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, |
| 0x06, 0x07, 0x08, 0x09, 0x10}, 23}, QCBOR_ERR_BAD_EXP_AND_MANTISSA}, |
| // End of input |
| { {(uint8_t[]){0xC4, 0x82}, 2}, QCBOR_ERR_NO_MORE_ITEMS}, |
| // End of input |
| { {(uint8_t[]){0xC4, 0x82, 0x01}, 3}, QCBOR_ERR_NO_MORE_ITEMS}, |
| // bad content for big num |
| { {(uint8_t[]){0xC4, 0x82, 0x01, 0xc3, 0x01}, 5}, QCBOR_ERR_BAD_OPT_TAG}, |
| // bad content for big num |
| { {(uint8_t[]){0xC4, 0x82, 0xc2, 0x01, 0x1f}, 5}, QCBOR_ERR_BAD_INT}, |
| // Bad integer for exponent |
| { {(uint8_t[]){0xC4, 0x82, 0x01, 0x1f}, 4}, QCBOR_ERR_BAD_INT}, |
| // Bad integer for mantissa |
| { {(uint8_t[]){0xC4, 0x82, 0x1f, 0x01}, 4}, QCBOR_ERR_BAD_INT}, |
| // 3 items in array |
| { {(uint8_t[]){0xC4, 0x83, 0x03, 0x01, 02}, 5}, QCBOR_ERR_BAD_EXP_AND_MANTISSA}, |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| // unterminated indefinite length array |
| { {(uint8_t[]){0xC4, 0x9f, 0x03, 0x01, 0x02}, 5}, QCBOR_ERR_BAD_EXP_AND_MANTISSA}, |
| #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| // unterminated indefinite length array |
| { {(uint8_t[]){0xC4, 0x9f, 0x03, 0x01, 0x02}, 5}, QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED}, |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| // Empty array |
| { {(uint8_t[]){0xC4, 0x80}, 2}, QCBOR_ERR_NO_MORE_ITEMS}, |
| // Second is not an integer |
| { {(uint8_t[]){0xC4, 0x82, 0x03, 0x40}, 4}, QCBOR_ERR_BAD_EXP_AND_MANTISSA}, |
| // First is not an integer |
| { {(uint8_t[]){0xC4, 0x82, 0x40}, 3}, QCBOR_ERR_BAD_EXP_AND_MANTISSA}, |
| // Not an array |
| { {(uint8_t[]){0xC4, 0xa2}, 2}, QCBOR_ERR_BAD_EXP_AND_MANTISSA} |
| }; |
| |
| |
| int32_t ExponentAndMantissaDecodeFailTests() |
| { |
| return ProcessFailures(ExponentAndMantissaFailures, |
| C_ARRAY_COUNT(ExponentAndMantissaFailures, |
| struct FailInput)); |
| } |
| |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| |
| |
| |
| /* |
| Some basic CBOR with map and array used in a lot of tests. |
| The map labels are all strings |
| |
| { |
| "first integer": 42, |
| "an array of two strings": [ |
| "string1", "string2" |
| ], |
| "map in a map": { |
| "bytes 1": h'78787878', |
| "bytes 2": h'79797979', |
| "another int": 98, |
| "text 2": "lies, damn lies and statistics" |
| } |
| } |
| */ |
| |
| int32_t SpiffyDecodeBasicMap(UsefulBufC input) |
| { |
| QCBORItem Item1, Item2, Item3; |
| int64_t nDecodedInt1, nDecodedInt2; |
| UsefulBufC B1, B2, S1, S2, S3; |
| |
| QCBORDecodeContext DCtx; |
| QCBORError nCBORError; |
| |
| QCBORDecode_Init(&DCtx, input, 0); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| QCBORDecode_GetInt64InMapSZ(&DCtx, "first integer", &nDecodedInt1); |
| |
| QCBORDecode_EnterMapFromMapSZ(&DCtx, "map in a map"); |
| QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt2); |
| QCBORDecode_GetByteStringInMapSZ(&DCtx, "bytes 1", &B1); |
| QCBORDecode_GetByteStringInMapSZ(&DCtx, "bytes 2", &B2); |
| QCBORDecode_GetTextStringInMapSZ(&DCtx, "text 2", &S1); |
| QCBORDecode_ExitMap(&DCtx); |
| |
| QCBORDecode_EnterArrayFromMapSZ(&DCtx, "an array of two strings"); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item2); |
| if(QCBORDecode_GetNext(&DCtx, &Item3) != QCBOR_ERR_NO_MORE_ITEMS) { |
| return -400; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| |
| // Parse the same array again using GetText() instead of GetItem() |
| QCBORDecode_EnterArrayFromMapSZ(&DCtx, "an array of two strings"); |
| QCBORDecode_GetTextString(&DCtx, &S2); |
| QCBORDecode_GetTextString(&DCtx, &S3); |
| if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) { |
| return 5000; |
| } |
| /* QCBORDecode_GetText(&DCtx, &S3); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 5001; |
| } */ |
| |
| QCBORDecode_ExitArray(&DCtx); |
| |
| QCBORDecode_ExitMap(&DCtx); |
| |
| nCBORError = QCBORDecode_Finish(&DCtx); |
| |
| if(nCBORError) { |
| return (int32_t)nCBORError; |
| } |
| |
| if(nDecodedInt1 != 42) { |
| return 1001; |
| } |
| |
| if(nDecodedInt2 != 98) { |
| return 1002; |
| } |
| |
| if(Item1.uDataType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item1.val.string, "string1")) { |
| return 1003; |
| } |
| |
| if(Item1.uDataType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item2.val.string, "string2")) { |
| return 1004; |
| } |
| |
| if(UsefulBufCompareToSZ(S1, "lies, damn lies and statistics")) { |
| return 1005; |
| } |
| |
| if(UsefulBuf_Compare(B1, UsefulBuf_FromSZ("xxxx"))){ |
| return 1006; |
| } |
| |
| if(UsefulBuf_Compare(B2, UsefulBuf_FromSZ("yyyy"))){ |
| return 1007; |
| } |
| |
| if(UsefulBuf_Compare(S2, UsefulBuf_FromSZ("string1"))){ |
| return 1008; |
| } |
| |
| if(UsefulBuf_Compare(S3, UsefulBuf_FromSZ("string2"))){ |
| return 1009; |
| } |
| |
| return 0; |
| } |
| |
| /* |
| { |
| -75008: h'05083399', |
| 88: [], |
| 100100: { |
| "sub1": { |
| 10: [ |
| 0 |
| ], |
| -75009: h'A46823990001', |
| 100100: { |
| "json": "{ \"ueid\", \"xyz\"}", |
| "subsub": { |
| 100002: h'141813191001' |
| } |
| } |
| } |
| } |
| } |
| */ |
| |
| static const uint8_t spNestedCBOR[] = { |
| 0xa3, 0x3a, 0x00, 0x01, 0x24, 0xff, 0x44, 0x05, |
| 0x08, 0x33, 0x99, 0x18, 0x58, 0x80, 0x1a, 0x00, |
| 0x01, 0x87, 0x04, 0xa1, 0x64, 0x73, 0x75, 0x62, |
| 0x31, 0xa3, 0x0a, 0x81, 0x00, 0x3a, 0x00, 0x01, |
| 0x25, 0x00, 0x46, 0xa4, 0x68, 0x23, 0x99, 0x00, |
| 0x01, 0x1a, 0x00, 0x01, 0x87, 0x04, 0xa2, 0x64, |
| 0x6a, 0x73, 0x6f, 0x6e, 0x70, 0x7b, 0x20, 0x22, |
| 0x75, 0x65, 0x69, 0x64, 0x22, 0x2c, 0x20, 0x22, |
| 0x78, 0x79, 0x7a, 0x22, 0x7d, 0x66, 0x73, 0x75, |
| 0x62, 0x73, 0x75, 0x62, 0xa1, 0x1a, 0x00, 0x01, |
| 0x86, 0xa2, 0x46, 0x14, 0x18, 0x13, 0x19, 0x10, |
| 0x01 |
| }; |
| |
| /* Get item in multi-level nesting in spNestedCBOR */ |
| static int32_t DecodeNestedGetSubSub(QCBORDecodeContext *pDCtx) |
| { |
| UsefulBufC String; |
| |
| uint8_t test_oemid_bytes[] = {0x14, 0x18, 0x13, 0x19, 0x10, 0x01}; |
| const struct q_useful_buf_c test_oemid = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(test_oemid_bytes); |
| |
| QCBORDecode_EnterMapFromMapN(pDCtx, 100100); |
| QCBORDecode_EnterMap(pDCtx, NULL); |
| QCBORDecode_EnterMapFromMapN(pDCtx, 100100); |
| QCBORDecode_EnterMapFromMapSZ(pDCtx, "subsub"); |
| QCBORDecode_GetByteStringInMapN(pDCtx, 100002, &String); |
| if(QCBORDecode_GetError(pDCtx)) { |
| return 4001; |
| } |
| if(UsefulBuf_Compare(String, test_oemid)) { |
| return 4002; |
| } |
| QCBORDecode_ExitMap(pDCtx); |
| QCBORDecode_ExitMap(pDCtx); |
| QCBORDecode_ExitMap(pDCtx); |
| QCBORDecode_ExitMap(pDCtx); |
| |
| return 0; |
| } |
| |
| /* Iterations on the zero-length array in spNestedCBOR */ |
| static int32_t DecodeNestedGetEmpty(QCBORDecodeContext *pDCtx) |
| { |
| QCBORItem Item; |
| QCBORError uErr; |
| |
| QCBORDecode_EnterArrayFromMapN(pDCtx, 88); |
| for(int x = 0; x < 20; x++) { |
| uErr = QCBORDecode_GetNext(pDCtx, &Item); |
| if(uErr != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 4100; |
| |
| } |
| } |
| QCBORDecode_ExitArray(pDCtx); |
| if(QCBORDecode_GetError(pDCtx)) { |
| return 4101; |
| } |
| |
| return 0; |
| } |
| |
| /* Various iterations on the array that contains a zero in spNestedCBOR */ |
| static int32_t DecodeNestedGetZero(QCBORDecodeContext *pDCtx) |
| { |
| QCBORError uErr; |
| |
| QCBORDecode_EnterMapFromMapN(pDCtx, 100100); |
| QCBORDecode_EnterMapFromMapSZ(pDCtx, "sub1"); |
| QCBORDecode_EnterArrayFromMapN(pDCtx, 10); |
| int64_t nInt = 99; |
| QCBORDecode_GetInt64(pDCtx, &nInt); |
| if(nInt != 0) { |
| return 4200; |
| } |
| for(int x = 0; x < 20; x++) { |
| QCBORItem Item; |
| uErr = QCBORDecode_GetNext(pDCtx, &Item); |
| if(uErr != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 4201; |
| |
| } |
| } |
| QCBORDecode_ExitArray(pDCtx); |
| if(QCBORDecode_GetAndResetError(pDCtx)) { |
| return 4202; |
| } |
| QCBORDecode_EnterArrayFromMapN(pDCtx, 10); |
| UsefulBufC dD; |
| QCBORDecode_GetByteString(pDCtx, &dD); |
| if(QCBORDecode_GetAndResetError(pDCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 4203; |
| } |
| for(int x = 0; x < 20; x++) { |
| QCBORDecode_GetByteString(pDCtx, &dD); |
| uErr = QCBORDecode_GetAndResetError(pDCtx); |
| if(uErr != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 4204; |
| } |
| } |
| QCBORDecode_ExitArray(pDCtx); |
| QCBORDecode_ExitMap(pDCtx); |
| QCBORDecode_ExitMap(pDCtx); |
| |
| return 0; |
| } |
| |
| /* Repeatedly enter and exit maps and arrays, go off the end of maps |
| and arrays and such. */ |
| static int32_t DecodeNestedIterate(void) |
| { |
| QCBORDecodeContext DCtx; |
| int32_t nReturn; |
| QCBORError uErr; |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNestedCBOR), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| for(int j = 0; j < 5; j++) { |
| for(int i = 0; i < 20; i++) { |
| nReturn = DecodeNestedGetSubSub(&DCtx); |
| if(nReturn) { |
| return nReturn; |
| } |
| } |
| |
| for(int i = 0; i < 20; i++) { |
| nReturn = DecodeNestedGetEmpty(&DCtx); |
| if(nReturn ) { |
| return nReturn; |
| } |
| } |
| |
| for(int i = 0; i < 20; i++) { |
| nReturn = DecodeNestedGetZero(&DCtx); |
| if(nReturn ) { |
| return nReturn; |
| } |
| } |
| } |
| |
| QCBORDecode_ExitMap(&DCtx); |
| uErr = QCBORDecode_Finish(&DCtx); |
| if(uErr) { |
| return (int32_t)uErr + 4100; |
| } |
| |
| return 0; |
| } |
| |
| |
| /* |
| [ |
| 23, |
| 6000, |
| h'67616C6163746963', |
| h'686176656E20746F6B656E' |
| ] |
| */ |
| static const uint8_t spSimpleArray[] = { |
| 0x84, |
| 0x17, |
| 0x19, 0x17, 0x70, |
| 0x48, 0x67, 0x61, 0x6C, 0x61, 0x63, 0x74, 0x69, 0x63, |
| 0x4B, 0x68, 0x61, 0x76, 0x65, 0x6E, 0x20, 0x74, 0x6F, 0x6B, 0x65, 0x6E}; |
| |
| /* [h'', {}, [], 0] */ |
| static const uint8_t spArrayOfEmpty[] = {0x84, 0x40, 0xa0, 0x80, 0x00}; |
| |
| /* {} */ |
| static const uint8_t spEmptyMap[] = {0xa0}; |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| /* {} */ |
| static const uint8_t spEmptyInDefinteLengthMap[] = {0xbf, 0xff}; |
| |
| |
| /* |
| { |
| 0: [], |
| 9: [ |
| [], |
| [] |
| ], |
| 8: { |
| 1: [], |
| 2: {}, |
| 3: [] |
| }, |
| 4: {}, |
| 5: [], |
| 6: [ |
| [], |
| [] |
| ] |
| } |
| */ |
| static const uint8_t spMapOfEmpty[] = { |
| 0xa6, 0x00, 0x80, 0x09, 0x82, 0x80, 0x80, 0x08, |
| 0xa3, 0x01, 0x80, 0x02, 0xa0, 0x03, 0x80, 0x04, |
| 0xa0, 0x05, 0x9f, 0xff, 0x06, 0x9f, 0x80, 0x9f, |
| 0xff, 0xff}; |
| |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| /* |
| Too many tags |
| Invalid tag content |
| Duplicate label |
| Integer overflow |
| Date overflow |
| |
| { |
| 1: 224(225(226(227(4(0))))), |
| 2: 1(h''), |
| 3: -18446744073709551616, |
| 4: 1(1.0e+300), |
| 5: 0, 8: 8 |
| } |
| */ |
| static const uint8_t spRecoverableMapErrors[] = { |
| 0xa7, |
| 0x01, 0xd8, 0xe0, 0xd8, 0xe1, 0xd8, 0xe2, 0xd8, 0xe3, 0xd8, 0x04, 0x00, |
| 0x02, 0xc1, 0x40, |
| 0x03, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0x04, 0xc1, 0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c, |
| 0x05, 0x00, |
| 0x05, 0x00, |
| 0x08, 0x08, |
| }; |
| |
| /* Bad break */ |
| static const uint8_t spUnRecoverableMapError1[] = { |
| 0xa2, 0xff, 0x01, 0x00, 0x02, 0x00 |
| }; |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| /* No more items */ |
| static const uint8_t spUnRecoverableMapError2[] = { |
| 0xbf, 0x02, 0xbf, 0xff, 0x01, 0x00, 0x02, 0x00 |
| }; |
| |
| /* Hit end because string is too long */ |
| static const uint8_t spUnRecoverableMapError3[] = { |
| 0xbf, 0x02, 0x69, 0x64, 0x64, 0xff |
| }; |
| |
| /* Hit end because string is too long */ |
| static const uint8_t spUnRecoverableMapError4[] = { |
| 0xbf, |
| 0x02, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, |
| 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff |
| }; |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| const unsigned char not_well_formed_submod_section[] = { |
| 0xa1, 0x14, 0x1f, |
| }; |
| |
| int32_t EnterMapTest() |
| { |
| QCBORItem Item1; |
| QCBORItem ArrayItem; |
| QCBORDecodeContext DCtx; |
| int32_t nReturn; |
| QCBORError uErr; |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spMapOfEmpty), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); // Label 0 |
| QCBORDecode_ExitArray(&DCtx); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); // Label 9 |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_ExitArray(&DCtx); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); // Label 8 |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_ExitMap(&DCtx); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_ExitMap(&DCtx); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); // Label4 |
| QCBORDecode_ExitMap(&DCtx); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); // Label 5 |
| QCBORDecode_ExitArray(&DCtx); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); // Label 6 |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_ExitArray(&DCtx); |
| |
| QCBORDecode_ExitMap(&DCtx); |
| |
| uErr = QCBORDecode_Finish(&DCtx); |
| if(uErr != QCBOR_SUCCESS){ |
| return 3011; |
| } |
| |
| (void)pValidMapIndefEncoded; |
| nReturn = SpiffyDecodeBasicMap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapIndefEncoded)); |
| if(nReturn) { |
| return nReturn + 20000; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| nReturn = SpiffyDecodeBasicMap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded)); |
| if(nReturn) { |
| return nReturn; |
| } |
| |
| |
| |
| // These tests confirm the cursor is at the right place after entering |
| // a map or array |
| const UsefulBufC ValidEncodedMap = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded); |
| |
| // Confirm cursor is at right place |
| QCBORDecode_Init(&DCtx, ValidEncodedMap, 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_INT64) { |
| return 2001; |
| } |
| |
| |
| QCBORDecode_Init(&DCtx, ValidEncodedMap, 0); |
| QCBORDecode_VGetNext(&DCtx, &Item1); |
| QCBORDecode_VGetNext(&DCtx, &Item1); |
| QCBORDecode_EnterArray(&DCtx, &ArrayItem); |
| if(ArrayItem.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(ArrayItem.label.string, |
| UsefulBuf_FROM_SZ_LITERAL("an array of two strings"))) { |
| return 2051; |
| } |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_TEXT_STRING) { |
| return 2002; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_EnterMap(&DCtx, &ArrayItem); |
| if(ArrayItem.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(ArrayItem.label.string, |
| UsefulBuf_FROM_SZ_LITERAL("map in a map"))) { |
| return 2052; |
| } |
| |
| |
| QCBORDecode_Init(&DCtx, ValidEncodedMap, 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_EnterMapFromMapSZ(&DCtx, "map in a map"); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_BYTE_STRING) { |
| return 2003; |
| } |
| |
| QCBORDecode_Init(&DCtx, ValidEncodedMap, 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| QCBORDecode_EnterArrayFromMapSZ(&DCtx, "an array of two strings"); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_TEXT_STRING) { |
| return 2004; |
| } |
| |
| QCBORDecode_Init(&DCtx, ValidEncodedMap, 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_EnterArrayFromMapSZ(&DCtx, "an array of two strings"); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_GetNext(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_MAP && Item1.uLabelAlloc != QCBOR_TYPE_TEXT_STRING) { |
| return 2006; |
| } |
| QCBORDecode_ExitMap(&DCtx); |
| if(QCBORDecode_GetNext(&DCtx, &Item1) != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 2007; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleArray), 0); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| int64_t nDecodedInt2; |
| QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt2); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){ |
| return 2008; |
| } |
| UsefulBufC String; |
| QCBORDecode_GetTextStringInMapN(&DCtx, 88, &String); |
| if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){ |
| return 2009; |
| } |
| |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmptyMap), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| // This will fail because the map is empty. |
| QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt2); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
| return 2010; |
| } |
| QCBORDecode_ExitMap(&DCtx); |
| uErr = QCBORDecode_Finish(&DCtx); |
| if(uErr != QCBOR_SUCCESS){ |
| return 2011; |
| } |
| |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmptyInDefinteLengthMap), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| // This will fail because the map is empty. |
| QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt2); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
| return 2012; |
| } |
| QCBORDecode_ExitMap(&DCtx); |
| uErr = QCBORDecode_Finish(&DCtx); |
| if(uErr != QCBOR_SUCCESS){ |
| return 2013; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spArrayOfEmpty), 0); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_GetByteString(&DCtx, &String); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_ExitMap(&DCtx); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_GetInt64(&DCtx, &nDecodedInt2); |
| QCBORDecode_ExitArray(&DCtx); |
| uErr = QCBORDecode_Finish(&DCtx); |
| if(uErr != QCBOR_SUCCESS) { |
| return 2014; |
| } |
| |
| int64_t nInt; |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spRecoverableMapErrors), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt); |
| uErr = QCBORDecode_GetError(&DCtx); |
| if(uErr != QCBOR_ERR_TOO_MANY_TAGS) { |
| return 2021; |
| } |
| if(QCBORDecode_GetNthTagOfLast(&DCtx, 0) != CBOR_TAG_INVALID64) { |
| return 2121; |
| } |
| (void)QCBORDecode_GetAndResetError(&DCtx); |
| |
| |
| QCBORDecode_GetEpochDateInMapN(&DCtx, 0x02, QCBOR_TAG_REQUIREMENT_TAG, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_BAD_OPT_TAG) { |
| return 2022; |
| } |
| |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x03, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_INT_OVERFLOW) { |
| return 2023; |
| } |
| |
| QCBORDecode_GetEpochDateInMapN(&DCtx, 0x04, QCBOR_TAG_REQUIREMENT_TAG, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| if(uErr != QCBOR_ERR_DATE_OVERFLOW) { |
| return 2024; |
| } |
| #else |
| if(uErr != QCBOR_ERR_FLOAT_DATE_DISABLED) { |
| return 2027; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x05, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_DUPLICATE_LABEL) { |
| return 2025; |
| } |
| |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x08, &nInt); |
| |
| QCBORDecode_ExitMap(&DCtx); |
| uErr = QCBORDecode_Finish(&DCtx); |
| if(uErr != QCBOR_SUCCESS) { |
| return 2026; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUnRecoverableMapError1), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_BAD_BREAK) { |
| return 2030; |
| } |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUnRecoverableMapError2), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 2031; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUnRecoverableMapError3), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_HIT_END) { |
| return 2032; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUnRecoverableMapError4), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt); |
| uErr = QCBORDecode_GetAndResetError(&DCtx); |
| if(uErr != QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP) { |
| return 2033; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0); |
| QCBORDecode_VGetNextConsume(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_MAP) { |
| return 2401; |
| } |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 2402; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0); |
| QCBORDecode_VGetNext(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_MAP || |
| Item1.val.uCount != 3 || |
| Item1.uNextNestLevel != 1) { |
| return 2403; |
| } |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 2404; |
| } |
| QCBORDecode_VGetNextConsume(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_INT64 || |
| Item1.uNextNestLevel != 1 || |
| Item1.val.int64 != 42) { |
| return 2405; |
| } |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 2406; |
| } |
| QCBORDecode_VGetNextConsume(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_ARRAY || |
| Item1.uNestingLevel != 1 || |
| Item1.uNextNestLevel != 1 || |
| Item1.val.uCount != 2) { |
| return 2407; |
| } |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 2408; |
| } |
| QCBORDecode_VGetNextConsume(&DCtx, &Item1); |
| if(Item1.uDataType != QCBOR_TYPE_MAP || |
| Item1.uNestingLevel != 1 || |
| Item1.uNextNestLevel != 0 || |
| Item1.val.uCount != 4) { |
| return 2409; |
| } |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 2410; |
| } |
| |
| nReturn = DecodeNestedIterate(); |
| |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(not_well_formed_submod_section), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_EnterMapFromMapN(&DCtx, 20); |
| if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_BAD_INT) { |
| return 2500; |
| } |
| |
| return nReturn; |
| } |
| |
| |
| struct NumberConversion { |
| char *szDescription; |
| UsefulBufC CBOR; |
| int64_t nConvertedToInt64; |
| QCBORError uErrorInt64; |
| uint64_t uConvertToUInt64; |
| QCBORError uErrorUint64; |
| double dConvertToDouble; |
| QCBORError uErrorDouble; |
| }; |
| |
| static const struct NumberConversion NumberConversions[] = { |
| { |
| "too large to fit into int64_t", |
| {(uint8_t[]){0xc3, 0x48, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 10}, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| ((double)INT64_MIN) + 1 , |
| QCBOR_SUCCESS |
| }, |
| { |
| "largest negative int that fits in int64_t", |
| {(uint8_t[]){0xc3, 0x48, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 10}, |
| INT64_MIN, |
| QCBOR_SUCCESS, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| (double)INT64_MIN, |
| QCBOR_SUCCESS |
| }, |
| { |
| "negative bignum -1", |
| {(uint8_t[]){0xc3, 0x41, 0x00}, 3}, |
| -1, |
| QCBOR_SUCCESS, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -1.0, |
| QCBOR_SUCCESS |
| }, |
| { |
| "Decimal Fraction with positive bignum 257 * 10e3", |
| {(uint8_t[]){0xC4, 0x82, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0xC2, 0x42, 0x01, 0x01}, 15}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 257000, |
| QCBOR_SUCCESS, |
| 257000, |
| QCBOR_SUCCESS, |
| 257000.0, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/ |
| }, |
| { |
| "bigfloat with negative bignum -258 * 2e3", |
| {(uint8_t[]){0xC5, 0x82, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0xC3, 0x42, 0x01, 0x01}, 15}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| -2064, |
| QCBOR_SUCCESS, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -2064.0, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/ |
| }, |
| { |
| "bigfloat with positive bignum 257 * 2e3", |
| {(uint8_t[]){0xC5, 0x82, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0xC2, 0x42, 0x01, 0x01}, 15}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 2056, |
| QCBOR_SUCCESS, |
| 2056, |
| QCBOR_SUCCESS, |
| 2056.0, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/ |
| }, |
| { |
| "negative bignum 0xc349010000000000000000 -18446744073709551617", |
| {(uint8_t[]){0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 11}, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -18446744073709551617.0, |
| QCBOR_SUCCESS |
| }, |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| { |
| "Positive bignum 0x01020304 indefinite length string", |
| {(uint8_t[]){0xC2, 0x5f, 0x42, 0x01, 0x02, 0x41, 0x03, 0x41, 0x04, 0xff}, 10}, |
| 0x01020304, |
| QCBOR_SUCCESS, |
| 0x01020304, |
| QCBOR_SUCCESS, |
| 16909060.0, |
| QCBOR_SUCCESS |
| }, |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| { |
| "Decimal Fraction with neg bignum [9223372036854775807, -4759477275222530853137]", |
| {(uint8_t[]){0xC4, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,}, 23}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -INFINITY, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| }, |
| { |
| "big float [9223372036854775806, 9223372036854775806]", |
| {(uint8_t[]){0xC5, 0x82, 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 20}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| INFINITY, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| }, |
| { |
| "Big float 3 * 2^^2", |
| {(uint8_t[]){0xC5, 0x82, 0x02, 0x03}, 4}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 12, |
| QCBOR_SUCCESS, |
| 12, |
| QCBOR_SUCCESS, |
| 12.0, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| }, |
| { |
| "Positive integer 18446744073709551615", |
| {(uint8_t[]){0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 9}, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 18446744073709551615ULL, |
| QCBOR_SUCCESS, |
| 18446744073709551615.0, |
| QCBOR_SUCCESS |
| }, |
| { |
| "Positive bignum 0xffff", |
| {(uint8_t[]){0xC2, 0x42, 0xff, 0xff}, 4}, |
| 65536-1, |
| QCBOR_SUCCESS, |
| 0xffff, |
| QCBOR_SUCCESS, |
| 65535.0, |
| QCBOR_SUCCESS |
| }, |
| { |
| "Postive integer 0", |
| {(uint8_t[]){0x0}, 1}, |
| 0LL, |
| QCBOR_SUCCESS, |
| 0ULL, |
| QCBOR_SUCCESS, |
| 0.0, |
| QCBOR_SUCCESS |
| }, |
| { |
| "Negative integer -18446744073709551616", |
| {(uint8_t[]){0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 9}, |
| -9223372036854775807-1, // INT64_MIN |
| QCBOR_SUCCESS, |
| 0ULL, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -9223372036854775808.0, |
| QCBOR_SUCCESS |
| }, |
| { |
| "Double Floating point value 100.3", |
| {(uint8_t[]){0xfb, 0x40, 0x59, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33}, 9}, |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| 100L, |
| QCBOR_SUCCESS, |
| 100ULL, |
| QCBOR_SUCCESS, |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| 100.3, |
| QCBOR_SUCCESS |
| }, |
| { |
| "Floating point value NaN 0xfa7fc00000", |
| {(uint8_t[]){0xfa, 0x7f, 0xc0, 0x00, 0x00}, 5}, |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| 0, |
| QCBOR_ERR_FLOAT_EXCEPTION, |
| 0, |
| QCBOR_ERR_FLOAT_EXCEPTION, |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| NAN, |
| QCBOR_SUCCESS |
| }, |
| { |
| "half-precision Floating point value -4", |
| {(uint8_t[]){0xf9, 0xc4, 0x00}, 3}, |
| #ifndef QCBOR_DISABLE_PREFERRED_FLOAT |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| // Normal case with all enabled. |
| -4, |
| QCBOR_SUCCESS, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -4.0, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| // Float HW disabled |
| -4, |
| QCBOR_ERR_HW_FLOAT_DISABLED, // Can't convert to integer |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, // Can't convert to integer |
| -4.0, |
| QCBOR_SUCCESS // Uses ieee754.h to conver, not HW |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| #else /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| // Half-precision disabled |
| -4, |
| QCBOR_ERR_HALF_PRECISION_DISABLED, |
| 0, |
| QCBOR_ERR_HALF_PRECISION_DISABLED, |
| -4.0, |
| QCBOR_ERR_HALF_PRECISION_DISABLED |
| #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| }, |
| { |
| "Decimal fraction 3/10", |
| {(uint8_t[]){0xC4, 0x82, 0x20, 0x03}, 4}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0.30000000000000004, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| }, |
| { |
| "+inifinity", |
| {(uint8_t[]){0xfa, 0x7f, 0x80, 0x00, 0x00}, 5}, |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| 0, |
| QCBOR_ERR_FLOAT_EXCEPTION, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| INFINITY, |
| QCBOR_SUCCESS |
| }, |
| |
| { |
| "extreme pos bignum", |
| {(uint8_t[]){0xc2, 0x59, 0x01, 0x90, |
| // 50 rows of 8 is 400 digits. |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0}, |
| 404}, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| INFINITY, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| }, |
| |
| { |
| "extreme neg bignum", |
| {(uint8_t[]){0xc3, 0x59, 0x01, 0x90, |
| // 50 rows of 8 is 400 digits. |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, |
| 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0}, |
| 404}, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| -INFINITY, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| 0, |
| QCBOR_ERR_HW_FLOAT_DISABLED, |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| }, |
| |
| { |
| "big float underflow [9223372036854775806, -9223372036854775806]", |
| {(uint8_t[]){ |
| 0xC5, 0x82, |
| 0x3B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, |
| 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 20}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| }, |
| |
| { |
| "bigfloat that evaluates to -INFINITY", |
| {(uint8_t[]){ |
| 0xC5, 0x82, |
| 0x1B, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, |
| 0xC3, 0x42, 0x01, 0x01}, 15}, |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| 0, |
| QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, |
| 0, |
| QCBOR_ERR_NUMBER_SIGN_CONVERSION, |
| -INFINITY, |
| QCBOR_SUCCESS |
| #else /* QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0, |
| QCBOR_ERR_UNEXPECTED_TYPE, |
| 0.0, |
| QCBOR_ERR_UNEXPECTED_TYPE |
| #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/ |
| }, |
| }; |
| |
| |
| |
| |
| static int32_t SetUpDecoder(QCBORDecodeContext *DCtx, UsefulBufC CBOR, UsefulBuf Pool) |
| { |
| QCBORDecode_Init(DCtx, CBOR, QCBOR_DECODE_MODE_NORMAL); |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| if(QCBORDecode_SetMemPool(DCtx, Pool, 0)) { |
| return 1; |
| } |
| #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| (void)Pool; |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| return 0; |
| } |
| |
| |
| int32_t IntegerConvertTest() |
| { |
| const int nNumTests = C_ARRAY_COUNT(NumberConversions, |
| struct NumberConversion); |
| |
| for(int nIndex = 0; nIndex < nNumTests; nIndex++) { |
| const struct NumberConversion *pF = &NumberConversions[nIndex]; |
| |
| // Set up the decoding context including a memory pool so that |
| // indefinite length items can be checked |
| QCBORDecodeContext DCtx; |
| UsefulBuf_MAKE_STACK_UB(Pool, 100); |
| |
| /* ----- test conversion to int64_t ------ */ |
| if(SetUpDecoder(&DCtx, pF->CBOR, Pool)) { |
| return (int32_t)(3333+nIndex); |
| } |
| |
| int64_t nInt; |
| QCBORDecode_GetInt64ConvertAll(&DCtx, 0xffff, &nInt); |
| if(QCBORDecode_GetError(&DCtx) != pF->uErrorInt64) { |
| return (int32_t)(2000+nIndex); |
| } |
| if(pF->uErrorInt64 == QCBOR_SUCCESS && pF->nConvertedToInt64 != nInt) { |
| return (int32_t)(3000+nIndex); |
| } |
| |
| /* ----- test conversion to uint64_t ------ */ |
| if(SetUpDecoder(&DCtx, pF->CBOR, Pool)) { |
| return (int32_t)(3333+nIndex); |
| } |
| |
| uint64_t uInt; |
| QCBORDecode_GetUInt64ConvertAll(&DCtx, 0xffff, &uInt); |
| if(QCBORDecode_GetError(&DCtx) != pF->uErrorUint64) { |
| return (int32_t)(4000+nIndex); |
| } |
| if(pF->uErrorUint64 == QCBOR_SUCCESS && pF->uConvertToUInt64 != uInt) { |
| return (int32_t)(5000+nIndex); |
| } |
| |
| /* ----- test conversion to double ------ */ |
| if(SetUpDecoder(&DCtx, pF->CBOR, Pool)) { |
| return (int32_t)(3333+nIndex); |
| } |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| double d; |
| QCBORDecode_GetDoubleConvertAll(&DCtx, 0xffff, &d); |
| if(QCBORDecode_GetError(&DCtx) != pF->uErrorDouble) { |
| return (int32_t)(6000+nIndex); |
| } |
| if(pF->uErrorDouble == QCBOR_SUCCESS) { |
| if(isnan(pF->dConvertToDouble)) { |
| // NaN's can't be compared for equality. A NaN is |
| // never equal to anything including another NaN |
| if(!isnan(d)) { |
| return (int32_t)(7000+nIndex); |
| } |
| } else { |
| if(pF->dConvertToDouble != d) { |
| return (int32_t)(8000+nIndex); |
| } |
| } |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| int32_t CBORSequenceDecodeTests(void) |
| { |
| QCBORDecodeContext DCtx; |
| QCBORItem Item; |
| QCBORError uCBORError; |
| size_t uConsumed; |
| |
| // --- Test a sequence with extra bytes --- |
| |
| // The input for the date test happens to be a sequence so it |
| // is reused. It is a sequence because it doesn't start as |
| // an array or map. |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| // Get the first item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 1; |
| } |
| if(Item.uDataType != QCBOR_TYPE_DATE_STRING) { |
| return 2; |
| } |
| |
| uCBORError = QCBORDecode_PartialFinish(&DCtx, &uConsumed); |
| if(uCBORError != QCBOR_ERR_EXTRA_BYTES || |
| uConsumed != 12) { |
| return 102; |
| } |
| |
| // Get a second item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uCBORError != QCBOR_ERR_BAD_OPT_TAG) { |
| return 66; |
| } |
| |
| uCBORError = QCBORDecode_PartialFinish(&DCtx, &uConsumed); |
| if(uCBORError != QCBOR_ERR_EXTRA_BYTES || |
| uConsumed != 14) { |
| return 102; |
| } |
| |
| // Get a third item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 2; |
| } |
| if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH) { |
| return 3; |
| } |
| |
| // A sequence can have stuff at the end that may |
| // or may not be valid CBOR. The protocol decoder knows |
| // when to stop by definition of the protocol, not |
| // when the top-level map or array is ended. |
| // Finish still has to be called to know that |
| // maps and arrays (if there were any) were closed |
| // off correctly. When called like this it |
| // must return the error QCBOR_ERR_EXTRA_BYTES. |
| uCBORError = QCBORDecode_Finish(&DCtx); |
| if(uCBORError != QCBOR_ERR_EXTRA_BYTES) { |
| return 4; |
| } |
| |
| |
| // --- Test an empty input ---- |
| uint8_t empty[1]; |
| UsefulBufC Empty = {empty, 0}; |
| QCBORDecode_Init(&DCtx, |
| Empty, |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| uCBORError = QCBORDecode_Finish(&DCtx); |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 5; |
| } |
| |
| |
| // --- Sequence with unclosed indefinite length array --- |
| static const uint8_t xx[] = {0x01, 0x9f, 0x02}; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(xx), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| // Get the first item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 7; |
| } |
| if(Item.uDataType != QCBOR_TYPE_INT64) { |
| return 8; |
| } |
| |
| // Get a second item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 9; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return 10; |
| } |
| |
| // Try to finish before consuming all bytes to confirm |
| // that the still-open error is returned. |
| uCBORError = QCBORDecode_Finish(&DCtx); |
| if(uCBORError != QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED) { |
| return 11; |
| } |
| #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| if(uCBORError != QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED) { |
| return 20; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| // --- Sequence with a closed indefinite length array --- |
| static const uint8_t yy[] = {0x01, 0x9f, 0xff}; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(yy), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| // Get the first item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 12; |
| } |
| if(Item.uDataType != QCBOR_TYPE_INT64) { |
| return 13; |
| } |
| |
| // Get a second item |
| uCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 14; |
| } |
| if(Item.uDataType != QCBOR_TYPE_ARRAY) { |
| return 15; |
| } |
| |
| // Try to finish before consuming all bytes to confirm |
| // that the still-open error is returned. |
| uCBORError = QCBORDecode_Finish(&DCtx); |
| if(uCBORError != QCBOR_SUCCESS) { |
| return 16; |
| } |
| #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| if(uCBORError != QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED) { |
| return 20; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| return 0; |
| } |
| |
| |
| |
| int32_t IntToTests() |
| { |
| int nErrCode; |
| int32_t n32; |
| int16_t n16; |
| int8_t n8; |
| uint32_t u32; |
| uint16_t u16; |
| uint8_t u8; |
| uint64_t u64; |
| |
| nErrCode = QCBOR_Int64ToInt32(1, &n32); |
| if(nErrCode == -1 || n32 != 1) { |
| return 1; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt32((int64_t)INT32_MAX, &n32); |
| if(nErrCode == -1 || n32 != INT32_MAX) { |
| return 2; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt32((int64_t)INT32_MIN, &n32); |
| if(nErrCode == -1 || n32 != INT32_MIN) { |
| return 3; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt32(((int64_t)INT32_MAX)+1, &n32); |
| if(nErrCode != -1) { |
| return 4; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt32(((int64_t)INT32_MIN)-1, &n32); |
| if(nErrCode != -1) { |
| return 5; |
| } |
| |
| |
| nErrCode = QCBOR_Int64ToInt16((int64_t)INT16_MAX, &n16); |
| if(nErrCode == -1 || n16 != INT16_MAX) { |
| return 6; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt16((int64_t)INT16_MIN, &n16); |
| if(nErrCode == -1 || n16 != INT16_MIN) { |
| return 7; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt16(1, &n16); |
| if(nErrCode == -1 || n16 != 1) { |
| return 8; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt16(((int64_t)INT16_MAX)+1, &n16); |
| if(nErrCode != -1) { |
| return 9; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt16(((int64_t)INT16_MIN)-1, &n16); |
| if(nErrCode != -1) { |
| return 10; |
| } |
| |
| |
| nErrCode = QCBOR_Int64ToInt8(1, &n8); |
| if(nErrCode == -1 || n8 != 1) { |
| return 11; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt8((int64_t)INT8_MAX, &n8); |
| if(nErrCode == -1 || n8 != INT8_MAX) { |
| return 12; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt8((int64_t)INT8_MIN, &n8); |
| if(nErrCode == -1 || n8 != INT8_MIN) { |
| return 13; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt8(((int64_t)INT8_MAX)+1, &n8); |
| if(nErrCode != -1) { |
| return 14; |
| } |
| |
| nErrCode = QCBOR_Int64ToInt8(((int64_t)INT8_MIN)-1, &n8); |
| if(nErrCode != -1) { |
| return 15; |
| } |
| |
| |
| nErrCode = QCBOR_Int64ToUInt32(1, &u32); |
| if(nErrCode == -1 || u32 != 1) { |
| return 16; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt32((int64_t)UINT32_MAX, &u32); |
| if(nErrCode == -1 || u32 != UINT32_MAX) { |
| return 17; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt32((int64_t)0, &u32); |
| if(nErrCode == -1 || u32 != 0) { |
| return 18; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt32(((int64_t)UINT32_MAX)+1, &u32); |
| if(nErrCode != -1) { |
| return 19; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt32((int64_t)-1, &u32); |
| if(nErrCode != -1) { |
| return 20; |
| } |
| |
| |
| nErrCode = QCBOR_Int64UToInt16((int64_t)UINT16_MAX, &u16); |
| if(nErrCode == -1 || u16 != UINT16_MAX) { |
| return 21; |
| } |
| |
| nErrCode = QCBOR_Int64UToInt16((int64_t)0, &u16); |
| if(nErrCode == -1 || u16 != 0) { |
| return 22; |
| } |
| |
| nErrCode = QCBOR_Int64UToInt16(1, &u16); |
| if(nErrCode == -1 || u16 != 1) { |
| return 23; |
| } |
| |
| nErrCode = QCBOR_Int64UToInt16(((int64_t)UINT16_MAX)+1, &u16); |
| if(nErrCode != -1) { |
| return 24; |
| } |
| |
| nErrCode = QCBOR_Int64UToInt16((int64_t)-1, &u16); |
| if(nErrCode != -1) { |
| return 25; |
| } |
| |
| |
| nErrCode = QCBOR_Int64ToUInt8((int64_t)UINT8_MAX, &u8); |
| if(nErrCode == -1 || u8 != UINT8_MAX) { |
| return 26; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt8((int64_t)0, &u8); |
| if(nErrCode == -1 || u8 != 0) { |
| return 27; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt8(1, &u8); |
| if(nErrCode == -1 || u8 != 1) { |
| return 28; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt8(((int64_t)UINT16_MAX)+1, &u8); |
| if(nErrCode != -1) { |
| return 29; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt8((int64_t)-1, &u8); |
| if(nErrCode != -1) { |
| return 30; |
| } |
| |
| |
| nErrCode = QCBOR_Int64ToUInt64(1, &u64); |
| if(nErrCode == -1 || u64 != 1) { |
| return 31; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt64(INT64_MAX, &u64); |
| if(nErrCode == -1 || u64 != INT64_MAX) { |
| return 32; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt64((int64_t)0, &u64); |
| if(nErrCode == -1 || u64 != 0) { |
| return 33; |
| } |
| |
| nErrCode = QCBOR_Int64ToUInt64((int64_t)-1, &u64); |
| if(nErrCode != -1) { |
| return 34; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| /* |
| A sequence with |
| A wrapping bstr |
| containing a map |
| 1 |
| 2 |
| A wrapping bstr |
| containing an array |
| 3 |
| wrapping bstr |
| 4 |
| 5 |
| 6 |
| array |
| 7 |
| 8 |
| */ |
| |
| static UsefulBufC EncodeBstrWrapTestData(UsefulBuf OutputBuffer) |
| { |
| UsefulBufC Encoded; |
| QCBOREncodeContext EC; |
| QCBORError uErr; |
| |
| QCBOREncode_Init(&EC, OutputBuffer); |
| |
| QCBOREncode_BstrWrap(&EC); |
| QCBOREncode_OpenMap(&EC); |
| QCBOREncode_AddInt64ToMapN(&EC, 100, 1); |
| QCBOREncode_AddInt64ToMapN(&EC, 200, 2); |
| QCBOREncode_CloseMap(&EC); |
| QCBOREncode_BstrWrap(&EC); |
| QCBOREncode_OpenArray(&EC); |
| QCBOREncode_AddInt64(&EC, 3); |
| QCBOREncode_BstrWrap(&EC); |
| QCBOREncode_AddInt64(&EC, 4); |
| QCBOREncode_CloseBstrWrap(&EC, NULL); |
| QCBOREncode_AddInt64(&EC, 5); |
| QCBOREncode_CloseArray(&EC); |
| QCBOREncode_CloseBstrWrap(&EC, NULL); |
| QCBOREncode_AddInt64(&EC, 6); |
| QCBOREncode_CloseBstrWrap(&EC, NULL); |
| QCBOREncode_OpenArray(&EC); |
| QCBOREncode_AddInt64(&EC, 7); |
| QCBOREncode_AddInt64(&EC, 8); |
| QCBOREncode_CloseArray(&EC); |
| |
| uErr = QCBOREncode_Finish(&EC, &Encoded); |
| if(uErr) { |
| Encoded = NULLUsefulBufC; |
| } |
| |
| return Encoded; |
| } |
| |
| /* h'FF' */ |
| static const uint8_t spBreakInByteString[] = { |
| 0x41, 0xff |
| }; |
| |
| |
| int32_t EnterBstrTest() |
| { |
| UsefulBuf_MAKE_STACK_UB(OutputBuffer, 100); |
| |
| QCBORDecodeContext DC; |
| |
| QCBORDecode_Init(&DC, EncodeBstrWrapTestData(OutputBuffer), 0); |
| |
| int64_t n1, n2, n3, n4, n5, n6, n7, n8; |
| |
| |
| QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| QCBORDecode_EnterMap(&DC, NULL); |
| QCBORDecode_GetInt64InMapN(&DC, 100, &n1); |
| QCBORDecode_GetInt64InMapN(&DC, 200, &n2); |
| QCBORDecode_ExitMap(&DC); |
| QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| QCBORDecode_EnterArray(&DC, NULL); |
| QCBORDecode_GetInt64(&DC, &n3); |
| QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| QCBORDecode_GetInt64(&DC, &n4); |
| QCBORDecode_ExitBstrWrapped(&DC); |
| QCBORDecode_GetInt64(&DC, &n5); |
| QCBORDecode_ExitArray(&DC); |
| QCBORDecode_ExitBstrWrapped(&DC); |
| QCBORDecode_GetInt64(&DC, &n6); |
| QCBORDecode_ExitBstrWrapped(&DC); |
| QCBORDecode_EnterArray(&DC, NULL); |
| QCBORDecode_GetInt64(&DC, &n7); |
| QCBORDecode_GetInt64(&DC, &n8); |
| QCBORDecode_ExitArray(&DC); |
| |
| QCBORError uErr = QCBORDecode_Finish(&DC); |
| if(uErr) { |
| return (int32_t)uErr; |
| } |
| |
| |
| /* Enter and exit byte string wrapped CBOR that is bad. It has just a break. |
| * Successful because no items are fetched from byte string. |
| */ |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBreakInByteString), |
| 0); |
| QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr) { |
| return 100 + (int32_t)uErr; |
| } |
| |
| QCBORDecode_ExitBstrWrapped(&DC); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr) { |
| return 200 + (int32_t)uErr; |
| } |
| |
| /* Try to get item that is a break out of a byte string wrapped CBOR. |
| * It fails because there should be no break. |
| */ |
| QCBORDecode_Init(&DC, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBreakInByteString), |
| 0); |
| QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| QCBORItem Item; |
| uErr = QCBORDecode_GetNext(&DC, &Item); |
| if(uErr != QCBOR_ERR_BAD_BREAK) { |
| return 300 + (int32_t)uErr; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| static const uint8_t spTaggedTypes[] = { |
| 0xb2, |
| |
| // Date string |
| 0x00, |
| 0xc0, 0x74, 0x32, 0x30, 0x30, 0x33, 0x2D, 0x31, 0x32, 0x2D, |
| 0x31, 0x33, 0x54, 0x31, 0x38, 0x3A, 0x33, 0x30, 0x3A, 0x30, |
| 0x32, 0x5A, |
| |
| 0x01, |
| 0x74, 0x32, 0x30, 0x30, 0x33, 0x2D, 0x31, 0x32, 0x2D, 0x31, |
| 0x33, 0x54, 0x31, 0x38, 0x3A, 0x33, 0x30, 0x3A, 0x30, 0x32, |
| 0x5A, |
| |
| // Bignum |
| 10, |
| 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x10, |
| |
| 11, |
| 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x10, |
| |
| // URL |
| 20, |
| 0xd8, 0x20, 0x6f, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, |
| 0x63, 0x62, 0x6F, 0x72, 0x2E, 0x6D, 0x65, 0x2F, |
| |
| 21, |
| 0x6f, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x62, |
| 0x6F, 0x72, 0x2E, 0x6D, 0x65, 0x2F, |
| |
| // B64 |
| 0x18, 0x1e, |
| 0xd8, 0x22, 0x6c, 0x63, 0x47, 0x78, 0x6C, 0x59, 0x58, 0x4E, |
| 0x31, 0x63, 0x6D, 0x55, 0x75, |
| |
| 0x18, 0x1f, |
| 0x6c, 0x63, 0x47, 0x78, 0x6C, 0x59, 0x58, 0x4E, 0x31, 0x63, |
| 0x6D, 0x55, 0x75, |
| |
| // B64URL |
| 0x18, 0x28, |
| 0xd8, 0x21, 0x6c, 0x63, 0x47, 0x78, 0x6C, 0x59, 0x58, 0x4E, |
| 0x31, 0x63, 0x6D, 0x55, 0x75, |
| |
| 0x18, 0x29, |
| 0x6c, 0x63, 0x47, 0x78, 0x6C, 0x59, 0x58, 0x4E, 0x31, 0x63, |
| 0x6D, 0x55, 0x75, |
| |
| // Regex |
| 0x18, 0x32, |
| 0xd8, 0x23, 0x68, 0x31, 0x30, 0x30, 0x5C, 0x73, 0x2A, 0x6D, |
| 0x6B, |
| |
| 0x18, 0x33, |
| 0x68, 0x31, 0x30, 0x30, 0x5C, 0x73, 0x2A, 0x6D, 0x6B, |
| |
| // MIME |
| 0x18, 0x3c, |
| 0xd8, 0x24, 0x72, 0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, |
| 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, 0x30, |
| 0x0A, |
| |
| 0x18, 0x3d, |
| 0x72, 0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, 0x73, |
| 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, 0x30, 0x0A, |
| |
| 0x18, 0x3e, |
| 0xd9, 0x01, 0x01, 0x52, 0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, |
| 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, |
| 0x30, 0x0A, |
| |
| 0x18, 0x3f, |
| 0x52, 0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, 0x73, |
| 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, 0x30, 0x0A, |
| |
| // UUID |
| 0x18, 0x46, |
| 0xd8, 0x25, 0x50, 0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, |
| 0x4C, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32, |
| |
| 0x18, 0x47, |
| 0x50, 0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4C, 0x54, |
| 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32 |
| }; |
| |
| int32_t DecodeTaggedTypeTests() |
| { |
| QCBORDecodeContext DC; |
| QCBORError uErr; |
| |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTaggedTypes), 0); |
| |
| UsefulBufC String; |
| bool bNeg; |
| |
| QCBORDecode_EnterMap(&DC, NULL); |
| QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &String); |
| if(QCBORDecode_GetError(&DC) != QCBOR_SUCCESS) { |
| return 1; |
| } |
| QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 2; |
| } |
| QCBORDecode_GetDateStringInMapN(&DC, 1, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 3; |
| } |
| QCBORDecode_GetDateStringInMapN(&DC, 1, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &String); |
| QCBORDecode_GetDateStringInMapN(&DC, 1, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 4; |
| } |
| QCBORDecode_GetDateStringInMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 5; |
| } |
| |
| QCBORDecode_GetBignumInMapN(&DC, 10, QCBOR_TAG_REQUIREMENT_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS || |
| bNeg != false) { |
| return 10; |
| } |
| QCBORDecode_GetBignumInMapN(&DC, 11, QCBOR_TAG_REQUIREMENT_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS || |
| bNeg != true) { |
| return 11; |
| } |
| QCBORDecode_GetBignumInMapN(&DC, 11, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 12; |
| } |
| QCBORDecode_GetBignumInMapN(&DC, 14, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 13; |
| } |
| QCBORDecode_GetBignumInMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 14; |
| } |
| |
| QCBORDecode_GetURIInMapN(&DC, 20, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 20; |
| } |
| QCBORDecode_GetURIInMapN(&DC, 21, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 21; |
| } |
| QCBORDecode_GetURIInMapN(&DC, 22, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 22; |
| } |
| QCBORDecode_GetURIInMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 23; |
| } |
| |
| #ifndef QCBOR_DISABLE_UNCOMMON_TAGS |
| QCBORDecode_GetB64InMapN(&DC, 30, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 30; |
| } |
| #endif |
| QCBORDecode_GetB64InMapN(&DC, 31, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 31; |
| } |
| QCBORDecode_GetB64InMapN(&DC, 32, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 32; |
| } |
| QCBORDecode_GetB64InMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 33; |
| } |
| |
| #ifndef QCBOR_DISABLE_UNCOMMON_TAGS |
| QCBORDecode_GetB64URLInMapN(&DC, 40, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 40; |
| } |
| #endif |
| QCBORDecode_GetB64URLInMapN(&DC, 41, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 41; |
| } |
| QCBORDecode_GetB64URLInMapN(&DC, 42, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 42; |
| } |
| QCBORDecode_GetB64URLInMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 43; |
| } |
| |
| #ifndef QCBOR_DISABLE_UNCOMMON_TAGS |
| QCBORDecode_GetRegexInMapN(&DC, 50, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 50; |
| } |
| #endif |
| QCBORDecode_GetRegexInMapN(&DC, 51, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 51; |
| } |
| QCBORDecode_GetRegexInMapN(&DC, 52, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 52; |
| } |
| QCBORDecode_GetRegexInMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 53; |
| } |
| |
| #ifndef QCBOR_DISABLE_UNCOMMON_TAGS |
| // MIME |
| bool bIsNot7Bit; |
| QCBORDecode_GetMIMEMessageInMapN(&DC, 60, QCBOR_TAG_REQUIREMENT_TAG, &String, &bIsNot7Bit); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS || |
| bIsNot7Bit == true) { |
| return 60; |
| } |
| QCBORDecode_GetMIMEMessageInMapN(&DC, 61, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String, &bIsNot7Bit); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS || |
| bIsNot7Bit == true) { |
| return 61; |
| } |
| QCBORDecode_GetMIMEMessageInMapN(&DC, 62, QCBOR_TAG_REQUIREMENT_TAG, &String, &bIsNot7Bit); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS || |
| bIsNot7Bit == false) { |
| return 62; |
| } |
| QCBORDecode_GetMIMEMessageInMapN(&DC, 63, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String, &bIsNot7Bit); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS || |
| bIsNot7Bit == false) { |
| return 63; |
| } |
| QCBORDecode_GetMIMEMessageInMapN(&DC, 64, QCBOR_TAG_REQUIREMENT_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 64; |
| } |
| QCBORDecode_GetMIMEMessageInMapSZ(&DC, "zzz", QCBOR_TAG_REQUIREMENT_TAG, &String, &bNeg); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 65; |
| } |
| |
| |
| QCBORDecode_GetBinaryUUIDInMapN(&DC, 70, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 70; |
| } |
| #endif /* #ifndef QCBOR_DISABLE_UNCOMMON_TAGS */ |
| |
| QCBORDecode_GetBinaryUUIDInMapN(&DC, 71, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_SUCCESS) { |
| return 71; |
| } |
| QCBORDecode_GetBinaryUUIDInMapN(&DC, 72, QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 72; |
| } |
| QCBORDecode_GetBinaryUUIDInMapSZ(&DC, "xxx", QCBOR_TAG_REQUIREMENT_TAG, &String); |
| if(QCBORDecode_GetAndResetError(&DC) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 73; |
| } |
| |
| // Improvement: add some more error test cases |
| |
| QCBORDecode_ExitMap(&DC); |
| |
| uErr = QCBORDecode_Finish(&DC); |
| if(uErr != QCBOR_SUCCESS) { |
| return 100; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| |
| /* |
| [ |
| "aaaaaaaaaa", |
| {} |
| ] |
| */ |
| static const uint8_t spTooLarge1[] = { |
| 0x9f, |
| 0x6a, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0xa0, |
| 0xff |
| }; |
| |
| /* |
| [ |
| { |
| 0: "aaaaaaaaaa" |
| } |
| ] |
| */ |
| static const uint8_t spTooLarge2[] = { |
| 0x9f, |
| 0xa1, |
| 0x00, |
| 0x6a, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| 0xff |
| }; |
| |
| /* |
| h'A1006A61616161616161616161' |
| |
| { |
| 0: "aaaaaaaaaa" |
| } |
| */ |
| static const uint8_t spTooLarge3[] = { |
| 0x4d, |
| 0xa1, |
| 0x00, |
| 0x6a, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, |
| }; |
| |
| int32_t TooLargeInputTest(void) |
| { |
| QCBORDecodeContext DC; |
| QCBORError uErr; |
| UsefulBufC String; |
| |
| // These tests require a build with QCBOR_MAX_DECODE_INPUT_SIZE set |
| // to 10 There's not really any way to test this error |
| // condition. The error condition is not complex, so setting |
| // QCBOR_MAX_DECODE_INPUT_SIZE gives an OK test. |
| |
| // The input CBOR is only too large because the |
| // QCBOR_MAX_DECODE_INPUT_SIZE is 10. |
| // |
| // This test is disabled for the normal test runs because of the |
| // special build requirement. |
| |
| |
| // Tests the start of a map being too large |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooLarge1), QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_EnterArray(&DC, NULL); |
| QCBORDecode_GetTextString(&DC, &String); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr != QCBOR_SUCCESS) { |
| return 1; |
| } |
| QCBORDecode_EnterMap(&DC, NULL); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr != QCBOR_ERR_INPUT_TOO_LARGE) { |
| return 2; |
| } |
| |
| // Tests the end of a map being too large |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooLarge2), QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_EnterArray(&DC, NULL); |
| QCBORDecode_EnterMap(&DC, NULL); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr != QCBOR_SUCCESS) { |
| return 3; |
| } |
| QCBORDecode_ExitMap(&DC); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr != QCBOR_ERR_INPUT_TOO_LARGE) { |
| return 4; |
| } |
| |
| // Tests the entire input CBOR being too large when processing bstr wrapping |
| QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooLarge3), QCBOR_DECODE_MODE_NORMAL); |
| QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| uErr = QCBORDecode_GetError(&DC); |
| if(uErr != QCBOR_ERR_INPUT_TOO_LARGE) { |
| return 5; |
| } |
| |
| return 0; |
| } |
| |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| |
| static const uint8_t spMapWithIndefLenStrings[] = { |
| 0xa3, |
| 0x7f, 0x61, 'l', 0x64, 'a', 'b', 'e', 'l' , 0x61, '1', 0xff, |
| 0x5f, 0x42, 0x01, 0x02, 0x43, 0x03, 0x04, 0x05, 0xff, |
| 0x7f, 0x62, 'd', 'y', 0x61, 'm', 0x61, 'o', 0xff, |
| 0x03, |
| 0x7f, 0x62, 'l', 'a', 0x63, 'b', 'e', 'l', 0x61, '2', 0xff, |
| 0xc3, |
| 0x5f, 0x42, 0x00, 0x01, 0x42, 0x00, 0x01, 0x41, 0x01, 0xff, |
| }; |
| |
| int32_t SpiffyIndefiniteLengthStringsTests() |
| { |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spMapWithIndefLenStrings), |
| QCBOR_DECODE_MODE_NORMAL); |
| |
| UsefulBuf_MAKE_STACK_UB(StringBuf, 200); |
| QCBORDecode_SetMemPool(&DCtx, StringBuf, false); |
| |
| UsefulBufC ByteString; |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetByteStringInMapSZ(&DCtx, "label1", &ByteString); |
| if(QCBORDecode_GetAndResetError(&DCtx)) { |
| return 1; |
| } |
| |
| const uint8_t pExectedBytes[] = {0x01, 0x02, 0x03, 0x04, 0x05}; |
| if(UsefulBuf_Compare(ByteString, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExectedBytes))) { |
| return 2; |
| } |
| |
| uint64_t uInt; |
| QCBORDecode_GetUInt64InMapSZ(&DCtx, "dymo", &uInt); |
| if(QCBORDecode_GetAndResetError(&DCtx)) { |
| return 3; |
| } |
| if(uInt != 3) { |
| return 4; |
| } |
| |
| double uDouble; |
| QCBORDecode_GetDoubleConvertAllInMapSZ(&DCtx, |
| "label2", |
| 0xff, |
| &uDouble); |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| if(QCBORDecode_GetAndResetError(&DCtx)) { |
| return 5; |
| } |
| if(uDouble != -16777474) { |
| return 6; |
| } |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_HW_FLOAT_DISABLED) { |
| return 7; |
| } |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| |
| |
| QCBORDecode_ExitMap(&DCtx); |
| |
| if(QCBORDecode_Finish(&DCtx)) { |
| return 99; |
| } |
| |
| return 0; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| /* |
| * An array of an integer and an array. The second array contains |
| * a bstr-wrapped map. |
| * |
| * [7, [h'A36D6669... (see next lines) 73']] |
| * |
| * {"first integer": 42, |
| * "an array of two strings": ["string1", "string2"], |
| * "map in a map": |
| * { "bytes 1": h'78787878', |
| * "bytes 2": h'79797979', |
| * "another int": 98, |
| * "text 2": "lies, damn lies and statistics" |
| * } |
| * } |
| */ |
| |
| static const uint8_t pValidWrappedMapEncoded[] = { |
| 0x82, 0x07, 0x81, 0x58, 0x97, |
| 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, |
| 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e, |
| 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, |
| 0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, |
| 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, |
| 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, |
| 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, |
| 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, |
| 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65, |
| 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, |
| 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, |
| 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, |
| 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, |
| 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, |
| 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, |
| 0x73 |
| }; |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| |
| /* As above, but the arrays are indefinite length */ |
| static const uint8_t pValidIndefWrappedMapEncoded[] = { |
| 0x9f, 0x07, 0x9f, 0x58, 0x97, |
| 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, |
| 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e, |
| 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, |
| 0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, |
| 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, |
| 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, |
| 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, |
| 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, |
| 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65, |
| 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, |
| 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, |
| 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, |
| 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, |
| 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, |
| 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, |
| 0x73, |
| 0xff, 0xff |
| }; |
| #endif |
| |
| |
| static const uint8_t pWithEmptyMap[] = {0x82, 0x18, 0x64, 0xa0}; |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| static const uint8_t pWithEmptyMapInDef[] = {0x9f, 0x18, 0x64, 0xbf, 0xff, 0xff}; |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| static const uint8_t pWrappedByIndefiniteLength[] = { |
| 0x81, |
| 0xd8, 0x18, |
| 0x5f, |
| 0x41, 0x83, |
| 0x41, 0x18, |
| 0x43, 0x2A, 0x18, 0x2B, |
| 0x42, 0x18, 0x2C, |
| 0xff |
| }; |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| int32_t PeekAndRewindTest() |
| { |
| QCBORItem Item; |
| QCBORError nCBORError; |
| QCBORDecodeContext DCtx; |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0); |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return 100+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 200; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 300; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return 400 + (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 500; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 600; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return 900 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return 1000; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 1100 + (int32_t)nCBORError; |
| } |
| |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return 1200; |
| } |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 1300 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return 1400; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 1500 + (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return 1600; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return 1700 + (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return 1800; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return 1900; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return 2000; |
| } |
| |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 2100 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "map in a map") || |
| Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 4) { |
| return 2100; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 2200 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 1"))|| |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "xxxx")) { |
| return 2300; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return 2400 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "bytes 2") || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "yyyy")) { |
| return 2500; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 2600 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBufCompareToSZ(Item.label.string, "bytes 2") || |
| Item.uDataType != QCBOR_TYPE_BYTE_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "yyyy")) { |
| return 2700; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 2800 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "another int") || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 98) { |
| return 2900; |
| } |
| |
| if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) { |
| return 3000 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "lies, damn lies and statistics")) { |
| return 3100; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 3200 + (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| |
| Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "lies, damn lies and statistics")) { |
| return 3300; |
| } |
| |
| |
| |
| // Rewind to top level after entering several maps |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 3) { |
| return 400; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 4000+(int32_t)nCBORError; |
| } |
| |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return 4100; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 4100+(int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return 4200; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 4200+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return 4300; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 4300+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return 4400; |
| } |
| |
| QCBORDecode_Rewind(&DCtx); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 4400+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || |
| Item.val.uCount != 3) { |
| return 4500; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return 4600; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return 4700; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return 4800; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 4900+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return 5000; |
| } |
| |
| |
| // Rewind an entered map |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5100+(int32_t)nCBORError; |
| } |
| |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return 5200; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5200+(int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return -5300; |
| } |
| |
| QCBORDecode_Rewind(&DCtx); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5300+(int32_t)nCBORError; |
| } |
| |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataType != QCBOR_TYPE_INT64 || |
| Item.val.int64 != 42 || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "first integer")) { |
| return 5400; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5400+(int32_t)nCBORError; |
| } |
| if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.label.string, "an array of two strings") || |
| Item.uDataType != QCBOR_TYPE_ARRAY || |
| Item.val.uCount != 2) { |
| return 5500; |
| } |
| |
| |
| // Rewind and entered array inside an entered map |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| QCBORDecode_EnterArrayFromMapSZ(&DCtx, "an array of two strings"); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5600+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return 5700; |
| } |
| |
| QCBORDecode_Rewind(&DCtx); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5700+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return 5800; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string2")) { |
| return 5900; |
| } |
| |
| QCBORDecode_Rewind(&DCtx); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 5900+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || |
| Item.uDataAlloc || |
| Item.uLabelAlloc || |
| UsefulBufCompareToSZ(Item.val.string, "string1")) { |
| return 6000; |
| } |
| |
| |
| // Rewind a byte string inside an array inside an array |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidWrappedMapEncoded), 0); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| |
| uint64_t i; |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| |
| QCBORDecode_EnterBstrWrapped(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 6100; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return (int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 6200; |
| } |
| |
| QCBORDecode_Rewind(&DCtx); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 6300+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 6400; |
| } |
| |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| // Rewind a byte string inside an indefinite-length array inside |
| // indefinite-length array |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidIndefWrappedMapEncoded), 0); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| |
| QCBORDecode_EnterBstrWrapped(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL); |
| if(QCBORDecode_GetError(&DCtx)) { |
| return 6500; |
| } |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 6600+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 6700; |
| } |
| |
| QCBORDecode_Rewind(&DCtx); |
| |
| if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { |
| return 6800+(int32_t)nCBORError; |
| } |
| if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) { |
| return 6900; |
| } |
| #endif |
| |
| // Rewind an empty map |
| // [100, {}] |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWithEmptyMap), 0); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 100) { |
| return 7010; |
| } |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| /* Do it 5 times to be sure multiple rewinds work */ |
| for(int n = 0; n < 5; n++) { |
| nCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(nCBORError != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 7000 + n; |
| } |
| QCBORDecode_Rewind(&DCtx); |
| } |
| QCBORDecode_ExitMap(&DCtx); |
| QCBORDecode_Rewind(&DCtx); |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 100) { |
| return 7010; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_Rewind(&DCtx); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| i = 9; |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 100) { |
| return 7020; |
| } |
| if(QCBORDecode_GetError(&DCtx)){ |
| return 7030; |
| } |
| |
| // Rewind an empty indefinite length map |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWithEmptyMapInDef), 0); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 100) { |
| return 7810; |
| } |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| |
| /* Do it 5 times to be sure multiple rewinds work */ |
| for(int n = 0; n < 5; n++) { |
| nCBORError = QCBORDecode_GetNext(&DCtx, &Item); |
| if(nCBORError != QCBOR_ERR_NO_MORE_ITEMS) { |
| return 7800 + n; |
| } |
| QCBORDecode_Rewind(&DCtx); |
| } |
| QCBORDecode_ExitMap(&DCtx); |
| QCBORDecode_Rewind(&DCtx); |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 100) { |
| return 7810; |
| } |
| QCBORDecode_ExitArray(&DCtx); |
| QCBORDecode_Rewind(&DCtx); |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| i = 9; |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 100) { |
| return 7820; |
| } |
| if(QCBORDecode_GetError(&DCtx)){ |
| return 7830; |
| } |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ |
| |
| // Rewind an indefnite length byte-string wrapped sequence |
| #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |
| QCBORDecode_Init(&DCtx, |
| UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWrappedByIndefiniteLength), |
| 0); |
| UsefulBuf_MAKE_STACK_UB(Pool, 100); |
| QCBORDecode_SetMemPool(&DCtx, Pool, 0); |
| |
| QCBORDecode_EnterArray(&DCtx, NULL); |
| QCBORDecode_EnterBstrWrapped(&DCtx, 2, NULL); |
| if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_INPUT_TOO_LARGE) { |
| /* this is what happens when trying to enter |
| indefinite-length byte string |
| wrapped CBOR. Tolerate for now. Eventually it needs |
| to be fixed so this works, but that is not simple. */ |
| return 7300; |
| } |
| |
| /* |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 42) { |
| return 7110; |
| } |
| QCBORDecode_Rewind(&DCtx); |
| QCBORDecode_GetUInt64(&DCtx, &i); |
| if(i != 42) { |
| return 7220; |
| }*/ |
| #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ |
| |
| |
| // Rewind an indefnite length byte-string wrapped sequence |
| |
| return 0; |
| } |
| |
| |
| |
| |
| static const uint8_t spBooleansInMap[] = |
| { |
| 0xa1, 0x08, 0xf5 |
| }; |
| |
| static const uint8_t spBooleansInMapWrongType[] = |
| { |
| 0xa1, 0x08, 0xf6 |
| }; |
| |
| static const uint8_t spBooleansInMapNWF[] = |
| { |
| 0xa1, 0x08, 0x1a |
| }; |
| |
| static const uint8_t spNullInMap[] = |
| { |
| 0xa1, 0x08, 0xf6 |
| }; |
| |
| |
| |
| int32_t BoolTest(void) |
| { |
| QCBORDecodeContext DCtx; |
| bool b; |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap), 0); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetBool(&DCtx, &b); |
| if(QCBORDecode_GetAndResetError(&DCtx) || !b) { |
| return 1; |
| } |
| |
| QCBORDecode_GetBoolInMapN(&DCtx, 7, &b); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 2; |
| } |
| |
| QCBORDecode_GetBoolInMapN(&DCtx, 8, &b); |
| if(QCBORDecode_GetAndResetError(&DCtx) || !b) { |
| return 3; |
| } |
| |
| |
| QCBORDecode_GetBoolInMapSZ(&DCtx, "xx", &b); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) { |
| return 4; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMapWrongType), 0); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetBool(&DCtx, &b); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 5; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMapNWF), 0); |
| |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetBool(&DCtx, &b); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_HIT_END) { |
| return 6; |
| } |
| |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNullInMap), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNull(&DCtx); |
| if(QCBORDecode_GetAndResetError(&DCtx)) { |
| return 7; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNull(&DCtx); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 8; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNullInMap), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNullInMapN(&DCtx, 8); |
| if(QCBORDecode_GetAndResetError(&DCtx)) { |
| return 9; |
| } |
| |
| QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap), 0); |
| QCBORDecode_EnterMap(&DCtx, NULL); |
| QCBORDecode_GetNullInMapN(&DCtx, 8); |
| if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) { |
| return 10; |
| } |
| |
| return 0; |
| } |