Refine use of integer variables to quiet static analyzers and reduce object code size a little

Note that the no bugs of consequence were found by the static analyzer. The analyzer used was codesafe.cn
diff --git a/inc/UsefulBuf.h b/inc/UsefulBuf.h
index 89ed643..a8da83b 100644
--- a/inc/UsefulBuf.h
+++ b/inc/UsefulBuf.h
@@ -1,6 +1,6 @@
 /*============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2019, Laurence Lundblade.
+ Copyright (c) 2018-2020, Laurence Lundblade.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -41,6 +41,7 @@
 
  when         who             what, where, why
  --------     ----            --------------------------------------------------
+ 1/25/2020    llundblade      Add some casts so static anlyzers don't complain.
  5/21/2019    llundblade      #define configs for efficient endianness handling.
  5/16/2019    llundblade      Add UsefulOutBuf_IsBufferNULL().
  3/23/2019    llundblade      Big documentation & style update. No interface
@@ -1692,8 +1693,8 @@
 #else
    uint8_t aTmp[2];
 
-   aTmp[0] = (uInteger16 & 0xff00) >> 8;
-   aTmp[1] = (uInteger16 & 0xff);
+   aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
+   aTmp[1] = (uint8_t)(uInteger16 & 0xff);
 
    pBytes = aTmp;
 #endif
@@ -1725,10 +1726,10 @@
 #else
    uint8_t aTmp[4];
 
-   aTmp[0] = (uInteger32 & 0xff000000) >> 24;
-   aTmp[1] = (uInteger32 & 0xff0000) >> 16;
-   aTmp[2] = (uInteger32 & 0xff00) >> 8;
-   aTmp[3] = (uInteger32 & 0xff);
+   aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
+   aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
+   aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
+   aTmp[3] = (uint8_t)(uInteger32 & 0xff);
 
    pBytes = aTmp;
 #endif
@@ -1775,14 +1776,14 @@
    // it is usually a little larger and slower than hton().
    uint8_t aTmp[8];
 
-   aTmp[0] = (uInteger64 & 0xff00000000000000) >> 56;
-   aTmp[1] = (uInteger64 & 0xff000000000000) >> 48;
-   aTmp[2] = (uInteger64 & 0xff0000000000) >> 40;
-   aTmp[3] = (uInteger64 & 0xff00000000) >> 32;
-   aTmp[4] = (uInteger64 & 0xff000000) >> 24;
-   aTmp[5] = (uInteger64 & 0xff0000) >> 16;
-   aTmp[6] = (uInteger64 & 0xff00) >> 8;
-   aTmp[7] = (uInteger64 & 0xff);
+   aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
+   aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
+   aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
+   aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
+   aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
+   aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
+   aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
+   aTmp[7] = (uint8_t)(uInteger64 & 0xff);
 
    pBytes = aTmp;
 #endif
@@ -1967,7 +1968,10 @@
 {
    const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
 
-   return pResult ? *(uint8_t *)pResult : 0;
+   // The ternery operator is subject to integer promotion, because the
+   // operands are smaller than int, so cast back to uint8_t is needed
+   // to be completely explicit about types (for static analyzers)
+   return (uint8_t)(pResult ? *(uint8_t *)pResult : 0);
 }
 
 static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
@@ -1995,7 +1999,12 @@
 #endif
 
 #else
-   return  ((uint16_t)pResult[0] << 8) + (uint16_t)pResult[1];
+
+   // The operations here are subject to integer promotion because the
+   // operands are smaller than int. They will be promoted to unsigned
+   // int for the shift and addition. The cast back to uint16_t is  is needed
+   // to be completely explicit about types (for static analyzers)
+   return (uint16_t)((pResult[0] << 8) + pResult[1]);
 
 #endif
 }
diff --git a/inc/qcbor.h b/inc/qcbor.h
index 18fd49e..00e3656 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -43,6 +43,7 @@
 
  when       who           what, where, why
  --------   ----          ---------------------------------------------------
+ 01/25/2020 llundblade    Cleaner handling of too-long encoded string input.
  01/08/2020 llundblade    Documentation corrections & improved code formatting.
  12/30/19   llundblade    Add support for decimal fractions and bigfloats.
  08/7/19    llundblade    Better handling of not well-formed encode and decode.
@@ -773,7 +774,15 @@
 
    /** Something is wrong with a decimal fraction or bigfloat such as
     it not consisting of an array with two integers */
-   QCBOR_ERR_BAD_EXP_AND_MANTISSA = 23
+   QCBOR_ERR_BAD_EXP_AND_MANTISSA = 23,
+
+   /** When decoding, a string's size is greater than size_t. 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).
+    */
+    QCBOR_ERR_STRING_TOO_LONG = 24
+
 } QCBORError;
 
 
diff --git a/src/ieee754.c b/src/ieee754.c
index ea44e1d..ef0adef 100644
--- a/src/ieee754.c
+++ b/src/ieee754.c
@@ -19,7 +19,8 @@
  the assumption that the optimizer will do a good job. The LLVM
  optimizer, -Os, does seem to do the job and the resulting object code
  is smaller from combining code for the many different cases (normal,
- subnormal, infinity, zero...) for the conversions.
+ subnormal, infinity, zero...) for the conversions. GCC is no where near
+ as good.
 
  This code has really long lines and is much easier to read because of
  them. Some coding guidelines prefer 80 column lines (can they not afford
@@ -27,7 +28,8 @@
  columns.
 
  Dead stripping is also really helpful to get code size down when
- floating-point encoding is not needed.
+ floating-point encoding is not needed. (If this is put in a library
+ and linking is against the library, then dead stripping is automatic).
 
  This code works solely using shifts and masks and thus has no
  dependency on any math libraries. It can even work if the CPU doesn't
@@ -47,6 +49,10 @@
  - https://en.wikipedia.org/wiki/IEEE_754 and subordinate pages
 
  - https://stackoverflow.com/questions/19800415/why-does-ieee-754-reserve-so-many-nan-values
+
+ - https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
+
+ - https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
  */
 
 
@@ -97,10 +103,10 @@
     0xfe     254      127      Largest normal exponent
     0xff     255      128      NaN and Infinity  */
 #define SINGLE_EXPONENT_BIAS        (127)
-#define SINGLE_EXPONENT_MAX         (SINGLE_EXPONENT_BIAS)    // 127  unbiased
+#define SINGLE_EXPONENT_MAX         (SINGLE_EXPONENT_BIAS)    //  127 unbiased
 #define SINGLE_EXPONENT_MIN         (-SINGLE_EXPONENT_BIAS+1) // -126 unbiased
 #define SINGLE_EXPONENT_ZERO        (-SINGLE_EXPONENT_BIAS)   // -127 unbiased
-#define SINGLE_EXPONENT_INF_OR_NAN  (SINGLE_EXPONENT_BIAS+1)  // 128  unbiased
+#define SINGLE_EXPONENT_INF_OR_NAN  (SINGLE_EXPONENT_BIAS+1)  //  128 unbiased
 
 
 // --------- Double-Precision ----------
@@ -132,14 +138,13 @@
 
 
 /*
- Convenient functions to avoid type punning, compiler warnings and such
- The optimizer reduces them to a simple assignment.
- This is a crusty corner of C. It shouldn't be this hard.
+ Convenient functions to avoid type punning, compiler warnings and
+ such. The optimizer reduces them to a simple assignment.  This is a
+ crusty corner of C. It shouldn't be this hard.
 
  These are also in UsefulBuf.h under a different name. They are copied
- here to avoid a dependency on UsefulBuf.h. There is no
- object code size impact because these always optimze down to a
- simple assignment.
+ here to avoid a dependency on UsefulBuf.h. There is no object code
+ size impact because these always optimze down to a simple assignment.
  */
 static inline uint32_t CopyFloatToUint32(float f)
 {
@@ -175,13 +180,18 @@
 {
     // Pull the three parts out of the single-precision float
     const uint32_t uSingle = CopyFloatToUint32(f);
-    const int32_t  nSingleUnbiasedExponent = ((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS;
-    const uint32_t uSingleSign             =  (uSingle & SINGLE_SIGN_MASK) >> SINGLE_SIGN_SHIFT;
-    const uint32_t uSingleSignificand      =   uSingle & SINGLE_SIGNIFICAND_MASK;
+    const int32_t  nSingleUnbiasedExponent = (int32_t)((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS;
+    const uint32_t uSingleSign             = (uSingle & SINGLE_SIGN_MASK) >> SINGLE_SIGN_SHIFT;
+    const uint32_t uSingleSignificand      = uSingle & SINGLE_SIGNIFICAND_MASK;
 
 
     // Now convert the three parts to half-precision.
-    uint16_t uHalfSign, uHalfSignificand, uHalfBiasedExponent;
+
+    // All works is done on uint32_t with conversion to uint16_t at the end.
+    // This avoids integer promotions that static analyzers complain about and
+    // reduces code size.
+    uint32_t uHalfSign, uHalfSignificand, uHalfBiasedExponent;
+
     if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN) {
         // +/- Infinity and NaNs -- single biased exponent is 0xff
         uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS;
@@ -189,13 +199,13 @@
             // Infinity
             uHalfSignificand = 0;
         } else {
-            // Copy the LBSs of the NaN payload that will fit from the single to the half
+            // Copy the LSBs of the NaN payload that will fit from the single to the half
             uHalfSignificand = uSingleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT);
             if(uSingleSignificand & SINGLE_QUIET_NAN_BIT) {
                 // It's a qNaN; copy the qNaN bit
                 uHalfSignificand |= HALF_QUIET_NAN_BIT;
             } else {
-                // It's a sNaN; make sure the significand is not zero so it stays a NaN
+                // It's an sNaN; make sure the significand is not zero so it stays a NaN
                 // This is needed because not all significand bits are copied from single
                 if(!uHalfSignificand) {
                     // Set the LSB. This is what wikipedia shows for sNAN.
@@ -213,26 +223,28 @@
         uHalfSignificand    = 0;
     } else if(nSingleUnbiasedExponent < HALF_EXPONENT_MIN) {
         // Exponent is too small to express in half-precision normal; make it a half-precision subnormal
-        uHalfBiasedExponent = (uint16_t)(HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS);
+        uHalfBiasedExponent = HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS;
         // Difference between single normal exponent and the base exponent of a half subnormal
-        const uint32_t nExpDiff = -(nSingleUnbiasedExponent - HALF_EXPONENT_MIN);
+        const uint32_t uExpDiff = (uint32_t)-(nSingleUnbiasedExponent - HALF_EXPONENT_MIN);
         // Also have to shift the significand by the difference in number of bits between a single and a half significand
-        const int32_t nSignificandBitsDiff = SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS;
+        const uint32_t uSignificandBitsDiff = SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS;
         // Add in the 1 that is implied in the significand of a normal number; it needs to be present in a subnormal
-        const uint32_t uSingleSignificandSubnormal = uSingleSignificand + (0x01L << SINGLE_NUM_SIGNIFICAND_BITS);
-        uHalfSignificand = uSingleSignificandSubnormal >> (nExpDiff + nSignificandBitsDiff);
+        const uint32_t uSingleSignificandSubnormal = uSingleSignificand + (0x01UL << SINGLE_NUM_SIGNIFICAND_BITS);
+        uHalfSignificand = uSingleSignificandSubnormal >> (uExpDiff + uSignificandBitsDiff);
     } else {
-        // The normal case
-        uHalfBiasedExponent = nSingleUnbiasedExponent + HALF_EXPONENT_BIAS;
+        // The normal case, exponent is in range for half-precision
+        uHalfBiasedExponent = (uint32_t)(nSingleUnbiasedExponent + HALF_EXPONENT_BIAS);
         uHalfSignificand    = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
     }
     uHalfSign = uSingleSign;
 
     // Put the 3 values in the right place for a half precision
-    const uint16_t uHalfPrecision =  uHalfSignificand |
+    const uint32_t uHalfPrecision =  uHalfSignificand |
                                     (uHalfBiasedExponent << HALF_EXPONENT_SHIFT) |
                                     (uHalfSign << HALF_SIGN_SHIFT);
-    return uHalfPrecision;
+    // Cast is safe because all the masks and shifts above work to make
+    // a half precision value which is only 16 bits.
+    return (uint16_t)uHalfPrecision;
 }
 
 
@@ -241,13 +253,19 @@
 {
     // Pull the three parts out of the double-precision float
     const uint64_t uDouble = CopyDoubleToUint64(d);
-    const int64_t  nDoubleUnbiasedExponent = ((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS;
-    const uint64_t uDoubleSign             =  (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT;
-    const uint64_t uDoubleSignificand      =   uDouble & DOUBLE_SIGNIFICAND_MASK;
-
+    const int64_t  nDoubleUnbiasedExponent = (int64_t)((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS;
+    const uint64_t uDoubleSign             = (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT;
+    const uint64_t uDoubleSignificand      = uDouble & DOUBLE_SIGNIFICAND_MASK;
 
     // Now convert the three parts to half-precision.
-    uint16_t uHalfSign, uHalfSignificand, uHalfBiasedExponent;
+
+    // All works is done on uint64_t with conversion to uint16_t at the end.
+    // This avoids integer promotions that static analyzers complain about.
+    // Other options are for these to be unsigned int or fast_int16_t. Code
+    // size doesn't vary much between all these options for 64-bit LLVM,
+    // 64-bit GCC and 32-bit Armv7 LLVM.
+    uint64_t uHalfSign, uHalfSignificand, uHalfBiasedExponent;
+
     if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN) {
         // +/- Infinity and NaNs -- single biased exponent is 0xff
         uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS;
@@ -255,7 +273,7 @@
             // Infinity
             uHalfSignificand = 0;
         } else {
-            // Copy the LBSs of the NaN payload that will fit from the double to the half
+            // Copy the LSBs of the NaN payload that will fit from the double to the half
             uHalfSignificand = uDoubleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT);
             if(uDoubleSignificand & DOUBLE_QUIET_NAN_BIT) {
                 // It's a qNaN; copy the qNaN bit
@@ -279,37 +297,42 @@
         uHalfSignificand    = 0;
     } else if(nDoubleUnbiasedExponent < HALF_EXPONENT_MIN) {
         // Exponent is too small to express in half-precision; round down to zero
-        uHalfBiasedExponent = (uint16_t)(HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS);
+        uHalfBiasedExponent = HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS;
         // Difference between double normal exponent and the base exponent of a half subnormal
-        const uint64_t nExpDiff = -(nDoubleUnbiasedExponent - HALF_EXPONENT_MIN);
+        const uint64_t uExpDiff = (uint64_t)-(nDoubleUnbiasedExponent - HALF_EXPONENT_MIN);
         // Also have to shift the significand by the difference in number of bits between a double and a half significand
-        const int64_t nSignificandBitsDiff = DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS;
+        const uint64_t uSignificandBitsDiff = DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS;
         // Add in the 1 that is implied in the significand of a normal number; it needs to be present in a subnormal
         const uint64_t uDoubleSignificandSubnormal = uDoubleSignificand + (0x01ULL << DOUBLE_NUM_SIGNIFICAND_BITS);
-        uHalfSignificand = uDoubleSignificandSubnormal >> (nExpDiff + nSignificandBitsDiff);
+        uHalfSignificand = uDoubleSignificandSubnormal >> (uExpDiff + uSignificandBitsDiff);
     } else {
-        // The normal case
-        uHalfBiasedExponent = nDoubleUnbiasedExponent + HALF_EXPONENT_BIAS;
+        // The normal case, exponent is in range for half-precision
+        uHalfBiasedExponent = (uint32_t)(nDoubleUnbiasedExponent + HALF_EXPONENT_BIAS);
         uHalfSignificand    = uDoubleSignificand >> (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
     }
     uHalfSign = uDoubleSign;
 
 
     // Put the 3 values in the right place for a half precision
-    const uint16_t uHalfPrecision =  uHalfSignificand |
+    const uint64_t uHalfPrecision =  uHalfSignificand |
                                     (uHalfBiasedExponent << HALF_EXPONENT_SHIFT) |
                                     (uHalfSign << HALF_SIGN_SHIFT);
-    return uHalfPrecision;
+    // Cast is safe because all the masks and shifts above work to make
+    // a half precision value which is only 16 bits.
+    return (uint16_t)uHalfPrecision;
 }
 
 
+
 // Public function; see ieee754.h
 float IEEE754_HalfToFloat(uint16_t uHalfPrecision)
 {
     // Pull out the three parts of the half-precision float
-    const uint16_t uHalfSignificand      =   uHalfPrecision & HALF_SIGNIFICAND_MASK;
-    const int16_t  nHalfUnBiasedExponent = ((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS;
-    const uint16_t uHalfSign             =  (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT;
+    // Do all the work in 32 bits because that is what the end result is
+    // may give smaller code size and will keep static analyzers happier.
+    const uint32_t uHalfSignificand      = uHalfPrecision & HALF_SIGNIFICAND_MASK;
+    const int32_t  nHalfUnBiasedExponent = (int32_t)((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS;
+    const uint32_t uHalfSign             = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT;
 
 
     // Make the three parts of the single-precision number
@@ -350,12 +373,11 @@
         }
     } else {
         // Normal number
-        uSingleBiasedExponent = nHalfUnBiasedExponent + SINGLE_EXPONENT_BIAS;
+        uSingleBiasedExponent = (uint32_t)(nHalfUnBiasedExponent + SINGLE_EXPONENT_BIAS);
         uSingleSignificand = uHalfSignificand << (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
     }
     uSingleSign = uHalfSign;
 
-
     // Shift the three parts of the single-precision into place
     const uint32_t uSinglePrecision = uSingleSignificand |
                                      (uSingleBiasedExponent << SINGLE_EXPONENT_SHIFT) |
@@ -369,9 +391,11 @@
 double IEEE754_HalfToDouble(uint16_t uHalfPrecision)
 {
     // Pull out the three parts of the half-precision float
-    const uint16_t uHalfSignificand      =   uHalfPrecision & HALF_SIGNIFICAND_MASK;
-    const int16_t  nHalfUnBiasedExponent = ((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS;
-    const uint16_t uHalfSign             =  (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT;
+    // Do all the work in 64 bits because that is what the end result is
+    // may give smaller code size and will keep static analyzers happier.
+    const uint64_t uHalfSignificand      = uHalfPrecision & HALF_SIGNIFICAND_MASK;
+    const int64_t  nHalfUnBiasedExponent = (int64_t)((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS;
+    const uint64_t uHalfSign             = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT;
 
 
     // Make the three parts of hte single-precision number
@@ -412,8 +436,8 @@
         }
     } else {
         // Normal number
-        uDoubleBiasedExponent = nHalfUnBiasedExponent + DOUBLE_EXPONENT_BIAS;
-        uDoubleSignificand    = (uint64_t)uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+        uDoubleBiasedExponent = (uint64_t)(nHalfUnBiasedExponent + DOUBLE_EXPONENT_BIAS);
+        uDoubleSignificand    = uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
     }
     uDoubleSign = uHalfSign;
 
@@ -433,7 +457,7 @@
 
     // Pull the neeed two parts out of the single-precision float
     const uint32_t uSingle = CopyFloatToUint32(f);
-    const int32_t  nSingleExponent    = ((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS;
+    const int32_t  nSingleExponent    = (int32_t)((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS;
     const uint32_t uSingleSignificand =   uSingle & SINGLE_SIGNIFICAND_MASK;
 
     // Bit mask that is the significand bits that would be lost when converting
@@ -469,7 +493,7 @@
 
     // Pull the needed two parts out of the double-precision float
     const uint64_t uDouble = CopyDoubleToUint64(d);
-    const int64_t  nDoubleExponent     = ((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS;
+    const int64_t  nDoubleExponent     = (int64_t)((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS;
     const uint64_t uDoubleSignificand  =   uDouble & DOUBLE_SIGNIFICAND_MASK;
 
     // Masks to check whether dropped significand bits are zero or not
diff --git a/src/ieee754.h b/src/ieee754.h
index d2c1224..705ef62 100644
--- a/src/ieee754.h
+++ b/src/ieee754.h
@@ -24,7 +24,7 @@
  +/- infinity, +/- zero, subnormal numbers, qNaN, sNaN and NaN
  payloads.
 
- This confirms to IEEE 754-2008, but note that this doesn't specify
+ This conforms to IEEE 754-2008, but note that this doesn't specify
  conversions, just the encodings.
 
  NaN payloads are preserved with alignment on the LSB. The qNaN bit is
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 26bc3f6..661264e 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -42,7 +42,9 @@
 
  when       who             what, where, why
  --------   ----            ---------------------------------------------------
- 01/08/2020 llundblade      Documentation corrections & improved code formatting.
+ 01/25/2020 llundblade      Cleaner handling of too-long encoded string input.
+ 01/25/2020 llundblade      Refine use of integer types to quiet static analysis
+ 01/08/2020 llundblade      Documentation corrections & improved code formatting
  12/30/19   llundblade      Add support for decimal fractions and bigfloats.
  11/07/19   llundblade      Fix long long conversion to double compiler warning
  09/07/19   llundblade      Fix bug decoding empty arrays and maps
@@ -107,7 +109,9 @@
 inline static uint8_t
 DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
 {
-   return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
+   // Check in DecodeNesting_Descend and never having
+   // QCBOR_MAX_ARRAY_NESTING > 255 gaurantee cast is safe
+   return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
 }
 
 inline static int
@@ -440,49 +444,52 @@
  This returns:
    pnMajorType -- the major type for the item
 
-   puNumber -- the "number" which is used a the value for integers,
+   puArgument -- the "number" which is used a the value for integers,
                tags and floats and length for strings and arrays
 
-   puAdditionalInfo -- Pass this along to know what kind of float or
+   pnAdditionalInfo -- Pass this along to know what kind of float or
                        if length is indefinite
 
+ The int type is preferred to uint8_t for some variables as this
+ avoids integer promotions, can reduce code size and makes
+ static analyzers happier.
  */
 inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
                                               int *pnMajorType,
                                               uint64_t *puArgument,
-                                              uint8_t *puAdditionalInfo)
+                                              int *pnAdditionalInfo)
 {
    QCBORError nReturn;
 
    // Get the initial byte that every CBOR data item has
-   const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf);
+   const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
 
    // Break down the initial byte
-   const uint8_t uTmpMajorType   = uInitialByte >> 5;
-   const uint8_t uAdditionalInfo = uInitialByte & 0x1f;
+   const int nTmpMajorType   = nInitialByte >> 5;
+   const int nAdditionalInfo = nInitialByte & 0x1f;
 
    // Where the number or argument accumulates
    uint64_t uArgument;
 
-   if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
+   if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
       // Need to get 1,2,4 or 8 additional argument bytes Map
       // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
       static const uint8_t aIterate[] = {1,2,4,8};
 
       // Loop getting all the bytes in the argument
       uArgument = 0;
-      for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
+      for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
          // This shift and add gives the endian conversion
          uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
       }
-   } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) {
+   } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
       // The reserved and thus-far unused additional info values
       nReturn = QCBOR_ERR_UNSUPPORTED;
       goto Done;
    } else {
       // Less than 24, additional info is argument or 31, an indefinite length
       // No more bytes to get
-      uArgument = uAdditionalInfo;
+      uArgument = (uint64_t)nAdditionalInfo;
    }
 
    if(UsefulInputBuf_GetError(pUInBuf)) {
@@ -492,14 +499,15 @@
 
    // All successful if we got here.
    nReturn           = QCBOR_SUCCESS;
-   *pnMajorType      = uTmpMajorType;
+   *pnMajorType      = nTmpMajorType;
    *puArgument       = uArgument;
-   *puAdditionalInfo = uAdditionalInfo;
+   *pnAdditionalInfo = nAdditionalInfo;
 
 Done:
    return nReturn;
 }
 
+
 /*
  CBOR doesn't explicitly specify two's compliment for integers but all
  CPUs use it these days and the test vectors in the RFC are so. All
@@ -511,12 +519,16 @@
  compliment to represent negative integers.
 
  See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
- used here in any way including in the interface
+ used carefully here, and in particular why it isn't used in the interface.
+ Also see
+ https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
+
+ Int is used for values that need less than 16-bits and would be subject
+ to integer promotion and complaining by static analyzers.
  */
 inline static QCBORError
 DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
 {
-   // Stack usage: int/ptr 1 -- 8
    QCBORError nReturn = QCBOR_SUCCESS;
 
    if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
@@ -531,7 +543,11 @@
       }
    } else {
       if(uNumber <= INT64_MAX) {
-         pDecodedItem->val.int64 = -uNumber-1;
+         // CBOR's representation of negative numbers lines up with the
+         // two-compliment representation. A negative integer has one
+         // more in range than a positive integer. INT64_MIN is
+         // equal to (-INT64_MAX) - 1.
+         pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
          pDecodedItem->uDataType = QCBOR_TYPE_INT64;
 
       } else {
@@ -577,16 +593,16 @@
  Decode true, false, floats, break...
  */
 inline static QCBORError
-DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
+DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
 {
-   // Stack usage: 0
    QCBORError nReturn = QCBOR_SUCCESS;
 
    // uAdditionalInfo is 5 bits from the initial byte compile time checks
-   // above make sure uAdditionalInfo values line up with uDataType values
-   pDecodedItem->uDataType = uAdditionalInfo;
+   // above make sure uAdditionalInfo values line up with uDataType values.
+   // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
+   pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
 
-   switch(uAdditionalInfo) {
+   switch(nAdditionalInfo) {
       // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
       // caught before this is called.
 
@@ -636,7 +652,6 @@
 }
 
 
-
 /*
  Decode text and byte strings. Call the string allocator if asked to.
  */
@@ -646,10 +661,20 @@
                                      UsefulInputBuf *pUInBuf,
                                      QCBORItem *pDecodedItem)
 {
-   // Stack usage: UsefulBuf 2, int/ptr 1  40
    QCBORError nReturn = QCBOR_SUCCESS;
 
-   const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
+   // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
+   // This check makes the casts to size_t below safe.
+
+   // 4 bytes less than the largest sizeof() so this can be tested by
+   // putting a SIZE_MAX length in the CBOR test input (no one will
+   // care the limit on strings is 4 bytes shorter).
+   if(uStrLen > SIZE_MAX-4) {
+      nReturn = QCBOR_ERR_STRING_TOO_LONG;
+      goto Done;
+   }
+
+   const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
    if(UsefulBuf_IsNULLC(Bytes)) {
       // Failed to get the bytes for this string item
       nReturn = QCBOR_ERR_HIT_END;
@@ -658,7 +683,7 @@
 
    if(pAllocator) {
       // We are asked to use string allocator to make a copy
-      UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, uStrLen);
+      UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
       if(UsefulBuf_IsNULL(NewMem)) {
          nReturn = QCBOR_ERR_STRING_ALLOCATE;
          goto Done;
@@ -670,8 +695,9 @@
       pDecodedItem->val.string = Bytes;
    }
    const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
-   pDecodedItem->uDataType  = bIsBstr ? QCBOR_TYPE_BYTE_STRING
-                                      : QCBOR_TYPE_TEXT_STRING;
+   // Cast because ternary operator causes promotion to integer
+   pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
+                                               : QCBOR_TYPE_TEXT_STRING);
 
 Done:
    return nReturn;
@@ -705,7 +731,6 @@
                                QCBORItem *pDecodedItem,
                                const QCORInternalAllocator *pAllocator)
 {
-   // Stack usage: int/ptr 3 -- 24
    QCBORError nReturn;
 
    /*
@@ -714,13 +739,13 @@
     an encoding of the length of the uNumber and is needed to decode
     floats and doubles
    */
-   int      uMajorType;
+   int      nMajorType;
    uint64_t uNumber;
-   uint8_t  uAdditionalInfo;
+   int      nAdditionalInfo;
 
    memset(pDecodedItem, 0, sizeof(QCBORItem));
 
-   nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
+   nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
 
    // Error out here if we got into trouble on the type and number.  The
    // code after this will not work if the type and number is not good.
@@ -730,25 +755,25 @@
 
    // At this point the major type and the value are valid. We've got
    // the type and the number that starts every CBOR data item.
-   switch (uMajorType) {
+   switch (nMajorType) {
       case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
       case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
-         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
+         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
             nReturn = QCBOR_ERR_BAD_INT;
          } else {
-            nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
+            nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
          }
          break;
 
       case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
       case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
-         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
-            const bool bIsBstr = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
-            pDecodedItem->uDataType = bIsBstr ? QCBOR_TYPE_BYTE_STRING
-                                              : QCBOR_TYPE_TEXT_STRING;
+         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+            const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
+            pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
+                                                        : QCBOR_TYPE_TEXT_STRING);
             pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
          } else {
-            nReturn = DecodeBytes(pAllocator, uMajorType, uNumber, pUInBuf, pDecodedItem);
+            nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
          }
          break;
 
@@ -759,18 +784,19 @@
             nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
             goto Done;
          }
-         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
+         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
             pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
          } else {
             // type conversion OK because of check above
             pDecodedItem->val.uCount = (uint16_t)uNumber;
          }
          // C preproc #if above makes sure constants for major types align
-         pDecodedItem->uDataType  = uMajorType;
+         // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
+         pDecodedItem->uDataType  = (uint8_t)nMajorType;
          break;
 
       case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
-         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
+         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
             nReturn = QCBOR_ERR_BAD_INT;
          } else {
             pDecodedItem->val.uTagV = uNumber;
@@ -780,7 +806,7 @@
 
       case CBOR_MAJOR_TYPE_SIMPLE:
          // Major type 7, float, double, true, false, null...
-         nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
+         nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
          break;
 
       default:
@@ -824,7 +850,8 @@
    // indefinite length string tests, to be sure all is OK if this is removed.
 
    // Only do indefinite length processing on strings
-   if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
+   if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING &&
+      pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
       goto Done; // no need to do any work here on non-string types
    }
 
@@ -864,7 +891,8 @@
       // Match data type of chunk to type at beginning.
       // Also catches error of other non-string types that don't belong.
       // Also catches indefinite length strings inside indefinite length strings
-      if(StringChunkItem.uDataType != uStringType || StringChunkItem.val.string.len == SIZE_MAX) {
+      if(StringChunkItem.uDataType != uStringType ||
+         StringChunkItem.val.string.len == SIZE_MAX) {
          nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
          break;
       }
@@ -1161,7 +1189,8 @@
    const UsefulBufC Temp    = pDecodedItem->val.string;
    pDecodedItem->val.bigNum = Temp;
    const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
-   pDecodedItem->uDataType  = bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
+   pDecodedItem->uDataType  = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
+                                                     : QCBOR_TYPE_NEGBIGNUM);
    return QCBOR_SUCCESS;
 }
 
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index cb6670d..ce14e41 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -42,6 +42,7 @@
 
  when       who             what, where, why
  --------   ----            ---------------------------------------------------
+ 01/25/2020 llundblade      Refine use of integer types to quiet static analysis.
  01/08/2020 llundblade      Documentation corrections & improved code formatting.
  12/30/19   llundblade      Add support for decimal fractions and bigfloats.
  8/7/19     llundblade      Prevent encoding simple type reserved values 24..31
@@ -147,9 +148,13 @@
    // items by two for maps to get the number of pairs.  This implementation
    // takes advantage of the map major type being one larger the array major
    // type, hence uDivisor is either 1 or 2.
-   const uint16_t uDivisor = pNesting->pCurrentNesting->uMajorType - CBOR_MAJOR_TYPE_ARRAY+1;
 
-   return pNesting->pCurrentNesting->uCount / uDivisor;
+   if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
+      // Cast back to uint16_t after integer promotion for bit shift
+      return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
+   } else {
+      return pNesting->pCurrentNesting->uCount;
+   }
 }
 
 inline static uint32_t Nesting_GetStartPos(QCBORTrackNesting *pNesting)
@@ -329,6 +334,26 @@
 
     Code Reviewers: THIS FUNCTION DOES POINTER MATH
     */
+   /*
+    The type int is used here for several variables because of the way
+    integer promotion works in C for integer variables that are
+    uint8_t or uint16_t. The basic rule is that they will always be
+    promoted to int if they will fit. All of these integer variables
+    need only hold values less than 255 or are promoted from uint8_t,
+    so they will always fit into an int. Note that promotion is only
+    to unsigned int if the value won't fit into an int even if the
+    promotion is for an unsigned like uint8_t.
+
+    By declaring them int, there are few implicit conversions and fewer
+    casts needed. Code size is reduced a little. It also makes static
+    analyzers happier.
+
+    Note also that declaring them uint8_t won't stop integer wrap
+    around if the code is wrong. It won't make the code more correct.
+
+    https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
+    https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
+    */
 
    // Holds up to 9 bytes of type and argument plus one extra so pointer
    // always points to valid bytes.
@@ -336,20 +361,20 @@
    // Point to the last bytes and work backwards
    uint8_t *pByte = &bytes[sizeof(bytes)-1];
    // This is the 5 bits in the initial byte that is not the major type
-   uint8_t uAdditionalInfo;
+   int nAdditionalInfo;
 
    if (uMajorType == CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN) {
       uMajorType = CBOR_MAJOR_TYPE_ARRAY;
-      uAdditionalInfo = LEN_IS_INDEFINITE;
+      nAdditionalInfo = LEN_IS_INDEFINITE;
    } else if (uMajorType == CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN) {
       uMajorType = CBOR_MAJOR_TYPE_MAP;
-      uAdditionalInfo = LEN_IS_INDEFINITE;
+      nAdditionalInfo = LEN_IS_INDEFINITE;
    } else if (uNumber < CBOR_TWENTY_FOUR && nMinLen == 0) {
       // Simple case where argument is < 24
-      uAdditionalInfo = uNumber;
+      nAdditionalInfo = (int)uNumber;
    } else if (uMajorType == CBOR_MAJOR_TYPE_SIMPLE && uNumber == CBOR_SIMPLE_BREAK) {
       // Break statement can be encoded in single byte too (0xff)
-      uAdditionalInfo = uNumber;
+      nAdditionalInfo = (int)uNumber;
    } else  {
       /*
        Encode argument in 1,2,4 or 8 bytes. Outer loop runs once for 1
@@ -361,22 +386,38 @@
        with zero bytes.
        */
       static const uint8_t aIterate[] = {1,1,2,4};
-      uint8_t i;
+      int i;
       for(i = 0; uNumber || nMinLen > 0; i++) {
-         const uint8_t uIterations = aIterate[i];
-         for(int j = 0; j < uIterations; j++) {
-            *--pByte = uNumber & 0xff;
+         const int nIterations = aIterate[i];
+         for(int j = 0; j < nIterations; j++) {
+            *--pByte = (uint8_t)(uNumber & 0xff);
             uNumber = uNumber >> 8;
          }
-         nMinLen -= uIterations;
+         nMinLen -= nIterations;
       }
       // Additional info is the encoding of the number of additional
       // bytes to encode argument.
-      uAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
+      nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
    }
-   *--pByte = (uMajorType << 5) + uAdditionalInfo;
 
-   UsefulOutBuf_InsertData(&(me->OutBuf), pByte, &bytes[sizeof(bytes)-1] - pByte, uPos);
+   /*
+    Expression integer-promotes to type int. The code above in
+    function gaurantees that uAdditionalInfo will never be larger than
+    0x1f. The caller may pass in a too-large uMajor type. The
+    conversion to unint8_t will cause an integer wrap around and
+    incorrect CBOR will be generated, but no security issue will
+    incur.
+    */
+   *--pByte = (uint8_t)((uMajorType << 5) + nAdditionalInfo);
+
+   /*
+    Will not go negative because the loops run for at most 8
+    decrements of pByte, only one other decrement is made and the
+    array is sized for this.
+    */
+   const size_t uHeadLen = (size_t)(&bytes[sizeof(bytes)-1] - pByte);
+
+   UsefulOutBuf_InsertData(&(me->OutBuf), pByte, uHeadLen, uPos);
 }
 
 
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index d8ccbac..1c2634e 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -79,23 +79,17 @@
    UsefulBufC UBC2 = {"unbounce ", 9};
    UsefulOutBuf_InsertUsefulBuf(&UOB, UBC2, 10);
 
-   // Make it a null terminated string (because all the appends and
-   // inserts above not strcpy !)
-   UsefulOutBuf_AppendByte(&UOB, '\0');
 
+   const UsefulBufC Expected = UsefulBuf_FROM_SZ_LITERAL("heffalump unbounce bluster hunny");
 
    UsefulBufC U = UsefulOutBuf_OutUBuf(&UOB);
-
-   const char *expected = "heffalump unbounce bluster hunny";
-
-   if(UsefulBuf_IsNULLC(U) || U.len-1 != strlen(expected) || strcmp(expected, U.ptr) || UsefulOutBuf_GetError(&UOB)) {
+   if(UsefulBuf_IsNULLC(U) || UsefulBuf_Compare(Expected, U) || UsefulOutBuf_GetError(&UOB)) {
       szReturn = "OutUBuf";
    }
 
    UsefulBuf_MAKE_STACK_UB(buf, 50);
    UsefulBufC Out =  UsefulOutBuf_CopyOut(&UOB, buf);
-
-   if(UsefulBuf_IsNULLC(Out) || Out.len-1 != strlen(expected) || strcmp(expected, Out.ptr)) {
+   if(UsefulBuf_IsNULLC(Out) || UsefulBuf_Compare(Expected, Out)) {
       szReturn = "CopyOut";
    }
 
@@ -316,10 +310,9 @@
    if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3))
      return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed";
 
-   char *sz = "not const"; // some data for the test
-   UsefulBuf B = (UsefulBuf){sz, sizeof(sz)};
+   UsefulBuf B = (UsefulBuf){(void *)Too.ptr, Too.len};
    UsefulBufC BC = UsefulBuf_Const(B);
-   if(BC.len != sizeof(sz) || BC.ptr != sz)
+   if(BC.len != Too.len || BC.ptr != Too.ptr)
       return "UsefulBufConst failed";
 
    return NULL;
diff --git a/test/float_tests.c b/test/float_tests.c
index 10ac012..20057c3 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -77,7 +77,7 @@
 };
 
 
-int HalfPrecisionDecodeBasicTests()
+int32_t HalfPrecisionDecodeBasicTests()
 {
     UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
 
@@ -190,12 +190,12 @@
 
 
 
-int HalfPrecisionAgainstRFCCodeTest()
+int32_t HalfPrecisionAgainstRFCCodeTest()
 {
     for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
         unsigned char x[2];
-        x[1] = uHalfP & 0xff;
-        x[0] = uHalfP >> 8;
+        x[1] = (uint8_t)(uHalfP & 0xff);
+        x[0] = (uint8_t)(uHalfP >> 8); // uHalfP is always less than 0xffff
         double d = decode_half(x);
 
         // Contruct the CBOR for the half-precision float by hand
@@ -203,7 +203,7 @@
         UsefulOutBuf UOB;
         UsefulOutBuf_Init(&UOB, __xx);
 
-        const uint8_t uHalfPrecInitialByte = HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5); // 0xf9
+        const uint8_t uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); // 0xf9
         UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float
         UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP);
 
@@ -307,7 +307,7 @@
 };
 
 
-int DoubleAsSmallestTest()
+int32_t DoubleAsSmallestTest()
 {
     UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420);
 
diff --git a/test/float_tests.h b/test/float_tests.h
index f3acb71..f777156 100644
--- a/test/float_tests.h
+++ b/test/float_tests.h
@@ -13,11 +13,13 @@
 #ifndef float_tests_h
 #define float_tests_h
 
-int HalfPrecisionDecodeBasicTests(void);
+#include <stdint.h>
 
-int DoubleAsSmallestTest(void);
+int32_t HalfPrecisionDecodeBasicTests(void);
 
-int HalfPrecisionAgainstRFCCodeTest(void);
+int32_t DoubleAsSmallestTest(void);
+
+int32_t HalfPrecisionAgainstRFCCodeTest(void);
 
 
 #endif /* float_tests_h */
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 8c2f093..1009e16 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -87,7 +87,7 @@
 
 // return CBOR error or -1 if type of value doesn't match
 
-static int IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx)
+static int32_t IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx)
 {
    QCBORItem          Item;
    int nCBORError;
@@ -99,7 +99,7 @@
 
    if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
       return nCBORError;
-   if(Item.uDataType != QCBOR_TYPE_INT64 || // Todo; fix for 32-bit machines
+   if(Item.uDataType != QCBOR_TYPE_INT64 ||
       Item.val.int64 != -9223372036854775807LL - 1)
       return -1;
 
@@ -414,10 +414,10 @@
 }
 
 
-// The largest negative int possible in CBOR.
-// Not possible in C.
-static const uint8_t spTooBigNegative[] = {
-   0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+// One less than the smallest negative integer allowed in C. Decoding
+// this should fail.
+static const uint8_t spTooSmallNegative[] = {
+   0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
 
@@ -425,7 +425,7 @@
    Tests the decoding of lots of different integers sizes
    and values.
  */
-int IntegerValuesParseTest()
+int32_t IntegerValuesParseTest()
 {
    int nReturn;
    QCBORDecodeContext DCtx;
@@ -442,7 +442,7 @@
 
    // The one large negative integer that can be parsed
    QCBORDecode_Init(&DCtx,
-                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooBigNegative),
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooSmallNegative),
                     QCBOR_DECODE_MODE_NORMAL);
 
    QCBORItem item;
@@ -464,7 +464,7 @@
 
 static uint8_t spSimpleArrayBuffer[50];
 
-static int CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen)
+static int32_t CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen)
 {
    QCBOREncodeContext ECtx;
    int nReturn = -1;
@@ -506,6 +506,9 @@
 
 
 /*
+ Some basic CBOR with map and array used in a lot of tests.
+ The map labels are all strings
+
  {"first integer": 42,
   "an array of two strings": [
       "string1", "string2"
@@ -518,8 +521,7 @@
    }
   }
  */
-
-static uint8_t pValidMapEncoded[] = {
+static const uint8_t pValidMapEncoded[] = {
    0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e,
    0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e,
    0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20,
@@ -537,7 +539,7 @@
    0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63,
    0x73 } ;
 
-static int ParseOrderedArray(const uint8_t *pEncoded,
+static int32_t ParseOrderedArray(const uint8_t *pEncoded,
                              size_t nLen,
                              int64_t *pInt1,
                              int64_t *pInt2,
@@ -589,7 +591,7 @@
 
 
 
-int SimpleArrayTest()
+int32_t SimpleArrayTest()
 {
    uint8_t *pEncoded;
    size_t  nEncodedLen;
@@ -640,7 +642,7 @@
 static uint8_t sEmpties[] = {0x83, 0x00, 0x80, 0x84, 0x80, 0x81, 0x00, 0xa0,
                              0xa3, 0x01, 0xa0, 0x02, 0xa0, 0x03, 0x80};
 
-int EmptyMapsAndArraysTest()
+int32_t EmptyMapsAndArraysTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -768,7 +770,7 @@
 static uint8_t spDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
                                  0x81, 0x81, 0x81, 0x80};
 
-int ParseDeepArrayTest()
+int32_t ParseDeepArrayTest()
 {
    QCBORDecodeContext DCtx;
    int nReturn = 0;
@@ -798,7 +800,7 @@
                                     0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
                                     0x81, 0x81, 0x81, 0x80};
 
-int ParseTooDeepArrayTest()
+int32_t ParseTooDeepArrayTest()
 {
    QCBORDecodeContext DCtx;
    int nReturn = 0;
@@ -829,7 +831,7 @@
 
 
 
-int ShortBufferParseTest()
+int32_t ShortBufferParseTest()
 {
    int nResult = 0;
 
@@ -853,7 +855,7 @@
 
 
 
-int ShortBufferParseTest2()
+int32_t ShortBufferParseTest2()
 {
    uint8_t *pEncoded;
    int      nReturn;
@@ -881,9 +883,10 @@
 
 /*
  Decode and thoroughly check a moderately complex
- set of maps
+ set of maps. Can be run in QCBOR_DECODE_MODE_NORMAL or in
+ QCBOR_DECODE_MODE_MAP_STRINGS_ONLY.
  */
-static int ParseMapTest1(QCBORDecodeMode nMode)
+static int32_t ParseMapTest1(QCBORDecodeMode nMode)
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -1010,7 +1013,7 @@
  Decode and thoroughly check a moderately complex
  set of maps
  */
-int ParseMapAsArrayTest()
+int32_t ParseMapAsArrayTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -1219,7 +1222,7 @@
  and made prettier and maybe a little more
  thorough.
  */
-static int ExtraBytesTest(int nLevel)
+static int32_t ExtraBytesTest(int nLevel)
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -1413,24 +1416,35 @@
 
 
 
-
-int ParseMapTest()
+/*
+ Public function for initialization. See header qcbor.h
+ */
+int32_t ParseMapTest()
 {
-   // Parse a moderatly complex map structure very thoroughl
-   int n = ParseMapTest1(QCBOR_DECODE_MODE_NORMAL);
+   // Parse a moderatly complex map structure very thoroughly
+   int32_t nResult = ParseMapTest1(QCBOR_DECODE_MODE_NORMAL);
+   if(nResult) {
+      return nResult;
+   }
 
-   n = ParseMapTest1(QCBOR_DECODE_MODE_MAP_STRINGS_ONLY);
+   // Again, but in strings-only mode. It should succeed since the input
+   // map has only string labels.
+   nResult = ParseMapTest1(QCBOR_DECODE_MODE_MAP_STRINGS_ONLY);
+   if(nResult) {
+      return nResult;
+   }
 
-   if(!n) {
-      for(int i = 0; i < 10; i++) {
-         n = ExtraBytesTest(i);
-         if(n) {
-            break;
-         }
+   // Again, but try to finish the decoding before the end of the
+   // input at 10 different place and see that the right error code
+   // is returned.
+   for(int i = 0; i < 10; i++) {
+      nResult = ExtraBytesTest(i);
+      if(nResult) {
+         break;
       }
    }
 
-   return(n);
+   return nResult;
 }
 
 
@@ -1438,7 +1452,7 @@
                                    0xe0, 0xf3, 0xf8, 0x00, 0xf8, 0x13,
                                    0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff};
 
-int ParseSimpleTest()
+int32_t ParseSimpleTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -1532,7 +1546,7 @@
 }
 
 
-int NotWellFormedTests()
+int32_t NotWellFormedTests()
 {
    // Loop over all the not-well-formed instance of CBOR
    // that are test vectors in not_well_formed_cbor.h
@@ -1574,7 +1588,7 @@
 };
 
 
-static int ProcessFailures(struct FailInput *pFailInputs, size_t nNumFails)
+static int32_t ProcessFailures(struct FailInput *pFailInputs, size_t nNumFails)
 {
    for(struct FailInput *pF = pFailInputs; pF < pFailInputs + nNumFails; pF++) {
       // Set up the decoding context including a memory pool so that
@@ -1888,9 +1902,9 @@
    { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG },
 };
 
-int DecodeFailureTests()
+int32_t DecodeFailureTests()
 {
-   int nResult;
+   int32_t nResult;
 
    nResult = ProcessFailures(Failures, sizeof(Failures)/sizeof(struct FailInput));
    if(nResult) {
@@ -1925,6 +1939,29 @@
       }
    }
 
+/*
+   This test is disabled until QCBOREncode_EncodeHead() is brought in so
+ the size encoded can be tied to SIZE_MAX and work for all size CPUs.
+
+ This relies on the largest string allowed being SIZE_MAX -4 rather than
+ SIZE_MAX. That way the test can be performed.
+   {
+      QCBORDecodeContext DCtx;
+      QCBORItem          Item;
+
+      static uint8_t foo[] = {0x5b, 0xff, 0xff, 0xff, 0xff,
+                                    0xff, 0xff, 0xff, 0xff};
+
+      QCBORDecode_Init(&DCtx,
+                       UsefulBuf_FROM_BYTE_ARRAY_LITERAL(foo),
+                       QCBOR_DECODE_MODE_NORMAL);
+
+      if(QCBOR_ERR_STRING_TOO_LONG != QCBORDecode_GetNext(&DCtx, &Item)) {
+         return -4;
+      }
+   }
+*/
+
    return 0;
 }
 
@@ -1940,7 +1977,7 @@
 
    for(int inputByte = 0; inputByte < 256; inputByte++) {
       // Set up the input
-      pBuf[nLen] = inputByte;
+      pBuf[nLen] = (uint8_t)inputByte;
       const UsefulBufC Input = {pBuf, nLen+1};
 
       // Get ready to parse
@@ -1968,7 +2005,7 @@
 /*
  Public function for initialization. See header qcbor.h
  */
-int ComprehensiveInputTest()
+int32_t ComprehensiveInputTest()
 {
    // Size 2 tests 64K inputs and runs quickly
    uint8_t pBuf[2];
@@ -1982,7 +2019,7 @@
 /*
  Public function for initialization. See header qcbor.h
  */
-int BigComprehensiveInputTest()
+int32_t BigComprehensiveInputTest()
 {
    // size 3 tests 16 million inputs and runs OK
    // in seconds on fast machines. Size 4 takes
@@ -2038,7 +2075,7 @@
 }
 
 
-int DateParseTest()
+int32_t DateParseTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -2185,10 +2222,10 @@
       0xcb, 0xc8, 0xc7, 0x24,
       0xc8, 0x22};
 
-static int CheckCSRMaps(QCBORDecodeContext *pDC);
+static int32_t CheckCSRMaps(QCBORDecodeContext *pDC);
 
 
-int OptTagParseTest()
+int32_t OptTagParseTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -2508,7 +2545,7 @@
 static uint8_t spBigNum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 
-int BignumParseTest()
+int32_t BignumParseTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
@@ -2588,7 +2625,7 @@
 
 
 
-static int CheckItemWithIntLabel(QCBORDecodeContext *pCtx,
+static int32_t CheckItemWithIntLabel(QCBORDecodeContext *pCtx,
                                  uint8_t uDataType,
                                  uint8_t uNestingLevel,
                                  uint8_t uNextNest,
@@ -2622,7 +2659,7 @@
 
 
 // Same code checks definite and indefinite length versions of the map
-static int CheckCSRMaps(QCBORDecodeContext *pDC)
+static int32_t CheckCSRMaps(QCBORDecodeContext *pDC)
 {
    if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 0, 1, 0, NULL)) return -1;
 
@@ -2687,7 +2724,7 @@
    0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
    0x07, 0x08, 0x09, 0x0a, 0x35, 0xa1, 0x24, 0x22};
 
-int NestedMapTest()
+int32_t NestedMapTest()
 {
    QCBORDecodeContext DCtx;
 
@@ -2700,7 +2737,7 @@
 
 
 
-int StringDecoderModeFailTest()
+int32_t StringDecoderModeFailTest()
 {
    QCBORDecodeContext DCtx;
 
@@ -2740,7 +2777,7 @@
    0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0xff, 0xff,
    0x35, 0xbf, 0x24, 0x22, 0xff, 0xff};
 
-int NestedMapTestIndefLen()
+int32_t NestedMapTestIndefLen()
 {
    QCBORDecodeContext DCtx;
 
@@ -2770,7 +2807,7 @@
 }
 
 
-static int parse_indeflen_nested(UsefulBufC Nested, int nNestLevel)
+static int32_t parse_indeflen_nested(UsefulBufC Nested, int nNestLevel)
 {
    QCBORDecodeContext DC;
    QCBORDecode_Init(&DC, Nested, 0);
@@ -2804,7 +2841,7 @@
 }
 
 
-int IndefiniteLengthNestTest()
+int32_t IndefiniteLengthNestTest()
 {
    UsefulBuf_MAKE_STACK_UB(Storage, 50);
    int i;
@@ -2832,7 +2869,7 @@
 // confused tag
 static const uint8_t spIndefiniteArrayBad5[] = {0x9f, 0xd1, 0xff};
 
-int IndefiniteLengthArrayMapTest()
+int32_t IndefiniteLengthArrayMapTest()
 {
    int nResult;
    // --- first test -----
@@ -3033,7 +3070,16 @@
    0x01 // integer being labeled.
 };
 
-static UsefulBufC MakeIndefiniteBigBstr(UsefulBuf Storage) // TODO: size this
+/**
+ Make an indefinite length string
+
+ @param Storage Storage for string, must be 144 bytes in size
+ @return The indefinite length string
+
+ This makes an array with one indefinite length string that has 7 chunks
+ from size of 1 byte up to 64 bytes.
+ */
+static UsefulBufC MakeIndefiniteBigBstr(UsefulBuf Storage)
 {
    UsefulOutBuf UOB;
 
@@ -3041,13 +3087,15 @@
    UsefulOutBuf_AppendByte(&UOB, 0x81);
    UsefulOutBuf_AppendByte(&UOB, 0x5f);
 
-   int i = 0;
-   for(int nChunkSize = 1; nChunkSize <= 128; nChunkSize *= 2) {
+   uint8_t uStringByte = 0;
+   // Use of type int is intentional
+   for(int uChunkSize = 1; uChunkSize <= 128; uChunkSize *= 2) {
+      // Not using preferred encoding here, but that is OK.
       UsefulOutBuf_AppendByte(&UOB, 0x58);
-      UsefulOutBuf_AppendByte(&UOB, (uint8_t)nChunkSize);
-      for(int j = 0; j < nChunkSize; j++ ) {
-         UsefulOutBuf_AppendByte(&UOB, i);
-         i++;
+      UsefulOutBuf_AppendByte(&UOB, (uint8_t)uChunkSize);
+      for(int j = 0; j < uChunkSize; j++) {
+         UsefulOutBuf_AppendByte(&UOB, uStringByte);
+         uStringByte++;
       }
    }
    UsefulOutBuf_AppendByte(&UOB, 0xff);
@@ -3070,7 +3118,7 @@
 }
 
 
-int IndefiniteLengthStringTest()
+int32_t IndefiniteLengthStringTest()
 {
    QCBORDecodeContext DC;
    QCBORItem Item;
@@ -3259,7 +3307,7 @@
 }
 
 
-int AllocAllStringsTest()
+int32_t AllocAllStringsTest()
 {
    QCBORDecodeContext DC;
    QCBORError nCBORError;
@@ -3366,7 +3414,7 @@
 
 
 
-int MemPoolTest(void)
+int32_t MemPoolTest(void)
 {
    // Set up the decoder with a tiny bit of CBOR to parse because
    // nothing can be done with it unless that is set up.
@@ -3464,7 +3512,7 @@
 }
 
 
-int SetUpAllocatorTest(void)
+int32_t SetUpAllocatorTest(void)
 {
    // Set up the decoder with a tiny bit of CBOR to parse because
    // nothing can be done with it unless that is set up.
@@ -3530,7 +3578,7 @@
                0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE
 };
 
-int ExponentAndMantissaDecodeTests(void)
+int32_t ExponentAndMantissaDecodeTests(void)
 {
    QCBORDecodeContext DC;
    QCBORError         nCBORError;
@@ -3722,7 +3770,7 @@
 };
 
 
-int ExponentAndMantissaDecodeFailTests()
+int32_t ExponentAndMantissaDecodeFailTests()
 {
    return ProcessFailures(ExponentAndMantissaFailures,
                           sizeof(ExponentAndMantissaFailures)/sizeof(struct FailInput));
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 2c556b8..e87490e 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -33,6 +33,7 @@
 #ifndef __QCBOR__qcbort_decode_tests__
 #define __QCBOR__qcbort_decode_tests__
 
+#include <stdint.h>
 
 /*
  Notes:
@@ -51,20 +52,20 @@
  Parse a well-known set of integers including those around the boundaries and
  make sure the expected values come out
  */
-int IntegerValuesParseTest(void);
+int32_t IntegerValuesParseTest(void);
 
 
 /*
  Decode a simple CBOR encoded array and make sure it returns all the correct values.
  This is a decode test.
  */
-int SimpleArrayTest(void);
+int32_t SimpleArrayTest(void);
 
 
 /*
  Tests with empty maps and arrays
  */
-int EmptyMapsAndArraysTest(void);
+int32_t EmptyMapsAndArraysTest(void);
 
 
 /*
@@ -72,21 +73,21 @@
  reported nesting level is correct.  This uses test vector
  of CBOR encoded data with a depth of 10.  This a parse test.
  */
-int ParseDeepArrayTest(void);
+int32_t ParseDeepArrayTest(void);
 
 
 /*
  See that the correct error is reported when parsing
  an array of depth 11, one too large.
  */
-int ParseTooDeepArrayTest(void);
+int32_t ParseTooDeepArrayTest(void);
 
 
 /*
   Try to parse some legit CBOR types that this parsers
   doesn't support.
  */
-int UnsupportedCBORDecodeTest(void);
+int32_t UnsupportedCBORDecodeTest(void);
 
 
 /*
@@ -94,33 +95,33 @@
   it over and over with one more byte less each time. It should fail
   every time on incorrect CBOR input. This is a hostile input decode test.
  */
-int ShortBufferParseTest(void);
+int32_t ShortBufferParseTest(void);
 
 
 /*
    Same as ShortBufferParseTest, but with a different encoded CBOR input.
    It is another hostile input test
  */
-int ShortBufferParseTest2(void);
+int32_t ShortBufferParseTest2(void);
 
 
 /*
   Parses the somewhat complicated CBOR MAP and makes sure all the correct
   values parse out.  About 15 values are tested. This is a decode test.
  */
-int ParseMapTest(void);
+int32_t ParseMapTest(void);
 
 
 /*
 Test the decoder mode where maps are treated as arrays.
  */
-int ParseMapAsArrayTest(void);
+int32_t ParseMapAsArrayTest(void);
 
 
 /*
  Test parsing of some simple values like true, false, null...
  */
-int ParseSimpleTest(void);
+int32_t ParseSimpleTest(void);
 
 
 /*
@@ -128,13 +129,13 @@
  (This is the CBORbis RFC which is not yet published at the
  time this test was added).
  */
-int NotWellFormedTests(void);
+int32_t NotWellFormedTests(void);
 
 
 /*
  Tests a number of failure cases on bad CBOR to get the right error code
  */
-int DecodeFailureTests(void);
+int32_t DecodeFailureTests(void);
 
 
 /*
@@ -145,7 +146,7 @@
  (Parsing all possible 3 byte strings takes too long on all but
   very fast machines).
  */
-int ComprehensiveInputTest(void);
+int32_t ComprehensiveInputTest(void);
 
 
 /*
@@ -155,64 +156,64 @@
  is only practical as a once-in-a-while regression test on
  fast machines.
  */
-int BigComprehensiveInputTest(void);
+int32_t BigComprehensiveInputTest(void);
 
 
 /*
  Thest the date types -- epoch and strings
  */
-int DateParseTest(void);
+int32_t DateParseTest(void);
 
 
 /*
   Test optional tags like the CBOR magic number.
  */
-int OptTagParseTest(void);
+int32_t OptTagParseTest(void);
 
 
 /*
  Parse some big numbers, positive and negative
  */
-int BignumParseTest(void);
+int32_t BignumParseTest(void);
 
 
 /*
  Test of mode where only string labels are allowed
  */
-int StringDecoderModeFailTest(void);
+int32_t StringDecoderModeFailTest(void);
 
 
 /*
  Parse some nested maps
  */
-int NestedMapTest(void);
+int32_t NestedMapTest(void);
 
 
 /*
  Parse maps with indefinite lengths
  */
-int NestedMapTestIndefLen(void);
+int32_t NestedMapTestIndefLen(void);
 
 
 /*
  Parse some maps and arrays with indefinite lengths.
  Includes some error cases.
  */
-int IndefiniteLengthArrayMapTest(void);
+int32_t IndefiniteLengthArrayMapTest(void);
 
 
 /*
  Parse indefinite length strings. Uses
  MemPool. Includes error cases.
  */
-int IndefiniteLengthStringTest(void);
+int32_t IndefiniteLengthStringTest(void);
 
 
 /*
  Test deep nesting of indefinite length
  maps and arrays including too deep.
  */
-int IndefiniteLengthNestTest(void);
+int32_t IndefiniteLengthNestTest(void);
 
 
 /*
@@ -220,19 +221,19 @@
  just indefinite length strings, are
  allocated. Includes error test cases.
  */
-int AllocAllStringsTest(void);
+int32_t AllocAllStringsTest(void);
 
 
 /*
  Direct test of MemPool string allocator
  */
-int MemPoolTest(void);
+int32_t MemPoolTest(void);
 
 
 /*
  Test the setting up of an external string allocator.
  */
-int SetUpAllocatorTest(void);
+int32_t SetUpAllocatorTest(void);
 
 
 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
@@ -240,13 +241,13 @@
  Test decoding of decimal fractions and big floats, both of which are
  made up of an exponent and mantissa.
  */
-int ExponentAndMantissaDecodeTests(void);
+int32_t ExponentAndMantissaDecodeTests(void);
 
 
 /*
  Hostile input tests for decimal fractions and big floats.
  */
-int ExponentAndMantissaDecodeFailTests(void);
+int32_t ExponentAndMantissaDecodeFailTests(void);
 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
 
 
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 9a7aecf..e922503 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -142,7 +142,7 @@
 /*
  Some very minimal tests.
  */
-int BasicEncodeTest()
+int32_t BasicEncodeTest()
 {
    // Very simple CBOR, a map with one boolean that is true in it
    QCBOREncodeContext EC;
@@ -511,7 +511,7 @@
 --XXXXboundary text--";
 
 
-int AllAddMethodsTest()
+int32_t AllAddMethodsTest()
 {
    // TODO: this test should be broken down into several so it is more
    // managable. Tags and labels could be more sensible
@@ -791,7 +791,7 @@
   to expected values generated from http://cbor.me.
 
  */
-int IntegerValuesTest1()
+int32_t IntegerValuesTest1()
 {
    QCBOREncodeContext ECtx;
    int nReturn = 0;
@@ -876,7 +876,7 @@
 static const uint8_t spExpectedEncodedSimple[] = {
    0x85, 0xf5, 0xf4, 0xf6, 0xf7, 0xa1, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7};
 
-int SimpleValuesTest1()
+int32_t SimpleValuesTest1()
 {
    QCBOREncodeContext ECtx;
    int nReturn = 0;
@@ -923,7 +923,7 @@
 static const uint8_t spExpectedEncodedSimpleIndefiniteLength[] = {
    0x9f, 0xf5, 0xf4, 0xf6, 0xf7, 0xbf, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7, 0xff, 0xff};
 
-int SimpleValuesIndefiniteLengthTest1()
+int32_t SimpleValuesIndefiniteLengthTest1()
 {
    QCBOREncodeContext ECtx;
    int nReturn = 0;
@@ -1118,7 +1118,7 @@
    0x31
 };
 
-int EncodeLengthThirtyoneTest()
+int32_t EncodeLengthThirtyoneTest()
 {
    QCBOREncodeContext ECtx;
    int nReturn = 0;
@@ -1198,7 +1198,7 @@
    0x32, 0x5a, 0x62, 0x53, 0x44, 0xc1, 0x19, 0x03, 0xe7
 };
 
-int EncodeDateTest()
+int32_t EncodeDateTest()
 {
    QCBOREncodeContext ECtx;
    int nReturn = 0;
@@ -1235,7 +1235,7 @@
 }
 
 
-int ArrayNestingTest1()
+int32_t ArrayNestingTest1()
 {
    QCBOREncodeContext ECtx;
    int i;
@@ -1258,7 +1258,7 @@
 
 
 
-int ArrayNestingTest2()
+int32_t ArrayNestingTest2()
 {
    QCBOREncodeContext ECtx;
    int i;
@@ -1282,7 +1282,7 @@
 
 
 
-int ArrayNestingTest3()
+int32_t ArrayNestingTest3()
 {
    QCBOREncodeContext ECtx;
    int i;
@@ -1399,7 +1399,7 @@
    0xff, 0xff};
 
 
-int EncodeRawTest()
+int32_t EncodeRawTest()
 {
    QCBOREncodeContext ECtx;
 
@@ -1425,7 +1425,7 @@
 /*
  This returns a pointer to spBigBuf
  */
-static int CreateMap(uint8_t **pEncoded, size_t *pEncodedLen)
+static int32_t CreateMap(uint8_t **pEncoded, size_t *pEncodedLen)
 {
    QCBOREncodeContext ECtx;
    int nReturn = -1;
@@ -1522,7 +1522,7 @@
    0x73 } ;
 
 
-int MapEncodeTest()
+int32_t MapEncodeTest()
 {
    uint8_t *pEncodedMaps;
    size_t nEncodedMapLen;
@@ -1563,7 +1563,7 @@
  */
 
 static UsefulBufC
-FormatRTICResults(int nRResult,
+FormatRTICResults(uint64_t uRResult,
                   uint64_t time,
                   const char *szType,
                   const char *szAlexString,
@@ -1586,7 +1586,7 @@
 
       // The result: 0 if scan happened and found nothing; 1 if it happened and
       // found something wrong; 2 if it didn't happen
-      QCBOREncode_AddSimpleToMap(&ECtx, "integrity", nRResult);
+      QCBOREncode_AddSimpleToMap(&ECtx, "integrity", uRResult);
 
       // Add the diagnostic code
       QCBOREncode_AddSZStringToMap(&ECtx, "type", szType);
@@ -1678,7 +1678,7 @@
    0xaa, 0xbb, 0x01, 0x01};
 
 
-int RTICResultsTest()
+int32_t RTICResultsTest()
 {
    const UsefulBufC Encoded = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730,
                                           "recent", "0xA1eC5001",
@@ -1777,7 +1777,7 @@
 
 
 
-int BstrWrapErrorTest()
+int32_t BstrWrapErrorTest()
 {
    // ---- Test closing a bstrwrap when it is an array that is open ---------
    QCBOREncodeContext EC;
@@ -1942,7 +1942,7 @@
 }
 
 // Part of bstr_wrap_nest_test
-static int DecodeNextNested2(UsefulBufC Wrapped)
+static int32_t DecodeNextNested2(UsefulBufC Wrapped)
 {
    int nReturn;
    QCBORDecodeContext DC;
@@ -2008,7 +2008,7 @@
 }
 
 
-int BstrWrapNestTest()
+int32_t BstrWrapNestTest()
 {
    QCBOREncodeContext EC;
    QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
@@ -2020,24 +2020,24 @@
 
    for(int i = 0; i < BSTR_TEST_DEPTH-2; i++) {
       QCBOREncode_BstrWrap(&EC);
-      QCBOREncode_AddUInt64(&EC, i);
+      QCBOREncode_AddInt64(&EC, i);
    }
 
    for(int i = 0; i < BSTR_TEST_DEPTH-2; i++) {
       QCBOREncode_CloseBstrWrap(&EC, NULL);
-      QCBOREncode_AddUInt64(&EC, i);
+      QCBOREncode_AddInt64(&EC, i);
    }
 
    for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) {
       QCBOREncode_OpenMap(&EC);
       QCBOREncode_BstrWrapInMapN(&EC, i+0x20);
       QCBOREncode_OpenArray(&EC);
-      QCBOREncode_AddUInt64(&EC, i+0x10);
+      QCBOREncode_AddInt64(&EC, i+0x10);
    }
 
    for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) {
       QCBOREncode_CloseArray(&EC);
-      QCBOREncode_AddUInt64(&EC, i+0x30);
+      QCBOREncode_AddInt64(&EC, i+0x30);
       QCBOREncode_CloseBstrWrap(&EC, NULL);
       QCBOREncode_AddSZStringToMapN(&EC, i+0x40, "hello");
       QCBOREncode_CloseMap(&EC);
@@ -2164,7 +2164,7 @@
  be nice as it would make the test really good. That would require
  bring in ECDSA crypto to this test.
  */
-int CoseSign1TBSTest()
+int32_t CoseSign1TBSTest()
 {
    // All of this is from RFC 8152 C.2.1
    const char          *szKid     = "11";
@@ -2230,7 +2230,7 @@
 }
 
 
-int EncodeErrorTests()
+int32_t EncodeErrorTests()
 {
    QCBOREncodeContext EC;
 
@@ -2486,7 +2486,7 @@
 };
 
 
-int ExponentAndMantissaEncodeTests()
+int32_t ExponentAndMantissaEncodeTests()
 {
    QCBOREncodeContext EC;
    UsefulBufC         EncodedExponentAndMantissa;
diff --git a/test/qcbor_encode_tests.h b/test/qcbor_encode_tests.h
index 3d11883..d768889 100644
--- a/test/qcbor_encode_tests.h
+++ b/test/qcbor_encode_tests.h
@@ -33,6 +33,7 @@
 #ifndef __QCBOR__qcbor_encode_tests__
 #define __QCBOR__qcbor_encode_tests__
 
+#include <stdint.h>
 
 /*
  Notes:
@@ -51,7 +52,7 @@
 /*
  Most basic test.
  */
-int BasicEncodeTest(void);
+int32_t BasicEncodeTest(void);
 
 
 /*
@@ -59,28 +60,28 @@
  make sure they Match the expected binary output. Primarily an
  encoding test.
  */
-int IntegerValuesTest1(void);
+int32_t IntegerValuesTest1(void);
 
 
 /*
  Create nested arrays to the max depth allowed and make sure it
  succeeds.  This is an encoding test.
  */
-int ArrayNestingTest1(void);
+int32_t ArrayNestingTest1(void);
 
 
 /*
  Create nested arrays to one more than the meax depth and make sure it
  fails.  This is an encoding test.
  */
-int ArrayNestingTest2(void);
+int32_t ArrayNestingTest2(void);
 
 
 /*
  Encoding test.  Create arrays to max depth and close one extra time
  and look for correct error code
  */
-int ArrayNestingTest3(void);
+int32_t ArrayNestingTest3(void);
 
 
 /*
@@ -88,80 +89,80 @@
  RAWCBOR to an array and comparing with expected values. This is an
  encoding test.
  */
-int EncodeRawTest(void);
+int32_t EncodeRawTest(void);
 
 
 /*
  This creates a somewhat complicated CBOR MAP and verifies it against
  expected data. This is an encoding test.
  */
-int MapEncodeTest(void);
+int32_t MapEncodeTest(void);
 
 
 /*
  Encodes a goodly number of floats and doubles and checks encoding is right
  */
-int FloatValuesTest1(void);
+int32_t FloatValuesTest1(void);
 
 
 /*
  Encodes true, false and the like
  */
-int SimpleValuesTest1(void);
+int32_t SimpleValuesTest1(void);
 
 
 /*
  Encodes basic maps and arrays with indefinite length
  */
-int SimpleValuesIndefiniteLengthTest1(void);
+int32_t SimpleValuesIndefiniteLengthTest1(void);
 
 
 /*
  Indefinite length arrays and maps use the 'magic' number 31, verify
  that everything with length 31 still works properly
  */
-int EncodeLengthThirtyoneTest(void);
+int32_t EncodeLengthThirtyoneTest(void);
 
 
 /*
  Encodes most data formats that are supported */
-int EncodeDateTest(void);
+int32_t EncodeDateTest(void);
 
 
 /*
  Encodes particular data structure that a particular app will need...
  */
-int RTICResultsTest(void);
+int32_t RTICResultsTest(void);
 
 
 /*
  Calls all public encode methods in qcbor.h once.
  */
-int AllAddMethodsTest(void);
+int32_t AllAddMethodsTest(void);
 
 /*
  The binary string wrapping of maps and arrays used by COSE
  */
-int  BstrWrapTest(void);
+int32_t  BstrWrapTest(void);
 
 
 /*
  Test error cases for bstr wrapping encoding such as closing an open
  array with CloseBstrWrap
  */
-int BstrWrapErrorTest(void);
+int32_t BstrWrapErrorTest(void);
 
 
 /*
  Test complicated nested bstr wrapping
  */
-int BstrWrapNestTest(void);
+int32_t BstrWrapNestTest(void);
 
 
 /*
  Test encoding a COSE_Sign1 with bstr wrapping
  */
-int CoseSign1TBSTest(void);
+int32_t CoseSign1TBSTest(void);
 
 
 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
@@ -169,7 +170,7 @@
  Test encoding of decimal fractions and big floats, both of which are
  made up of an exponent and mantissa
  */
-int ExponentAndMantissaEncodeTests(void);
+int32_t ExponentAndMantissaEncodeTests(void);
 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
 
 /*
@@ -177,7 +178,7 @@
  buffer too small, array nesting too deep. Aims to cover the error
  codes returned when encoding CBOR
  */
-int EncodeErrorTests(void);
+int32_t EncodeErrorTests(void);
 
 
 #endif /* defined(__QCBOR__qcbor_encode_tests__) */
diff --git a/test/run_tests.c b/test/run_tests.c
index 5b72398..133103f 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -24,7 +24,7 @@
  Test configuration
  */
 
-typedef int (test_fun_t)(void);
+typedef int32_t (test_fun_t)(void);
 typedef const char * (test_fun2_t)(void);
 
 
@@ -137,12 +137,12 @@
    }
 
    bool bDidSomeOutput = false;
-   for(int n = nMax; n > 0; n/=10) {
-      int x = nNum/n;
-      if(x || bDidSomeOutput){
+   for(int32_t n = nMax; n > 0; n/=10) {
+      int nDigitValue = nNum/n;
+      if(nDigitValue || bDidSomeOutput){
          bDidSomeOutput = true;
-         UsefulOutBuf_AppendByte(&OutBuf, '0' + x);
-         nNum -= x * n;
+         UsefulOutBuf_AppendByte(&OutBuf, (uint8_t)('0' + nDigitValue));
+         nNum -= nDigitValue * n;
       }
    }
    if(!bDidSomeOutput){
@@ -238,7 +238,7 @@
             }
         }
 
-        int nTestResult = (t->test_fun)();
+        int32_t nTestResult = (t->test_fun)();
         nTestsRun++;
         if(pfOutput) {
             (*pfOutput)(t->szTestName, poutCtx, 0);