From 12fc0a36728eff286bd29c29a8b57e094be72f3b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 15:01:17 +0200 Subject: [PATCH] Test the overflow check of json_view at the largest double Numbers of more than 19 digits at the boundary of the largest double are decided by the exact comparison with the midpoint in the overflow check. The check uses the floating-point type of the document: with float, the view rejects what parse() rejects (1e39, 3.4028236e38, the midpoint between the largest float and 2^128), and double documents are not affected. Signed-off-by: Niels Lohmann --- tests/src/unit-json_view_builder.cpp | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/src/unit-json_view_builder.cpp b/tests/src/unit-json_view_builder.cpp index e589834bd..2289214f0 100644 --- a/tests/src/unit-json_view_builder.cpp +++ b/tests/src/unit-json_view_builder.cpp @@ -14,6 +14,7 @@ using nlohmann::json; #include #include +#include #include #include #include @@ -228,6 +229,48 @@ TEST_CASE("json_view builder") { check_same(text); } + + // the midpoint between the largest double and 2^1024 rounds to + // infinity (an overflow), one less to the largest double: with more + // than 19 digits, Eisel-Lemire cannot decide these, and the overflow + // check needs the exact comparison with the midpoint + const std::string midpoint = "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792"; + const std::string below = "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791"; + check_same(midpoint); + check_same("-" + midpoint); + check_same(below); + check_same("[" + below + "," + midpoint + "]"); + + // the check uses the floating-point type of the document: with float, + // the view rejects what parse() rejects (out_of_range.406), and a + // double document is not affected + using float_json = nlohmann::basic_json; + CHECK_FALSE(float_json::accept("1e39")); + CHECK(float_json::accept("3.4028235e38")); + CHECK_FALSE(float_json::accept("3.4028236e38")); + for (const char* text : + { + "1e39", "-1e39", "3.4028235e38", "-3.4028235e38", "3.4028236e38", "-3.4028236e38", "3.4028234663852886e38", "1e38", + "340282356779733661637539395458142568448", "340282356779733661637539395458142568447.99", "0.00034028236e42", + "[1.5e38, 3.5e38]", "{\"a\": 1e-50, \"b\": 1e39}" + }) + { + CAPTURE(text); + const bool float_accepted = float_json::accept(text); + for (const bool sentinel : + { + true, false + }) + { + const built f = build(text, false, false, sentinel); + CHECK(f.ok == float_accepted); + if (!f.ok) + { + CHECK(f.failure.code == nlohmann::detail::view::error_code::number_overflow); + } + CHECK(build(text, false, false, sentinel).ok == json::accept(text)); + } + } } SECTION("malformed input")