From c10760455b0bcf6b481e02fd17bd8c00a3e1a585 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 11 Oct 2026 14:31:23 +0200 Subject: [PATCH] Move the std::deque array test out of unit-regression3.cpp The range checks added to binary_writer pushed the C++20 build of unit-regression3.cpp past 65535 sections, so the MinGW clang 18 job failed to link it ("relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.rdata'"). Move the regression test for #5476, the only one instantiating a second basic_json specialization with the binary formats, into unit-custom-array-type.cpp, which already tests the same deque_json type. Signed-off-by: Niels Lohmann --- tests/src/unit-custom-array-type.cpp | 46 +++++++++++++++++++++++++++ tests/src/unit-regression3.cpp | 47 ---------------------------- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/tests/src/unit-custom-array-type.cpp b/tests/src/unit-custom-array-type.cpp index 6f015d234..e602b4716 100644 --- a/tests/src/unit-custom-array-type.cpp +++ b/tests/src/unit-custom-array-type.cpp @@ -9,7 +9,9 @@ #include "doctest_compatibility.h" #include +using nlohmann::json; +#include #include #include #include @@ -164,3 +166,47 @@ TEST_CASE("array type without at()") CHECK(j.at(no_at_json::json_pointer("/1")) == 2); CHECK_THROWS_AS(j.at(no_at_json::json_pointer("/3")), no_at_json::out_of_range); } + +TEST_CASE("regression test #5476 - array type without reserve()") +{ + // the capacity reserved for definite-length arrays must not require the + // array type to have a reserve() member function + SECTION("std::deque") + { + const auto j = deque_json::parse(R"({"a":[1,[2,3]],"b":[]})"); + CHECK(j.dump() == R"({"a":[1,[2,3]],"b":[]})"); + + // the binary formats pass a definite length to start_array() + CHECK(deque_json::from_cbor(deque_json::to_cbor(j)) == j); + CHECK(deque_json::from_msgpack(deque_json::to_msgpack(j)) == j); + CHECK(deque_json::from_bon8(deque_json::to_bon8(j)) == j); + + // parse() instantiates the callback parser as well, which reserves too + const auto with_callback = deque_json::parse(R"([1,2,3])", [](int /*depth*/, deque_json::parse_event_t /*event*/, deque_json& /*parsed*/) noexcept + { + return true; + }); + CHECK(with_callback == deque_json({1, 2, 3})); + } + + SECTION("std::vector still reserves") + { + json array = json::array(); + for (int i = 0; i < 100; ++i) + { + array.push_back(i); + } + + const auto j = json::from_cbor(json::to_cbor(array)); + CHECK(j == array); + CHECK(j.get_ref().capacity() >= 100); + } + + SECTION("the reservation stays capped") + { + // CBOR array announcing 2^32-1 elements, but truncated right after the + // header: the input must be rejected without reserving that capacity + const std::vector truncated = {0x9A, 0xFF, 0xFF, 0xFF, 0xFF}; + CHECK(json::from_cbor(truncated, true, false).is_discarded()); + } +} diff --git a/tests/src/unit-regression3.cpp b/tests/src/unit-regression3.cpp index f8d9740fa..d85a33000 100644 --- a/tests/src/unit-regression3.cpp +++ b/tests/src/unit-regression3.cpp @@ -43,7 +43,6 @@ using ordered_json = nlohmann::ordered_json; #endif #include -#include #include #include #include @@ -915,52 +914,6 @@ TEST_CASE("issue #5402 - update(merge_objects=true) overwrites a primitive with } -TEST_CASE("regression test #5476 - array type without reserve()") -{ - // the capacity reserved for definite-length arrays must not require the - // array type to have a reserve() member function - using deque_json = nlohmann::json::with_array_t; - - SECTION("std::deque") - { - const auto j = deque_json::parse(R"({"a":[1,[2,3]],"b":[]})"); - CHECK(j.dump() == R"({"a":[1,[2,3]],"b":[]})"); - - // the binary formats pass a definite length to start_array() - CHECK(deque_json::from_cbor(deque_json::to_cbor(j)) == j); - CHECK(deque_json::from_msgpack(deque_json::to_msgpack(j)) == j); - CHECK(deque_json::from_bon8(deque_json::to_bon8(j)) == j); - - // parse() instantiates the callback parser as well, which reserves too - const auto with_callback = deque_json::parse(R"([1,2,3])", [](int /*depth*/, deque_json::parse_event_t /*event*/, deque_json& /*parsed*/) noexcept - { - return true; - }); - CHECK(with_callback == deque_json({1, 2, 3})); - } - - SECTION("std::vector still reserves") - { - json array = json::array(); - for (int i = 0; i < 100; ++i) - { - array.push_back(i); - } - - const auto j = json::from_cbor(json::to_cbor(array)); - CHECK(j == array); - CHECK(j.get_ref().capacity() >= 100); - } - - SECTION("the reservation stays capped") - { - // CBOR array announcing 2^32-1 elements, but truncated right after the - // header: the input must be rejected without reserving that capacity - const std::vector truncated = {0x9A, 0xFF, 0xFF, 0xFF, 0xFF}; - CHECK(json::from_cbor(truncated, true, false).is_discarded()); - } -} - TEST_CASE("issue #5317 - nested indefinite-length CBOR string chunks are rejected") { json _;