Add getting un decoded arrays and maps (#117)
This adds QCBORDecode_GetArray() and QCBORDecode_GetMap() plus friends. They return undecoded arrays and maps so they can be passed on to other decoder instances or such.
This also adds UsefulBuf_OffsetToPointer() and UsefulInputBuf_PointerToOffset() to UsefulBuf.
Consume no longer validates standard tags like big floats when it is consuming stuff. It still checks for CBOR that is not well formed.
There was some internal restructuring of array and map processing, but the tests are thorough and they are all passing.
This is to address #112
* getting started on returning arrays
* progress...
* returning maps and arrays mostly working
* Checkpoint progress
* Checkpoint: mostly working
* checkpoint -- it is working
* OffsetToPtr documentation and test
* test and documentation
* Fix Get() of nested indef arrays and maps
* Test tags; doc fixes
* Fix #ifdef test fan out
* Last bit of documentation update
---------
Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 7fedf91..1a83452 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -5945,9 +5945,6 @@
00
};
-const unsigned char spBadConsumeInput3[] = {
- 0x81, 0xc0, 0x81, 0x00
-};
const unsigned char spBadConsumeInput4[] = {
0x81, 0x9f, 0x00, 0xff
@@ -6003,6 +6000,9 @@
QCBORDecode_EnterMap(&DCtx, NULL);
QCBORDecode_GetInt64InMapN (&DCtx, 3, &nInt);
uErr = QCBORDecode_GetNext(&DCtx, &Item1);
+ if(uErr != QCBOR_SUCCESS) {
+ return 701;
+ }
if(Item1.uDataType != QCBOR_TYPE_INT64) {
return 700;
}
@@ -6424,12 +6424,6 @@
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 2700;
}
-
- QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBadConsumeInput3), 0);
- QCBORDecode_VGetNextConsume(&DCtx, &Item1);
- if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT) {
- return 2800;
- }
#endif
@@ -8841,6 +8835,333 @@
}
+
+static const uint8_t spExpectedArray2s[] = {
+ 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x31, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x32};
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+static const uint8_t spExpectedArray2sIndef[] = {
+ 0x9f, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x31, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x32, 0xff};
+#endif
+
+static const uint8_t spExpectedMap4[] = {
+ 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
+
+static const uint8_t spExpectedMap4Indef[] = {
+ 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};
+
+/*
+ * [[[[[0, []]]]], 0]
+ */
+static const uint8_t spDefAndIndef[] = {
+ 0x82,
+ 0x9f, 0x9f, 0x9f, 0x82, 0x00, 0x9f, 0xff, 0xff, 0xff, 0xff, 0x00
+};
+#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+
+#ifndef QCBOR_DISABLE_TAGS
+/* An exp / mant tag in two nested arrays */
+static const uint8_t spExpMant[] = {0x81, 0x81, 0xC4, 0x82, 0x20, 0x03};
+#endif /* !QCBOR_DISABLE_TAGS */
+
+
+int32_t GetMapAndArrayTest(void)
+{
+ QCBORDecodeContext DCtx;
+ size_t uPosition ;
+ QCBORItem Item;
+ UsefulBufC ReturnedEncodedCBOR;
+
+
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
+ 0);
+
+ QCBORDecode_EnterMap(&DCtx, NULL);
+ QCBORDecode_VGetNextConsume(&DCtx, &Item);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 1;
+ }
+ if(Item.val.uCount != 2) {
+ return 2;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedArray2s))) {
+ return 3;
+ }
+
+ if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+ UsefulBuf_Compare(Item.label.string, UsefulBuf_FROM_SZ_LITERAL("an array of two strings"))) {
+ return 4;
+ }
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+
+
+ QCBORDecode_GetMap(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 10;
+ }
+ if(Item.val.uCount != 4) {
+ return 11;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedMap4))) {
+ return 12;
+ }
+ uPosition = QCBORDecode_Tell(&DCtx);
+ QCBORDecode_GetArrayFromMapSZ(&DCtx,
+ "an array of two strings",
+ &Item,
+ &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 20;
+ }
+ if(Item.val.uCount != 2) {
+ return 21;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedArray2s))) {
+ return 22;
+ }
+ if(uPosition != QCBORDecode_Tell(&DCtx)) {
+ return 23;
+ }
+
+ QCBORDecode_Rewind(&DCtx);
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+ QCBORDecode_GetMapFromMapSZ(&DCtx, "map in a map", &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 30;
+ }
+ if(Item.val.uCount != 4) {
+ return 31;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedMap4))) {
+ return 32;
+ }
+ if(uPosition != QCBORDecode_Tell(&DCtx)) {
+ return 33;
+ }
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+ QCBORDecode_GetArrayFromMapSZ(&DCtx, "map in a map", &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+ return 40;
+ }
+ if(UINT32_MAX != QCBORDecode_Tell(&DCtx)) {
+ return 41;
+ }
+ QCBORDecode_GetAndResetError(&DCtx);
+ if(uPosition != QCBORDecode_Tell(&DCtx)) {
+ return 42;
+ }
+
+
+#ifndef QCBOR_DISABLE_TAGS
+ UsefulBufC ExpMant = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpMant);
+ QCBORDecode_Init(&DCtx, ExpMant, 0);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 200;
+ }
+ if(Item.uDataType != QCBOR_TYPE_ARRAY) {
+ return 201;
+ }
+ if(!QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DECIMAL_FRACTION)) {
+ return 202;
+ }
+ if(Item.val.uCount != 2) {
+ return 201;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_Tail(ExpMant, 2))) {
+ return 205;
+ }
+#endif /* !QCBOR_DISABLE_TAGS */
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+
+ UsefulBufC DefAndIndef = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDefAndIndef);
+ QCBORDecode_Init(&DCtx, DefAndIndef, 0);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 50;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_Tail(UsefulBuf_Head(DefAndIndef, 11), 1))) {
+ return 51;
+ }
+
+ QCBORDecode_Init(&DCtx, DefAndIndef, 0);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 52;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_Tail(UsefulBuf_Head(DefAndIndef, 10), 2))) {
+ return 53;
+ }
+
+ QCBORDecode_Init(&DCtx, DefAndIndef, 0);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 54;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_Tail(UsefulBuf_Head(DefAndIndef, 9), 3))) {
+ return 55;
+ }
+ QCBORDecode_Init(&DCtx, DefAndIndef, 0);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 56;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_Tail(UsefulBuf_Head(DefAndIndef, 8), 4))) {
+ return 57;
+ }
+
+ QCBORDecode_Init(&DCtx, DefAndIndef, 0);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_EnterArray(&DCtx, NULL);
+ QCBORDecode_VGetNextConsume(&DCtx, &Item);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 58;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_Tail(UsefulBuf_Head(DefAndIndef, 8), 6))) {
+ return 59;
+ }
+
+
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapIndefEncoded),
+ 0);
+
+ QCBORDecode_EnterMap(&DCtx, NULL);
+ QCBORDecode_VGetNextConsume(&DCtx, &Item);
+ QCBORDecode_GetArray(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 60;
+ }
+ if(Item.val.uCount != UINT16_MAX) {
+ return 61;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedArray2sIndef))) {
+ return 62;
+ }
+
+ if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+ UsefulBuf_Compare(Item.label.string, UsefulBuf_FROM_SZ_LITERAL("an array of two strings"))) {
+ return 63;
+ }
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+
+
+ QCBORDecode_GetMap(&DCtx, &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 70;
+ }
+ if(Item.val.uCount != UINT16_MAX) {
+ return 71;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedMap4Indef))) {
+ return 72;
+ }
+
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+ QCBORDecode_GetArrayFromMapSZ(&DCtx,
+ "an array of two strings",
+ &Item,
+ &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 80;
+ }
+ if(Item.val.uCount != UINT16_MAX) {
+ return 81;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedArray2sIndef))) {
+ return 82;
+ }
+ if(uPosition != QCBORDecode_Tell(&DCtx)) {
+ return 83;
+ }
+
+ QCBORDecode_Rewind(&DCtx);
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+ QCBORDecode_GetMapFromMapSZ(&DCtx, "map in a map", &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx)) {
+ return 90;
+ }
+ if(Item.val.uCount != UINT16_MAX) {
+ return 91;
+ }
+ if(UsefulBuf_Compare(ReturnedEncodedCBOR, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedMap4Indef))) {
+ return 92;
+ }
+ if(uPosition != QCBORDecode_Tell(&DCtx)) {
+ return 93;
+ }
+
+ uPosition = QCBORDecode_Tell(&DCtx);
+ QCBORDecode_GetArrayFromMapSZ(&DCtx, "map in a map", &Item, &ReturnedEncodedCBOR);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+ return 100;
+ }
+ if(UINT32_MAX != QCBORDecode_Tell(&DCtx)) {
+ return 101;
+ }
+ QCBORDecode_GetAndResetError(&DCtx);
+ if(uPosition != QCBORDecode_Tell(&DCtx)) {
+ return 102;
+ }
+#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+ return 0;
+}
+
+
int32_t
ErrorHandlingTests(void)
{