Bug fixes for spiffy decode corner cases (#57)
* Bug fix for decoding empty maps and arrays with spiffy decode
* Bug fix for entering and exiting the same map multiple times
* Add a lot of tests for spiffy decoding of nested maps and arrays
Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 70fd3b1..6ee22fd 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -4647,7 +4647,7 @@
"another int": 98,
"text 2": "lies, damn lies and statistics"
}
- }
+ }
*/
int32_t SpiffyDecodeBasicMap(UsefulBufC input)
@@ -4743,6 +4743,174 @@
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()
+{
+ 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,
@@ -5125,7 +5293,9 @@
return 2033;
}
- return 0;
+ nReturn = DecodeNestedIterate();
+
+ return nReturn;
}