Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions xson/xson-json-decoder.test.c++
Original file line number Diff line number Diff line change
Expand Up @@ -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})";
Expand Down
24 changes: 22 additions & 2 deletions xson/xson-json.c++m
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,11 @@ private:
if(std::isdigit(c))
{
m_number = m_number * 10.0 + static_cast<xson::number_type>(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 == '.')
{
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
Loading