#ifdef to reduce code size by disabling some encode error checks (#55)

* First encode guards removal

* document disabling of encode guards

* remove one more error check; neater code for count increment

* remove extraneous comment

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/README.md b/README.md
index 1a01b42..906bf41 100644
--- a/README.md
+++ b/README.md
@@ -230,9 +230,9 @@
 
     |               | smallest | largest |  
     |---------------|----------|---------|
-    | encode only   |      900 |    2100 |
-    | decode only   |     2800 |   13500 |
-    | combined      |     3700 |   15600 |
+    | encode only   |      850 |    2100 |
+    | decode only   |     2900 |   13500 |
+    | combined      |     3750 |   15600 |
     
  From the table above, one can see that the amount of code pulled in
  from the QCBOR library varies a lot, ranging from 1KB to 15KB.  The
@@ -271,11 +271,10 @@
  carefully written to be defensive.
 
  Disable features with defines like
- QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA (saves about 400 bytes) and
+ QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA (saves about 400 bytes) 
+ QCBOR_DISABLE_ENCODE_USAGE_GUARDS (saves about 150), and
  QCBOR_DISABLE_PREFERRED_FLOAT (saves about 900 bytes).  More of these
- defines are planned than are currently implemented (they are a little
- complex to implement because all the combination configurations must
- be tested).
+ defines are planned than are currently implemented.
  
  If QCBOR is installed as a shared library, then of course only one
  copy of the code is in memory no matter how many applications use it.
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index ae5027a..54a3635 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -229,6 +229,19 @@
  [RFC 8742] (https://tools.ietf.org/html/rfc8742). This encoder supports
  either just by whether the first item added is an array, map or other.
 
+ If QCBOR is compiled with QCBOR_DISABLE_ENCODE_USAGE_GUARDS defined,
+ the errors QCBOR_ERR_CLOSE_MISMATCH, QCBOR_ERR_ARRAY_TOO_LONG,
+ QCBOR_ERR_TOO_MANY_CLOSES, QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN, and
+ QCBOR_ERR_ENCODE_UNSUPPORTED will never be returned. It is up to the
+ caller to make sure that opened maps, arrays and byte-string wrapping
+ is closed correctly and that QCBOREncode_AddType7() is called
+ correctly.  With this defined, it is easier to make a mistake when
+ authoring the encoding of a protocol that will output not well formed
+ CBOR, but as long as the calling code is correct, it is safe to
+ disable these checks. Bounds checking that prevents security issues
+ in the code is still enforced. This define reduces the size of
+ encoding object code by about 150 bytes.
+
  @anchor Tags-Overview
 
  ## Tags Overview
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 992fa87..623b8d5 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -95,9 +95,11 @@
 
 inline static uint8_t Nesting_Increment(QCBORTrackNesting *pNesting)
 {
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
       return QCBOR_ERR_ARRAY_TOO_LONG;
    }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    pNesting->pCurrentNesting->uCount++;
 
@@ -127,6 +129,7 @@
    return pNesting->pCurrentNesting->uStart;
 }
 
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
 inline static uint8_t Nesting_GetMajorType(QCBORTrackNesting *pNesting)
 {
    return pNesting->pCurrentNesting->uMajorType;
@@ -136,6 +139,7 @@
 {
    return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
 }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
 
 
@@ -160,34 +164,34 @@
 
 /*
  Error tracking plan -- Errors are tracked internally and not returned
- until QCBOREncode_Finish is called. The CBOR errors are in me->uError.
- UsefulOutBuf also tracks whether the buffer is full or not in its
- context.  Once either of these errors is set they are never
- cleared. Only QCBOREncode_Init() resets them. Or said another way, they must
- never be cleared or we'll tell the caller all is good when it is not.
+ until QCBOREncode_Finish() or QCBOREncode_GetErrorState() is
+ called. The CBOR errors are in me->uError.  UsefulOutBuf also tracks
+ whether the buffer is full or not in its context.  Once either of
+ these errors is set they are never cleared. Only QCBOREncode_Init()
+ resets them. Or said another way, they must never be cleared or we'll
+ tell the caller all is good when it is not.
 
- Only one error code is reported by QCBOREncode_Finish() even if there are
- multiple errors. The last one set wins. The caller might have to fix
- one error to reveal the next one they have to fix.  This is OK.
+ Only one error code is reported by QCBOREncode_Finish() even if there
+ are multiple errors. The last one set wins. The caller might have to
+ fix one error to reveal the next one they have to fix.  This is OK.
 
  The buffer full error tracked by UsefulBuf is only pulled out of
- UsefulBuf in Finish() so it is the one that usually wins.  UsefulBuf
- will never go off the end of the buffer even if it is called again
- and again when full.
+ UsefulBuf in QCBOREncode_Finish() so it is the one that usually wins.
+ UsefulBuf will never go off the end of the buffer even if it is
+ called again and again when full.
 
- It is really tempting to not check for overflow on the count in the
- number of items in an array. It would save a lot of code, it is
- extremely unlikely that any one will every put 65,000 items in an
- array, and the only bad thing that would happen is the CBOR would be
- bogus.
+ QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
+ checks here to reduce code size by about 150 bytes leaving only the
+ checks for size to avoid buffer overflow. If the calling code is
+ completely correct, checks are completely unnecessary.  For example,
+ there is no need to check that all the opens are matched by a close.
 
- Since this does not parse any input, you could in theory remove all
- error checks in this code if you knew the caller called it
- correctly. Maybe someday CDDL or some such language will be able to
- generate the code to call this and the calling code would always be
- correct. This could also automatically size some of the data
- structures like array/map nesting resulting in some stack memory
- savings.
+ QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
+ than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
+ QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
+ to be reached. If it is reached, the count will wrap around to zero
+ and CBOR that is not well formed will be produced, but there will be
+ no buffers overrun and new security issues in the code.
 
  The 8 errors returned here fall into three categories:
 
@@ -195,15 +199,17 @@
    QCBOR_ERR_BUFFER_TOO_LARGE        -- Encoded output exceeded UINT32_MAX
    QCBOR_ERR_BUFFER_TOO_SMALL        -- Output buffer too small
    QCBOR_ERR_ARRAY_NESTING_TOO_DEEP  -- Nesting > QCBOR_MAX_ARRAY_NESTING1
-   QCBOR_ERR_ARRAY_TOO_LONG          -- Too many things added to an array/map
+   QCBOR_ERR_ARRAY_TOO_LONG          -- Too many items added to an array/map [1]
 
  Nesting constructed incorrectly
-   QCBOR_ERR_TOO_MANY_CLOSES         -- More close calls than opens
-   QCBOR_ERR_CLOSE_MISMATCH          -- Type of close does not match open
-   QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes
+   QCBOR_ERR_TOO_MANY_CLOSES         -- More close calls than opens [1]
+   QCBOR_ERR_CLOSE_MISMATCH          -- Type of close does not match open [1]
+   QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
 
  Would generate not-well-formed CBOR
-   QCBOR_ERR_ENCODE_UNSUPPORTED      -- Simple type between 24 and 31
+   QCBOR_ERR_ENCODE_UNSUPPORTED      -- Simple type between 24 and 31 [1]
+
+ [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
  */
 
 
@@ -440,31 +446,54 @@
  */
 static void InsertCBORHead(QCBOREncodeContext *me, uint8_t uMajorType, size_t uLen)
 {
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(me->uError == QCBOR_SUCCESS) {
       if(!Nesting_IsInNest(&(me->nesting))) {
          me->uError = QCBOR_ERR_TOO_MANY_CLOSES;
+         return;
       } else if(Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
          me->uError = QCBOR_ERR_CLOSE_MISMATCH;
-      } else {
-         // A stack buffer large enough for a CBOR head
-         UsefulBuf_MAKE_STACK_UB (pBufferForEncodedHead,QCBOR_HEAD_BUFFER_SIZE);
-
-         UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
-                                                         uMajorType,
-                                                         0,
-                                                         uLen);
-
-         /* No check for EncodedHead == NULLUsefulBufC is performed here to
-          * save object code. It is very clear that pBufferForEncodedHead
-          * is the correct size. If EncodedHead == NULLUsefulBufC then
-          * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is
-          * no security whole introduced.
-          */
-         UsefulOutBuf_InsertUsefulBuf(&(me->OutBuf), EncodedHead, Nesting_GetStartPos(&(me->nesting)) );
-
-         Nesting_Decrease(&(me->nesting));
+         return;
       }
    }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   // A stack buffer large enough for a CBOR head
+   UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
+
+   UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
+                                                   uMajorType,
+                                                   0,
+                                                   uLen);
+
+   /* No check for EncodedHead == NULLUsefulBufC is performed here to
+    * save object code. It is very clear that pBufferForEncodedHead
+    * is the correct size. If EncodedHead == NULLUsefulBufC then
+    * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is
+    * no security whole introduced.
+    */
+   UsefulOutBuf_InsertUsefulBuf(&(me->OutBuf),
+                                EncodedHead,
+                                Nesting_GetStartPos(&(me->nesting)));
+
+   Nesting_Decrease(&(me->nesting));
+}
+
+
+/*
+ Increment the count of items in a map or array. This is mostly
+ a separate function to have fewer occurance of
+ #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+ */
+static inline void IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uError == QCBOR_SUCCESS) {
+      pMe->uError = Nesting_Increment(&(pMe->nesting));
+   }
+#else
+   (void)Nesting_Increment(&(pMe->nesting));
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 }
 
 
@@ -473,10 +502,9 @@
  */
 void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue)
 {
-   if(me->uError == QCBOR_SUCCESS) {
-      AppendCBORHead(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue, 0);
-      me->uError = Nesting_Increment(&(me->nesting));
-   }
+   AppendCBORHead(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue, 0);
+
+   IncrementMapOrArrayCount(me);
 }
 
 
@@ -485,22 +513,20 @@
  */
 void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum)
 {
-   if(me->uError == QCBOR_SUCCESS) {
-      uint8_t      uMajorType;
-      uint64_t     uValue;
+   uint8_t      uMajorType;
+   uint64_t     uValue;
 
-      if(nNum < 0) {
-         // In CBOR -1 encodes as 0x00 with major type negative int.
-         uValue = (uint64_t)(-nNum - 1);
-         uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
-      } else {
-         uValue = (uint64_t)nNum;
-         uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
-      }
-      AppendCBORHead(me, uMajorType, uValue, 0);
-
-      me->uError = Nesting_Increment(&(me->nesting));
+   if(nNum < 0) {
+      // In CBOR -1 encodes as 0x00 with major type negative int.
+      uValue = (uint64_t)(-nNum - 1);
+      uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
+   } else {
+      uValue = (uint64_t)nNum;
+      uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
    }
+   AppendCBORHead(me, uMajorType, uValue, 0);
+
+   IncrementMapOrArrayCount(me);
 }
 
 
@@ -526,24 +552,21 @@
  */
 void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes)
 {
-   if(me->uError == QCBOR_SUCCESS) {
-      // If it is not Raw CBOR, add the type and the length
-      if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
-         uint8_t uRealMajorType = uMajorType;
-         if(uRealMajorType == CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
-            uRealMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
-         }
-         AppendCBORHead(me, uRealMajorType, Bytes.len, 0);
+   // If it is not Raw CBOR, add the type and the length
+   if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
+      uint8_t uRealMajorType = uMajorType;
+      if(uRealMajorType == CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
+         uRealMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
       }
-
-      if(uMajorType != CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
-         // Actually add the bytes
-         UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
-      }
-
-      // Update the array counting if there is any nesting at all
-      me->uError = Nesting_Increment(&(me->nesting));
+      AppendCBORHead(me, uRealMajorType, Bytes.len, 0);
    }
+
+   if(uMajorType != CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
+      // Actually add the bytes
+      UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
+   }
+
+   IncrementMapOrArrayCount(me);
 }
 
 
@@ -564,15 +587,19 @@
  */
 void QCBOREncode_AddType7(QCBOREncodeContext *me, uint8_t uMinLen, uint64_t uNum)
 {
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(me->uError == QCBOR_SUCCESS) {
       if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
          me->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
-      } else {
-         // AppendHead() does endian swapping for the float / double
-         AppendCBORHead(me, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
-         me->uError = Nesting_Increment(&(me->nesting));
+         return;
       }
    }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   // AppendHead() does endian swapping for the float / double
+   AppendCBORHead(me, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
+   
+   IncrementMapOrArrayCount(me);
 }
 
 
@@ -681,34 +708,33 @@
 void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
 {
    // Add one item to the nesting level we are in for the new map or array
-   me->uError = Nesting_Increment(&(me->nesting));
-   if(me->uError == QCBOR_SUCCESS) {
-      /*
-       The offset where the length of an array or map will get written
-       is stored in a uint32_t, not a size_t to keep stack usage
-       smaller. This checks to be sure there is no wrap around when
-       recording the offset.  Note that on 64-bit machines CBOR larger
-       than 4GB can be encoded as long as no array / map offsets occur
-       past the 4GB mark, but the public interface says that the
-       maximum is 4GB to keep the discussion simpler.
-      */
-      size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
+   IncrementMapOrArrayCount(me);
 
-      /*
-       QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
-       code can run on a 32-bit machine and tests can pass on a 32-bit
-       machine. If it was exactly UINT32_MAX, then this code would not
-       compile or run on a 32-bit machine and an #ifdef or some
-       machine size detection would be needed reducing portability.
-      */
-      if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
-         me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
+   /*
+    The offset where the length of an array or map will get written
+    is stored in a uint32_t, not a size_t to keep stack usage
+    smaller. This checks to be sure there is no wrap around when
+    recording the offset.  Note that on 64-bit machines CBOR larger
+    than 4GB can be encoded as long as no array / map offsets occur
+    past the 4GB mark, but the public interface says that the
+    maximum is 4GB to keep the discussion simpler.
+   */
+   size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
 
-      } else {
-         // Increase nesting level because this is a map or array.  Cast
-         // from size_t to uin32_t is safe because of check above
-         me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)uEndPosition);
-      }
+   /*
+    QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
+    code can run on a 32-bit machine and tests can pass on a 32-bit
+    machine. If it was exactly UINT32_MAX, then this code would not
+    compile or run on a 32-bit machine and an #ifdef or some
+    machine size detection would be needed reducing portability.
+   */
+   if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
+      me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
+
+   } else {
+      // Increase nesting level because this is a map or array.  Cast
+      // from size_t to uin32_t is safe because of check above
+      me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)uEndPosition);
    }
 }
 
@@ -781,18 +807,23 @@
  */
 void QCBOREncode_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *me, uint8_t uMajorType)
 {
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(me->uError == QCBOR_SUCCESS) {
       if(!Nesting_IsInNest(&(me->nesting))) {
          me->uError = QCBOR_ERR_TOO_MANY_CLOSES;
+         return;
       } else if(Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
          me->uError = QCBOR_ERR_CLOSE_MISMATCH;
-      } else {
-         // Append the break marker (0xff for both arrays and maps)
-         AppendCBORHead(me, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
-
-         Nesting_Decrease(&(me->nesting));
+         return;
       }
    }
+#else
+   (void) uMajorType;
+#endif
+
+   // Append the break marker (0xff for both arrays and maps)
+   AppendCBORHead(me, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
+   Nesting_Decrease(&(me->nesting));
 }
 
 
@@ -807,10 +838,12 @@
       goto Done;
    }
 
-   if (Nesting_IsInNest(&(me->nesting))) {
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(Nesting_IsInNest(&(me->nesting))) {
       uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
       goto Done;
    }
+#endif
 
    *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf));
 
@@ -834,63 +867,3 @@
 
    return nReturn;
 }
-
-
-
-
-/*
-Object code sizes on 64-bit x86 with GCC -Os Jan 2020. GCC compiles smaller
-than LLVM and optimizations have been made to decrease code size. Bigfloat,
-Decimal fractions and indefinite length encoding were added to increase code
-size. Bstr wrapping is now separate which means if you don't use it, it gets
-dead stripped.
-
-_QCBOREncode_EncodeHead           187
-_QCBOREncode_CloseBstrWrap2:      154
-_QCBOREncode_AddExponentAndMantissa: 144
-_QCBOREncode_AddBuffer            105
-_QCBOREncode_OpenMapOrArray       101
-_QCBOREncode_CloseMapOrArrayIndefiniteLength: 72
-_QCBOREncode_Finish                71
-_InsertCBORHead.part.0             66
-_QCBOREncode_CloseMapOrArray       64
-_QCBOREncode_AddType7              58
-_QCBOREncode_AddInt64              57
-_AppendCBORHead                    54
-_QCBOREncode_AddUInt64             40
-_QCBOREncode_Init                  38
-_Nesting_Increment.isra.0          36
-_QCBOREncode_FinishGetSize:        34
-_QCBOREncode_AddDouble:            26
-_QCBOREncode_AddTag:               15
-Total                            1322
-Min_encode use case               776
-
-
- Object code sizes on X86 with LLVM compiler and -Os (Dec 30, 2018)
-
- _QCBOREncode_Init   69
- _QCBOREncode_AddUInt64   76
- _QCBOREncode_AddInt64   87
- _QCBOREncode_AddBuffer   113
- _QCBOREncode_AddTag 27
- _QCBOREncode_AddType7   87
- _QCBOREncode_AddDouble 36
- _QCBOREncode_OpenMapOrArray   103
- _QCBOREncode_CloseMapOrArray   181
- _InsertEncodedTypeAndNumber   190
- _QCBOREncode_Finish   72
- _QCBOREncode_FinishGetSize  70
-
- Total is about 1.1KB
-
- _QCBOREncode_CloseMapOrArray is larger because it has a lot
- of nesting tracking to do and much of Nesting_ inlines
- into it. It probably can't be reduced much.
-
- If the error returned by Nesting_Increment() can be ignored
- because the limit is so high and the consequence of exceeding
- is proved to be inconsequential, then a lot of if(me->uError)
- instance can be removed, saving some code.
-
- */
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index c573a4b..154bde7 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -1780,8 +1780,12 @@
 
 int32_t BstrWrapErrorTest()
 {
-   // ---- Test closing a bstrwrap when it is an array that is open ---------
    QCBOREncodeContext EC;
+   UsefulBufC Wrapped;
+   UsefulBufC Encoded2;
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   // ---- Test closing a bstrwrap when it is an array that is open ---------
 
    QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
 
@@ -1792,12 +1796,10 @@
    QCBOREncode_AddUInt64(&EC, 466);
    QCBOREncode_OpenArray(&EC);
 
-   UsefulBufC Wrapped;
    QCBOREncode_CloseBstrWrap(&EC, &Wrapped);
 
    QCBOREncode_CloseArray(&EC);
 
-   UsefulBufC Encoded2;
    if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_CLOSE_MISMATCH) {
       return -1;
    }
@@ -1808,6 +1810,7 @@
    if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_TOO_MANY_CLOSES) {
       return -2;
    }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    // --------------- test nesting too deep ----------------------------------
    QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
@@ -2358,13 +2361,13 @@
 
    // Second verify error from an array in encoded output too large
    // Also test fetching the error code before finish
-   QCBOREncode_Init(&EC, Buffer);
+   QCBOREncode_Init(&EC, (UsefulBuf){NULL, UINT32_MAX});
    QCBOREncode_OpenArray(&EC);
-   QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, UINT32_MAX-6});
+   QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, UINT32_MAX-10});
    QCBOREncode_OpenArray(&EC); // Where QCBOR internally encounters and records error
    if(QCBOREncode_GetErrorState(&EC) != QCBOR_ERR_BUFFER_TOO_LARGE) {
       // Error fetch failed.
-      return -12;
+      return -122;
    }
    QCBOREncode_CloseArray(&EC);
    QCBOREncode_CloseArray(&EC);
@@ -2435,6 +2438,7 @@
    }
 
 
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    // ------ QCBOR_ERR_TOO_MANY_CLOSES --------
    QCBOREncode_Init(&EC, Large);
    for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) {
@@ -2471,6 +2475,7 @@
       // One more level to cause error
       return -9;
    }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    /* QCBOR_ERR_ARRAY_TOO_LONG is not tested here as
     it would require a 64KB of RAM to test */
@@ -2482,6 +2487,7 @@
       return -11;
    }
 
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    // ------ QCBOR_ERR_UNSUPPORTED --------
    QCBOREncode_Init(&EC, Large);
    QCBOREncode_OpenArray(&EC);
@@ -2496,6 +2502,8 @@
    if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_ENCODE_UNSUPPORTED) {
       return -13;
    }
+#endif /* #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
 
    return 0;
 }
diff --git a/test/run_tests.c b/test/run_tests.c
index 0609736..0383b21 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -73,7 +73,9 @@
     TEST_ENTRY(MapEncodeTest),
     TEST_ENTRY(ArrayNestingTest1),
     TEST_ENTRY(ArrayNestingTest2),
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
     TEST_ENTRY(ArrayNestingTest3),
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
     TEST_ENTRY(EncodeDateTest),
     TEST_ENTRY(SimpleValuesTest1),
     TEST_ENTRY(IntegerValuesTest1),