Fix warning about long long conversion to double; this was also a bug that affected a 30 second range of dates 10 billion years in the future or past
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index b25e3bb..36a9d11 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -42,6 +42,7 @@
 
  when               who             what, where, why
  --------           ----            ---------------------------------------------------
+ 11/07/19           llundblade      Fix long long conversion to double compiler warning
  09/07/19           llundblade      Fix bug decoding empty arrays and maps
  07/31/19           llundblade      Decode error fixes for some not-well-formed CBOR
  07/31/19           llundblade      New error code for better end of data handling
@@ -681,13 +682,33 @@
 
       case QCBOR_TYPE_DOUBLE:
          {
+            // This comparison needs to be done as a float before
+            // conversion to an int64_t to be able to detect doubles
+            // that are too large to fit into an int64_t.  A double
+            // has 52 bits of preceision. An int64_t has 63. Casting
+            // INT64_MAX to a double actually causes a round up which
+            // is bad and wrong for the comparison because it will
+            // allow conversion of doubles that can't fit into a
+            // uint64_t.  To remedy this INT64_MAX - 0x7ff is used as
+            // the cutoff point as if that rounds up in conversion to
+            // double it will still be less than INT64_MAX. 0x7ff is
+            // picked because it has 11 bits set.
+            //
+            // INT64_MAX seconds is on the order of 10 billion years,
+            // and the earth is less than 5 billion years old, so for
+            // most uses this conversion error won't occur even though
+            // doubles can go much larger.
+            //
+            // Without the 0x7ff there is a ~30 minute range of time
+            // values 10 billion years in the past and in the future
+            // where this this code would go wrong.
             const double d = pDecodedItem->val.dfnum;
-            if(d > INT64_MAX) {
+            if(d > (double)(INT64_MAX - 0x7ff)) {
                nReturn = QCBOR_ERR_DATE_OVERFLOW;
                goto Done;
             }
-            pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
-            pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
+            pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
+            pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
          }
          break;
 
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 5c8a4a5..7de8c6c 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1976,8 +1976,14 @@
    0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1
 
    0xc1, // tag for epoch date
-   0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large
+   0xfa, 0x7f, 0x7f, 0xff, 0xff, // 3.4028234663852886e+38 too large
 
+   0xc1, // tag for epoch date
+   0xfb, 0x43, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9223372036854775808.000000 just barely too large
+   //0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large
+
+   0xc1, // tag for epoch date
+   0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe // 9223372036854773760 largest supported
 };
 
 
@@ -2052,6 +2058,18 @@
       return -10;
    }
 
+   // Epoch date double that is just slightly too large
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
+      return -11;
+   }
+
+   // Largest double epoch date supported
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
+      Item.val.epochDate.nSeconds != 9223372036854773760 ||
+      Item.val.epochDate.nSeconds == 0) {
+      return -12;
+   }
    // TODO: could use a few more tests with float, double, and half precsion and negative (but coverage is still pretty good)
 
    return 0;