Skip to content

Commit

Permalink
Merge pull request #510 from miloyip/issue509_writingnaninf
Browse files Browse the repository at this point in the history
Fix #509 by checking Nan/Inf when writing a double
  • Loading branch information
miloyip committed Jan 20, 2016
2 parents 78c7d54 + bab80e7 commit 8fbe442
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/rapidjson/internal/ieee754.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Double {

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; }

Expand Down
8 changes: 7 additions & 1 deletion include/rapidjson/writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class Writer {
}

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));
Expand Down Expand Up @@ -235,6 +235,9 @@ class Writer {
}

bool WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf())
return false;

char buffer[25];
char* end = internal::dtoa(d, buffer);
for (char* p = buffer; p != end; ++p)
Expand Down Expand Up @@ -381,6 +384,9 @@ inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {

template<>
inline bool Writer<StringBuffer>::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<size_t>(25 - (end - buffer)));
Expand Down
25 changes: 25 additions & 0 deletions test/unittest/writertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(nan));
}

TEST(Writer, Inf) {
double inf = 1.0 / zero;
EXPECT_TRUE(internal::Double(inf).IsInf());
StringBuffer buffer;
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(inf));
}
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(-inf));
}
}

0 comments on commit 8fbe442

Please sign in to comment.