diff --git a/docs/mkdocs/docs/api/basic_json/from_bjdata.md b/docs/mkdocs/docs/api/basic_json/from_bjdata.md index 9df21ab30..f86345091 100644 --- a/docs/mkdocs/docs/api/basic_json/from_bjdata.md +++ b/docs/mkdocs/docs/api/basic_json/from_bjdata.md @@ -111,3 +111,12 @@ Linear in the size of the input. - Added in version 3.11.0. - Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0. - Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0. + +!!! warning "Deprecation" + + - Overload (2) replaces calls to `from_bjdata` with a pointer and a length as first two parameters, which has been + deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like + `#!cpp from_bjdata(ptr, len, ...);` with `#!cpp from_bjdata(ptr, ptr+len, ...);`. + + You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated + function. diff --git a/docs/mkdocs/docs/api/basic_json/from_bon8.md b/docs/mkdocs/docs/api/basic_json/from_bon8.md index 2f9d1e749..cac6b31eb 100644 --- a/docs/mkdocs/docs/api/basic_json/from_bon8.md +++ b/docs/mkdocs/docs/api/basic_json/from_bon8.md @@ -106,3 +106,12 @@ Linear in the size of the input. ## Version history - Added in version 3.13.0. + +!!! warning "Deprecation" + + - Overload (2) replaces calls to `from_bon8` with a pointer and a length as first two parameters, which has been + deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like + `#!cpp from_bon8(ptr, len, ...);` with `#!cpp from_bon8(ptr, ptr+len, ...);`. + + You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated + function. diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 500fcddf2..c4295e7cb 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -5547,6 +5547,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bjdata(ptr, ptr + len)) + static basic_json from_bjdata(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bjdata(ptr, ptr + len, strict, allow_exceptions); + } + /// @brief create a JSON value from an input in BON8 format /// @sa https://json.nlohmann.me/api/basic_json/from_bon8/ template @@ -5584,6 +5594,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bon8(ptr, ptr + len)) + static basic_json from_bon8(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bon8(ptr, ptr + len, strict, allow_exceptions); + } + /// @brief create a JSON value from an input in BSON format /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ template diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 576498738..66e08b36d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -31628,6 +31628,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bjdata(ptr, ptr + len)) + static basic_json from_bjdata(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bjdata(ptr, ptr + len, strict, allow_exceptions); + } + /// @brief create a JSON value from an input in BON8 format /// @sa https://json.nlohmann.me/api/basic_json/from_bon8/ template @@ -31665,6 +31675,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bon8(ptr, ptr + len)) + static basic_json from_bon8(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bon8(ptr, ptr + len, strict, allow_exceptions); + } + /// @brief create a JSON value from an input in BSON format /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ template diff --git a/tests/src/unit-bjdata.cpp b/tests/src/unit-bjdata.cpp index a58507c15..ca6cdaafa 100644 --- a/tests/src/unit-bjdata.cpp +++ b/tests/src/unit-bjdata.cpp @@ -4572,3 +4572,31 @@ TEST_CASE("BJData roundtrips" * doctest::skip()) } } } + +TEST_CASE("issue #5648 - from_bjdata(ptr, len) must read len bytes, not treat ptr as a C string") +{ + // to_bjdata() encodes the integer 0 as the two bytes 'i' 0x00 (a BJData + // type marker followed by the value byte 0x00), so the packed data + // below contains a 0x00 byte before its end. + const json j = {{"a", 0}}; + const std::vector packed = json::to_bjdata(j); + bool contains_nul = false; + for (const auto byte : packed) + { + contains_nul |= (byte == 0x00); + } + REQUIRE(contains_nul); + + // before the fix, from_bjdata had no (ptr, len) overload, so this call + // bound to from_bjdata(InputType&&, bool strict) instead: ptr was read + // as a NUL-terminated C string (stopping at the embedded 0x00 byte), and + // len was silently converted to the strict flag. The deprecated + // overload added for this issue forwards to from_bjdata(ptr, ptr + len, + // ...) instead, like from_ubjson's deprecated (ptr, len) overload does. + json result; + CHECK_NOTHROW(result = json::from_bjdata(packed.data(), packed.size())); + CHECK(result == j); + + // len must not collapse into the strict flag either + CHECK(json::from_bjdata(packed.data(), packed.size(), false) == j); +} diff --git a/tests/src/unit-bon8.cpp b/tests/src/unit-bon8.cpp index 030e1d5c3..1574ff060 100644 --- a/tests/src/unit-bon8.cpp +++ b/tests/src/unit-bon8.cpp @@ -1010,6 +1010,34 @@ TEST_CASE("BON8 roundtrips" * doctest::skip()) } } +TEST_CASE("issue #5648 - from_bon8(ptr, len) must read len bytes, not treat ptr as a C string") +{ + // to_bon8() encodes the integer 40 as the two bytes 0xC2 0x00 (a BON8 + // lead byte followed by a continuation byte of 0x00), so the packed data + // below contains a 0x00 byte before its end. + const json j = {{"a", 40}, {"b", "x"}}; + const std::vector packed = json::to_bon8(j); + bool contains_nul = false; + for (const auto byte : packed) + { + contains_nul |= (byte == 0x00); + } + REQUIRE(contains_nul); + + // before the fix, from_bon8 had no (ptr, len) overload, so this call + // bound to from_bon8(InputType&&, bool strict) instead: ptr was read as + // a NUL-terminated C string (stopping at the embedded 0x00 byte), and + // len was silently converted to the strict flag. The deprecated + // overload added for this issue forwards to from_bon8(ptr, ptr + len, + // ...) instead, like from_cbor's deprecated (ptr, len) overload does. + json result; + CHECK_NOTHROW(result = json::from_bon8(packed.data(), packed.size())); + CHECK(result == j); + + // len must not collapse into the strict flag either + CHECK(json::from_bon8(packed.data(), packed.size(), false) == j); +} + #ifdef JSON_HAS_CPP_17 TEST_CASE("BON8 with std::byte") {