diff --git a/xson/xson-json-decoder.test.c++ b/xson/xson-json-decoder.test.c++ index bb0b7fb..2446dee 100644 --- a/xson/xson-json-decoder.test.c++ +++ b/xson/xson-json-decoder.test.c++ @@ -41,6 +41,16 @@ auto register_tests() require_false(ob["huge_num"s].is_integer()); }; + // Digit-only magnitudes beyond ~1e308 overflow double to ±inf in integer_overflow. + // Scientific notation already rejected non-finite results; the plain digit path must too + // (otherwise parse accepts Inf and stringify can emit non-JSON). + test_case("DigitOverflowToInfinityRejected, [xson]") = [] { + const auto huge = "1"s + std::string(400, '0'); + require_throws([&]{ (void)json::parse(huge); }); + require_throws([&]{ (void)json::parse("-"s + huge); }); + require_throws([&]{ (void)json::parse(huge + ".5"); }); + }; + test_case("SmallIntegerRemainsInt, [xson]") = [] { // Test that small integers remain as integers auto json_str = R"({"small": 42, "zero": 0, "negative": -123})"; diff --git a/xson/xson-json.c++m b/xson/xson-json.c++m index 6d28ae6..c738742 100644 --- a/xson/xson-json.c++m +++ b/xson/xson-json.c++m @@ -663,6 +663,11 @@ private: if(std::isdigit(c)) { m_number = m_number * 10.0 + static_cast(c - '0'); + // ~310+ digits overflow double to ±inf; reject like the scientific-notation path. + if(!std::isfinite(m_number)) + { + throw std::runtime_error{"JSON parse error: number is not finite (infinity or NaN)"s}; + } } else if(c == '.') { @@ -689,6 +694,10 @@ private: } const xson::number_type final_value = Sign * m_number; + if(!std::isfinite(final_value)) + { + throw std::runtime_error{"JSON parse error: number is not finite (infinity or NaN)"s}; + } m_builder.value(final_value); m_number = 0; m_integer = 0; @@ -722,7 +731,13 @@ private: { if(c == '\0') { - m_builder.value(Sign * m_number); + const xson::number_type final_value = Sign * m_number; + // Integer-overflow → fraction can carry ±inf into this state. + if(!std::isfinite(final_value)) + { + throw std::runtime_error{"JSON parse error: number is not finite (infinity or NaN)"s}; + } + m_builder.value(final_value); m_number = 0; m_place = 1; m_state_machine.pop(); @@ -751,7 +766,12 @@ private: throw std::runtime_error{"JSON parse error: unexpected character in number: '"s + c + "'"s}; } - m_builder.value(Sign * m_number); + const xson::number_type final_value = Sign * m_number; + if(!std::isfinite(final_value)) + { + throw std::runtime_error{"JSON parse error: number is not finite (infinity or NaN)"s}; + } + m_builder.value(final_value); m_number = 0; m_place = 1; m_state_machine.pop();