improve map search error handling
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index efde5d1..62858de 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -302,18 +302,19 @@
        well-formed. */
    QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED = 12,
 
-   /** During decoding, an integer type is encoded with a bad length (
-       that of an indefinite length string). The CBOR is not-well
+   /** During decoding, an integer type is encoded with a bad length
+       (that of an indefinite length string). The CBOR is not-well
        formed. */
    QCBOR_ERR_BAD_INT = 13,
 
+#define QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS 14
+
    /** During decoding, one of the chunks in an indefinite-length
        string is not of the type of the start of the string.  The CBOR
        is not well-formed.  This error makes no further decoding
        possible. */
    QCBOR_ERR_INDEFINITE_STRING_CHUNK = 14,
 
-#define QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS 15
    /** During decoding, hit the end of the given data to decode. For
        example, a byte string of 100 bytes was expected, but the end
        of the input was hit before finding those 100 bytes.  Corrupted
@@ -348,40 +349,39 @@
        possible. */
    QCBOR_ERR_ARRAY_DECODE_TOO_LONG = 19,
 
-   /** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encounterd for a
-       CBOR ITEM.  @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this
-       implementation.  During decoding, too many tags in the
-       caller-configured tag list, or not enough space in @ref
-       QCBORTagListOut. This error makes no further decoding
-       possible.  */
-    // TODO: probably can remove this from unrecoverable
-   QCBOR_ERR_TOO_MANY_TAGS = 20,
-
    /** When decoding, a string's size is greater than what a size_t
        can hold less 4. In all but some very strange situations this
        is because of corrupt input CBOR and should be treated as
        such. The strange situation is a CPU with a very small size_t
        (e.g., a 16-bit CPU) and a large string (e.g., > 65KB). This
        error makes no further decoding possible. */
-   QCBOR_ERR_STRING_TOO_LONG = 21,
+   QCBOR_ERR_STRING_TOO_LONG = 20,
 
    /** Something is wrong with a decimal fraction or bigfloat such as
        it not consisting of an array with two integers. This error
        makes no further decoding possible. */
-   QCBOR_ERR_BAD_EXP_AND_MANTISSA = 22,
+   QCBOR_ERR_BAD_EXP_AND_MANTISSA = 21,
 
    /** Unable to decode an indefinite-length string because no string
        allocator was configured. See QCBORDecode_SetMemPool() or
        QCBORDecode_SetUpAllocator().  This error makes no further
        decoding possible.*/
-   QCBOR_ERR_NO_STRING_ALLOCATOR = 23,
+   QCBOR_ERR_NO_STRING_ALLOCATOR = 22,
 
    /** Error allocating space for a string, usually for an
        indefinite-length string. This error makes no further decoding
        possible. */
-   QCBOR_ERR_STRING_ALLOCATE = 24,
+   QCBOR_ERR_STRING_ALLOCATE = 23,
 
-#define QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS 24
+#define QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS 23
+
+   /** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encounterd for a
+       CBOR ITEM.  @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this
+       implementation.  During decoding, too many tags in the
+       caller-configured tag list, or not enough space in @ref
+       QCBORTagListOut. This error makes no further decoding
+       possible.  */
+   QCBOR_ERR_TOO_MANY_TAGS = 24,
 
    /** During decoding, the type of the label for a map entry is not
        one that can be handled in the current decoding mode. Typically
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 5c2e3f5..b88657c 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -300,7 +300,7 @@
 /**
  The main data structure that holds the type, value and other info for
  a decoded item returned by QCBORDecode_GetNext() and
- QCBORDecode_GetNextWithTags().
+ and methods.
 
  This size of this may vary by compiler but is roughly 56 bytes on
  a 64-bit CPU and 52 bytes on a 32-bit CPU.
@@ -1115,6 +1115,8 @@
  incorrect lengths or array counts are unrecoverable. Unrecoverable
  errors also occur when certain implementation limits such as the
  limit on array and map nesting occur.
+
+ The specific errors are a range of the errors in @ref QCBORError.
  */
 static bool QCBORDecode_IsUnrecoverableError(QCBORError uErr);
 
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index ae66a3b..4145f8a 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -112,11 +112,16 @@
  type. Then for use one of the type-specific methods to get the item
  again to take advantage of the type conversion provided.
 
- Error reporting when get items by label in a map is not accurate for
- some errors. They are reported as not found rather than overflow and
- such. The error may be for other than the labeled item being searched
- for. Non-well formed maps cannot be searched at all. (This may be
- improved).
+ When getting an item by label from a map the whole map is
+ traversed including traversal of nested arrays and maps. If
+ there is any unrecoverable error anywhere in the that traversal
+ the retrieval by label will fail and the unrecoverable error
+ will be returned even if it is not due to the labeled item
+ being sought. Recoverable errors will be ignored unless
+ they are on the item being sought, in which case the
+ unrecoverable error will be returned. Unrecoverable
+ errors are those indicated by QCBORDecode_IsUnrecoverableError().
+ 
 
  @anchor Tag-Usage
 
@@ -1707,7 +1712,8 @@
    QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
                                              nLabel,
                                              uConvertTypes,
-                                             pnValue, &Item);
+                                             pnValue,
+                                             &Item);
 }
 
 inline static void
@@ -1720,7 +1726,8 @@
    QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
                                               szLabel,
                                               uConvertTypes,
-                                              pnValue, &Item);
+                                              pnValue,
+                                              &Item);
 }
 
 inline static void
@@ -1731,8 +1738,8 @@
 
 inline static void
 QCBORDecode_GetInt64InMapN(QCBORDecodeContext *pMe,
-                           int64_t nLabel,
-                           int64_t *pnValue)
+                           int64_t             nLabel,
+                           int64_t            *pnValue)
 {
    QCBORDecode_GetInt64ConvertInMapN(pMe,
                                      nLabel,
@@ -1742,8 +1749,8 @@
 
 inline static void
 QCBORDecode_GetInt64InMapSZ(QCBORDecodeContext *pMe,
-                            const char *szLabel,
-                            int64_t *pnValue)
+                            const char         *szLabel,
+                            int64_t            *pnValue)
 {
    QCBORDecode_GetInt64ConvertInMapSZ(pMe,
                                       szLabel,
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index a34c1d0..4cc0113 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -1300,8 +1300,9 @@
          // be the real data
          QCBORItem LabelItem = *pDecodedItem;
          nReturn = GetNext_TaggedItem(me, pDecodedItem);
-         if(nReturn)
+         if(QCBORDecode_IsUnrecoverableError(nReturn)) {
             goto Done;
+         }
 
          pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
 
@@ -1603,12 +1604,6 @@
    }
 
 Done:
-   if(uReturn != QCBOR_SUCCESS) {
-      /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
-      pDecodedItem->uDataType = QCBOR_TYPE_NONE;
-      pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
-      // memset(pDecodedItem, 0, sizeof(QCBORItem));
-   }
    return uReturn;
 }
 
@@ -1934,8 +1929,8 @@
 /*
  Public function, see header qcbor/qcbor_decode.h file
  */
-QCBORError
-QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static QCBORError
+QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
    QCBORError nReturn;
 
@@ -2029,11 +2024,20 @@
    }
 
 Done:
-   if(nReturn != QCBOR_SUCCESS) {
+   return nReturn;
+}
+
+
+QCBORError
+QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   QCBORError uErr;
+   uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
+   if(uErr != QCBOR_SUCCESS) {
       pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
       pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
    }
-   return nReturn;
+   return uErr;
 }
 
 
@@ -2538,7 +2542,7 @@
  for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
  not every item in the map.
 
- @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
+ @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was wrong for the matchd label.
 
  @retval Also errors returned by QCBORDecode_GetNext().
 
@@ -2597,10 +2601,21 @@
                        DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
 
    /*
-    Loop over all the items in the map. They could be
-    deeply nested and this should handle both definite
-    and indefinite length maps and arrays, so this
-    adds some complexity.
+    Loop over all the items in the map or array. Each item
+    could be a map or array, but label matching is only at
+    the main level. This handles definite and indefinite
+    length maps and arrays. The only reason this is ever
+    called on arrays is to find their end position.
+
+    This will always run over all items in order to do
+    duplicate detection.
+
+    This will exit with failure if it encounters an
+    unrecoverable error, but continue on for recoverable
+    errors.
+
+    If a recoverable error occurs on a matched item, then
+    that error code is returned.
     */
    const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
    uint_fast8_t  uNextNestLevel;
@@ -2610,21 +2625,21 @@
 
       /* Get the item */
       QCBORItem Item;
-      uReturn = QCBORDecode_GetNext(pMe, &Item);
-      if(QCBORDecode_IsUnrecoverableError(uReturn)) {
+      QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
+      if(QCBORDecode_IsUnrecoverableError(uResult)) {
          /* Got non-well-formed CBOR so map can't even be decoded. */
+         uReturn = uResult;
          goto Done;
       }
-      if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
+      if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
          // Unexpected end of map or array.
+         uReturn = uResult;
          goto Done;
       }
 
       /* See if item has one of the labels that are of interest */
       bool bMatched = false;
       for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
-         // TODO: have label filled in on invalid CBOR so error reporting
-         // can work a lot better.
          if(MatchLabel(Item, pItemArray[nIndex])) {
             /* A label match has been found */
             if(uFoundItemBitMap & (0x01ULL << nIndex)) {
@@ -2637,6 +2652,11 @@
                goto Done;
             }
 
+            if(uResult != QCBOR_SUCCESS) {
+               uReturn = uResult;
+               goto Done;
+            }
+
             /* Successful match. Return the item. */
             pItemArray[nIndex] = Item;
             uFoundItemBitMap |= 0x01ULL << nIndex;
@@ -2679,8 +2699,8 @@
 
    const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
 
-   // Check here makes that this won't accidentally be
-   // QCBOR_MAP_OFFSET_CACHE_INVALID. It is larger than
+   // Check here makes sure that this won't accidentally be
+   // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
    // QCBOR_MAX_DECODE_INPUT_SIZE.
    if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
       uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
@@ -2693,10 +2713,11 @@
    DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
 
  Done2:
-   /* For all items not found, set the data type to QCBOR_TYPE_NONE */
+   /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
    for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
       if(!(uFoundItemBitMap & (0x01ULL << i))) {
-         pItemArray[i].uDataType = QCBOR_TYPE_NONE;
+         pItemArray[i].uDataType  = QCBOR_TYPE_NONE;
+         pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
       }
    }
 
@@ -2723,16 +2744,16 @@
    OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE; // Indicates end of array
 
    QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
+
+   *pItem = OneItemSeach[0];
+
    if(uReturn != QCBOR_SUCCESS) {
       goto Done;
    }
    if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
       uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
-      goto Done;
    }
 
-   *pItem = OneItemSeach[0];
-
  Done:
    pMe->uLastError = (uint8_t)uReturn;
 }
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 2780097..71bde05 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -2481,7 +2481,7 @@
    }
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
    uError = QCBORDecode_GetAndResetError(&DC);
-   if(uError != QCBOR_ERR_LABEL_NOT_FOUND) {
+   if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
       return 102;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -2495,7 +2495,7 @@
    }
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
    uError = QCBORDecode_GetAndResetError(&DC);
-   if(uError != QCBOR_ERR_LABEL_NOT_FOUND) {
+   if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
       return 112;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -4778,12 +4778,62 @@
  }
  */
 
-
 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};
 
+/*
+ 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[] = {
+   0xbf,
+   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,
+   0xff
+};
+
+// Bad break
+static const uint8_t spUnRecoverableMapError1[] = {
+   0xa2, 0xff, 0x01, 0x00, 0x02, 0x00
+};
+
+// 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
+};
+
+
 int32_t EnterMapTest()
 {
    QCBORItem          Item1;
@@ -4964,12 +5014,88 @@
    QCBORDecode_GetInt64(&DCtx, &nDecodedInt2);
    QCBORDecode_ExitArray(&DCtx);
    uErr = QCBORDecode_Finish(&DCtx);
-   if(uErr != QCBOR_SUCCESS){
+   if(uErr != QCBOR_SUCCESS) {
       return 2014;
    }
 
-   // TODO: more testing of entered mapps and arrays with problems
-   // TODO: document error handling better (maybe improve error handling)
+   int64_t nInt;
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spRecoverableMapErrors), 0);
+   QCBORDecode_EnterMap(&DCtx);
+   QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt);
+   uErr = QCBORDecode_GetAndResetError(&DCtx);
+   if(uErr != QCBOR_ERR_TOO_MANY_TAGS) {
+      return 2021;
+   }
+
+   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
+
+   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);
+   QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt);
+   uErr = QCBORDecode_GetAndResetError(&DCtx);
+   if(uErr != QCBOR_ERR_BAD_BREAK) {
+      return 2030;
+   }
+
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUnRecoverableMapError2), 0);
+   QCBORDecode_EnterMap(&DCtx);
+   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);
+   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);
+   QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt);
+   uErr = QCBORDecode_GetAndResetError(&DCtx);
+   if(uErr != QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP) {
+      return 2033;
+   }
 
    return 0;
 }