Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/miloyip/rapidjson.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Fidler <efidler@topologyinc.com>2016-05-31 20:46:04 +0300
committerEli Fidler <efidler@topologyinc.com>2016-06-14 17:01:41 +0300
commitc52cec7e518feb30ec01bc0a978b620f8d9462ab (patch)
tree885f7cc533cff36bae5018cb29eb138416db25b6
parent05f0592b34cb943e7c96b8767d716431a3d9eaef (diff)
fix undefined double to uint64_t cast
note that std::numeric_limits<uint64_t>::max() and std::numeric_limits<int64_t>::max() aren't exactly representable in a double, so we need to be strictly less to be definitely lossless UBSAN gave during Value.IsLosslessDouble test: include/rapidjson/document.h:955:42: runtime error: value 1.84467e+19 is outside the range of representable values of type 'unsigned long'
-rw-r--r--include/rapidjson/document.h9
-rw-r--r--test/unittest/valuetest.cpp16
2 files changed, 21 insertions, 4 deletions
diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h
index d286eb1e..f1857f5c 100644
--- a/include/rapidjson/document.h
+++ b/include/rapidjson/document.h
@@ -23,6 +23,7 @@
#include "memorystream.h"
#include "encodedstream.h"
#include <new> // placement new
+#include <limits>
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
@@ -952,12 +953,16 @@ public:
if (IsUint64()) {
uint64_t u = GetUint64();
volatile double d = static_cast<double>(u);
- return static_cast<uint64_t>(d) == u;
+ return (d >= 0.0)
+ && (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
+ && (u == static_cast<uint64_t>(d));
}
if (IsInt64()) {
int64_t i = GetInt64();
volatile double d = static_cast<double>(i);
- return static_cast< int64_t>(d) == i;
+ return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
+ && (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
+ && (i == static_cast<int64_t>(d));
}
return true; // double, int, uint are always lossless
}
diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp
index 430a828a..fefc001d 100644
--- a/test/unittest/valuetest.cpp
+++ b/test/unittest/valuetest.cpp
@@ -673,6 +673,7 @@ TEST(Value, Float) {
}
TEST(Value, IsLosslessDouble) {
+ EXPECT_TRUE(Value(0.0).IsLosslessDouble());
EXPECT_TRUE(Value(12.34).IsLosslessDouble());
EXPECT_TRUE(Value(-123).IsLosslessDouble());
EXPECT_TRUE(Value(2147483648u).IsLosslessDouble());
@@ -681,8 +682,19 @@ TEST(Value, IsLosslessDouble) {
EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDouble());
#endif
- EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble());
- EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble());
+ EXPECT_FALSE(Value(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); // INT64_MAX
+ EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); // -INT64_MAX
+ EXPECT_TRUE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF)) - 1).IsLosslessDouble()); // INT64_MIN
+ EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble()); // UINT64_MAX
+
+ EXPECT_TRUE(Value(3.4028234e38f).IsLosslessDouble()); // FLT_MAX
+ EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessDouble()); // -FLT_MAX
+ EXPECT_TRUE(Value(1.17549435e-38f).IsLosslessDouble()); // FLT_MIN
+ EXPECT_TRUE(Value(-1.17549435e-38f).IsLosslessDouble()); // -FLT_MIN
+ EXPECT_TRUE(Value(1.7976931348623157e+308).IsLosslessDouble()); // DBL_MAX
+ EXPECT_TRUE(Value(-1.7976931348623157e+308).IsLosslessDouble()); // -DBL_MAX
+ EXPECT_TRUE(Value(2.2250738585072014e-308).IsLosslessDouble()); // DBL_MIN
+ EXPECT_TRUE(Value(-2.2250738585072014e-308).IsLosslessDouble()); // -DBL_MIN
}
TEST(Value, IsLosslessFloat) {