Fix bug decoding empty arrays and maps (#16)


diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 9599b07..c35a29d 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -42,6 +42,7 @@
 
  when               who             what, where, why
  --------           ----            ---------------------------------------------------
+ 09/07/19           llundblade      Fix bug decoding empty arrays and maps
  07/31/19           llundblade      Decode error fixes for some not-well-formed CBOR
  07/31/19           llundblade      New error code for better end of data handling
  02/17/19           llundblade      Fixed: QCBORItem.u{Data|Label}Alloc when bAllStrings set
@@ -129,28 +130,27 @@
 // Called on every single item except breaks including the opening of a map/array
 inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
 {
-   if(!DecodeNesting_IsNested(pNesting)) {
-      // at top level where there is no tracking
-      return;
-   }
+   while(DecodeNesting_IsNested(pNesting)) {
+      // Not at the top level, so there is decrementing to be done.
 
-   if(DecodeNesting_IsIndefiniteLength(pNesting)) {
-      // There is no count for indefinite length arrays/maps
-      return;
-   }
-
-   // Decrement the count of items in this array/map
-   pNesting->pCurrent->uCount--;
-
-   // Pop up nesting levels if the counts at the levels are zero
-   while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) {
-      pNesting->pCurrent--;
       if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
+         // Decrement the current nesting level if it is not indefinite.
          pNesting->pCurrent->uCount--;
       }
+
+      if(pNesting->pCurrent->uCount != 0) {
+         // Did not close out an array or map, so nothing further
+         break;
+      }
+
+      // Closed out an array or map so level up
+      pNesting->pCurrent--;
+
+      // Continue with loop to see if closing out this doesn't close out more
    }
 }
 
+
 // Called on every map/array
 inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
 {
@@ -1098,7 +1098,10 @@
       // Maps and arrays do count in as items in the map/array that encloses
       // them so a decrement needs to be done for them too, but that is done
       // only when all the items in them have been processed, not when they
-      // are opened.
+      // are opened with the exception of an empty map or array.
+       if(pDecodedItem->val.uCount == 0) {
+           DecodeNesting_DecrementCount(&(me->nesting));
+       }
    } else {
       // Decrement the count of items in the enclosing map/array
       // If the count in the enclosing map/array goes to zero, that
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 8a79bd8..3c17d0a 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -593,6 +593,149 @@
 }
 
 
+/*
+ [
+    0,
+    [],
+    [
+       [],
+       [
+          0
+       ],
+       {},
+       {
+          1: {},
+          2: {},
+          3: []
+       }
+    ]
+ ]
+ */
+static uint8_t sEmpties[] = {0x83, 0x00, 0x80, 0x84, 0x80, 0x81, 0x00, 0xa0,
+                             0xa3, 0x01, 0xa0, 0x02, 0xa0, 0x03, 0x80};
+
+int EmptyMapsAndArraysTest()
+{
+   QCBORDecodeContext DCtx;
+   QCBORItem Item;
+
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmpties), QCBOR_DECODE_MODE_NORMAL);
+
+   // Array with 3 items
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.uNestingLevel != 0 ||
+      Item.uNextNestLevel != 1 ||
+      Item.val.uCount != 3) {
+      return -1;
+   }
+
+   // An integer 0
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_INT64 ||
+      Item.uNestingLevel != 1 ||
+      Item.uNextNestLevel != 1 ||
+      Item.val.uint64 != 0) {
+      return -2;
+   }
+
+   // An empty array
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.uNestingLevel != 1 ||
+      Item.uNextNestLevel != 1 ||
+      Item.val.uCount != 0) {
+      return -3;
+   }
+
+   // An array with 4 items
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.uNestingLevel != 1 ||
+      Item.uNextNestLevel != 2 ||
+      Item.val.uCount != 4) {
+      return -4;
+   }
+
+   // An empty array
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.uNestingLevel != 2 ||
+      Item.uNextNestLevel != 2 ||
+      Item.val.uCount != 0) {
+      return -5;
+   }
+
+   // An array with 1 item
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.uNestingLevel != 2 ||
+      Item.uNextNestLevel != 3 ||
+      Item.val.uCount != 1) {
+      return -6;
+   }
+
+   // An integer 0
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_INT64 ||
+      Item.uNestingLevel != 3 ||
+      Item.uNextNestLevel != 2 ||
+      Item.val.uint64 != 0) {
+      return -7;
+   }
+
+   // An empty map
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_MAP ||
+      Item.uNestingLevel != 2 ||
+      Item.uNextNestLevel != 2 ||
+      Item.val.uCount != 0) {
+      return -8;
+   }
+
+   // An map with 3 items
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_MAP ||
+      Item.uNestingLevel != 2 ||
+      Item.uNextNestLevel != 3 ||
+      Item.val.uCount != 3) {
+      return -9;
+   }
+
+   // An empty map
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_MAP ||
+      Item.uNestingLevel != 3 ||
+      Item.uNextNestLevel != 3 ||
+      Item.val.uCount != 0) {
+      return -10;
+   }
+
+   // An empty map
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_MAP ||
+      Item.uNestingLevel != 3 ||
+      Item.uNextNestLevel != 3 ||
+      Item.val.uCount != 0) {
+      return -11;
+   }
+
+   // An empty array
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0 ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.uNestingLevel != 3 ||
+      Item.uNextNestLevel != 0 ||
+      Item.val.uCount != 0) {
+      return -12;
+   }
+
+   if(QCBORDecode_Finish(&DCtx) != QCBOR_SUCCESS) {
+      return -13;
+   }
+
+   return 0;
+}
+
 
 static uint8_t spDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
 
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 6159c8b..dfac338 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -67,6 +67,11 @@
  */
 int SimpleArrayTest(void);
 
+/*
+ Tests with empty maps and arrays
+ */
+int EmptyMapsAndArraysTest(void);
+
 
 /*
  Make sure a maximally deep array can be parsed and that the
diff --git a/test/run_tests.c b/test/run_tests.c
index 374b40e..becd545 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -100,6 +100,7 @@
 
 
 test_entry s_tests[] = {
+    TEST_ENTRY(EmptyMapsAndArraysTest),
     TEST_ENTRY(NotWellFormedTests),
     TEST_ENTRY(ParseMapAsArrayTest),
     TEST_ENTRY(AllocAllStringsTest),