From 6a81cf336887bd0e6bff33fe2b2ceda2c2e9174e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 6 Sep 2026 13:26:25 +0200 Subject: [PATCH] Move the new binary-subtype regression test out of unit-regression2.cpp unit-regression2.cpp is already at the edge of what the MinGW linker can relocate; adding this test's ~26 lines tips test-regression2_cpp20 (clang, Windows) over into "relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.rdata'" (see 8ce64b9c1 / b82717c8a for the same failure mode). Split the test along format lines instead: MessagePack assertions move to unit-msgpack.cpp, BSON assertions to unit-bson.cpp. The CBOR round-trip guard is dropped as redundant -- unit-cbor.cpp's "Tagged values" section already round-trips subtypes up to 8589934590, far past the 70000 checked here. Signed-off-by: Niels Lohmann --- tests/src/unit-bson.cpp | 9 +++++++++ tests/src/unit-msgpack.cpp | 15 +++++++++++++++ tests/src/unit-regression2.cpp | 26 -------------------------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/tests/src/unit-bson.cpp b/tests/src/unit-bson.cpp index 7896b9f18..366d9c83e 100644 --- a/tests/src/unit-bson.cpp +++ b/tests/src/unit-bson.cpp @@ -652,6 +652,15 @@ TEST_CASE("BSON") } } +TEST_CASE("regression test - BSON binary subtype rejects a value that doesn't fit a single byte") +{ + json const doc255 = {{"b", json::binary({1, 2}, 255)}}; + CHECK(json::from_bson(json::to_bson(doc255))["b"].get_binary().subtype() == 255); + + CHECK_THROWS_AS(json::to_bson(json{{"b", json::binary({1, 2}, 256)}}), json::out_of_range); + CHECK_THROWS_WITH_AS(json::to_bson(json{{"b", json::binary({1, 2}, 300)}}), "[json.exception.out_of_range.413] subtype 300 is too large for the BSON binary subtype (max 255)", json::out_of_range); +} + TEST_CASE("BSON input/output_adapters") { const json json_representation = diff --git a/tests/src/unit-msgpack.cpp b/tests/src/unit-msgpack.cpp index 4358cd464..00f6c3a6a 100644 --- a/tests/src/unit-msgpack.cpp +++ b/tests/src/unit-msgpack.cpp @@ -1597,6 +1597,21 @@ TEST_CASE("MessagePack") } } +TEST_CASE("regression test - MessagePack ext type rejects a subtype that doesn't fit a single byte") +{ + // subtype 0-255 must still round-trip correctly (regression guard, pre-existing behavior) + CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}, 0))).get_binary().subtype() == 0); + CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}, 200))).get_binary().subtype() == 200); + CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}, 255))).get_binary().subtype() == 255); + + // a subtype > 255 must throw instead of silently truncating + CHECK_THROWS_AS(json::to_msgpack(json::binary({1, 2}, 256)), json::out_of_range); + CHECK_THROWS_WITH_AS(json::to_msgpack(json::binary({1, 2}, 70000)), "[json.exception.out_of_range.413] subtype 70000 is too large for the MessagePack ext type (max 255)", json::out_of_range); + + // a binary value with no subtype at all must be unaffected + CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}))).get_binary().has_subtype() == false); +} + // use this testcase outside [hide] to run it with Valgrind TEST_CASE("single MessagePack roundtrip") { diff --git a/tests/src/unit-regression2.cpp b/tests/src/unit-regression2.cpp index 1d296c6ff..6bec0ad3a 100644 --- a/tests/src/unit-regression2.cpp +++ b/tests/src/unit-regression2.cpp @@ -1668,30 +1668,4 @@ TEST_CASE("regression test - excessive binary container size honors allow_except CHECK(json::from_cbor(std::vector {0x9b, 0, 0, 0, 0, 0, 0, 0, 0x02}, true, false).is_discarded()); } -TEST_CASE("regression test - MessagePack/BSON writers reject binary subtypes that don't fit their wire format") -{ - // MessagePack: subtype 0-255 must still round-trip correctly (regression guard, pre-existing behavior) - CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}, 0))).get_binary().subtype() == 0); - CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}, 200))).get_binary().subtype() == 200); - CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}, 255))).get_binary().subtype() == 255); - - // MessagePack: subtype > 255 must now throw instead of silently truncating - CHECK_THROWS_AS(json::to_msgpack(json::binary({1, 2}, 256)), json::out_of_range); - CHECK_THROWS_AS(json::to_msgpack(json::binary({1, 2}, 70000)), json::out_of_range); - CHECK_THROWS_WITH_AS(json::to_msgpack(json::binary({1, 2}, 70000)), "[json.exception.out_of_range.413] subtype 70000 is too large for the MessagePack ext type (max 255)", json::out_of_range); - - // BSON: same pattern - json doc255 = {{"b", json::binary({1, 2}, 255)}}; - CHECK(json::from_bson(json::to_bson(doc255))["b"].get_binary().subtype() == 255); - CHECK_THROWS_AS(json::to_bson(json{{"b", json::binary({1, 2}, 256)}}), json::out_of_range); - CHECK_THROWS_AS(json::to_bson(json{{"b", json::binary({1, 2}, 300)}}), json::out_of_range); - CHECK_THROWS_WITH_AS(json::to_bson(json{{"b", json::binary({1, 2}, 300)}}), "[json.exception.out_of_range.413] subtype 300 is too large for the BSON binary subtype (max 255)", json::out_of_range); - - // CBOR must remain unaffected (full 64-bit subtype range already supported correctly) - regression guard - CHECK(json::from_cbor(json::to_cbor(json::binary({1, 2}, 70000)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 70000); - - // a binary value with NO subtype at all must be completely unaffected by this change - CHECK(json::from_msgpack(json::to_msgpack(json::binary({1, 2}))).get_binary().has_subtype() == false); -} - DOCTEST_CLANG_SUPPRESS_WARNING_POP