From 935e2ef7ed190e87c7b45d0fc2a7315839f6b36f Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Wed, 20 Jan 2016 22:30:15 +0800 Subject: [PATCH] Merge pull request #510 from miloyip/issue509_writingnaninf Fix #509 by checking Nan/Inf when writing a double --- include/rapidjson/internal/ieee754.h | 1 + include/rapidjson/writer.h | 8 +++++++- test/unittest/writertest.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index 6890f89..82bb0b9 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -40,6 +40,7 @@ public: bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index ffb6cb5..4f42b9e 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -139,7 +139,7 @@ public: } bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } - + bool EndObject(SizeType memberCount = 0) { (void)memberCount; RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); @@ -242,6 +242,9 @@ protected: } bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) + return false; + char buffer[25]; char* end = internal::dtoa(d, buffer); PutReserve(*os_, static_cast(end - buffer)); @@ -394,6 +397,9 @@ inline bool Writer::WriteUint64(uint64_t u) { template<> inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) + return false; + char *buffer = os_->Push(25); char* end = internal::dtoa(d, buffer); os_->Pop(static_cast(25 - (end - buffer))); diff --git a/test/unittest/writertest.cpp b/test/unittest/writertest.cpp index 2adb551..197411c 100644 --- a/test/unittest/writertest.cpp +++ b/test/unittest/writertest.cpp @@ -375,3 +375,28 @@ TEST(Writer, InvalidEventSequence) { EXPECT_FALSE(writer.IsComplete()); } } + +extern double zero; // clang -Wmissing-variable-declarations +double zero = 0.0; // Use global variable to prevent compiler warning + +TEST(Writer, NaN) { + double nan = zero / zero; + EXPECT_TRUE(internal::Double(nan).IsNan()); + StringBuffer buffer; + Writer writer(buffer); + EXPECT_FALSE(writer.Double(nan)); +} + +TEST(Writer, Inf) { + double inf = 1.0 / zero; + EXPECT_TRUE(internal::Double(inf).IsInf()); + StringBuffer buffer; + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(inf)); + } + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(-inf)); + } +}