diff --git a/README.md b/README.md index c549ef3eca..76358c2ecb 100644 --- a/README.md +++ b/README.md @@ -383,6 +383,7 @@ I deeply appreciate the help of the following people. - [Aaron Burghardt](https://github.com/aburgh) implemented code to parse streams incrementally. Furthermore, he greatly improved the parser class by allowing the definition of a filter function to discard undesired elements while parsing. - [Daniel Kopeček](https://github.com/dkopecek) fixed a bug in the compilation with GCC 5.0. - [Florian Weber](https://github.com/Florianjw) fixed a bug in and improved the performance of the comparison operators. +- [Eric Cornelius](https://github.com/EricMCornelius) pointed out a bug in the handling with NaN and infinity values. Thanks a lot for helping out! @@ -395,7 +396,7 @@ $ make $ ./json_unit =============================================================================== -All tests passed (4558 assertions in 19 test cases) +All tests passed (4673 assertions in 19 test cases) ``` For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml). diff --git a/src/json.hpp b/src/json.hpp index 74c9d8662d..e2877352b3 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -431,7 +431,14 @@ class basic_json /// create a floating-point number (explicit) inline basic_json(const number_float_t& value) : m_type(value_t::number_float), m_value(value) - {} + { + // replace infinity and NAN by null + if (not std::isfinite(value)) + { + m_type = value_t::null; + m_value = json_value(); + } + } /// create a floating-point number (implicit) template inline basic_json(const T value) noexcept : m_type(value_t::number_float), m_value(number_float_t(value)) - {} + { + // replace infinity and NAN by null + if (not std::isfinite(value)) + { + m_type = value_t::null; + m_value = json_value(); + } + } /// create a container (array or object) from an initializer list inline basic_json(list_init_t init, bool type_deduction = true, diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 8fa2644fb7..282dbdf058 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -431,7 +431,14 @@ class basic_json /// create a floating-point number (explicit) inline basic_json(const number_float_t& value) : m_type(value_t::number_float), m_value(value) - {} + { + // replace infinity and NAN by null + if (not std::isfinite(value)) + { + m_type = value_t::null; + m_value = json_value(); + } + } /// create a floating-point number (implicit) template inline basic_json(const T value) noexcept : m_type(value_t::number_float), m_value(number_float_t(value)) - {} + { + // replace infinity and NAN by null + if (not std::isfinite(value)) + { + m_type = value_t::null; + m_value = json_value(); + } + } /// create a container (array or object) from an initializer list inline basic_json(list_init_t init, bool type_deduction = true, diff --git a/test/unit.cpp b/test/unit.cpp index dbde58be63..ea11c0bdad 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -8450,4 +8450,25 @@ TEST_CASE("regression tests") CHECK(j == R"(["\"foo\""])"_json); } } + + SECTION("issue #70 - Handle infinity and NaN cases") + { + SECTION("NAN value") + { + CHECK(json(NAN) == json()); + } + + SECTION("overflows") + { + CHECK(json(std::exp(800)) == json()); + CHECK(json(HUGE_VALF) == json()); + CHECK(json(HUGE_VAL) == json()); + CHECK(json(HUGE_VALL) == json()); + } + + SECTION("infinity") + { + CHECK(json(INFINITY) == json()); + } + } }