diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index e23dd0d7..bab76b62 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -266,6 +266,7 @@ json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch op json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | @liveexample{The following code shows how an `out_of_range` exception can be caught.,out_of_range} diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 0a7cf45f..24c08001 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -681,6 +681,11 @@ class binary_writer */ static std::size_t calc_bson_entry_header_size(const typename BasicJsonType::string_t& name) { + if (name.find(static_cast(0)) != BasicJsonType::string_t::npos) + { + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000")); + } + return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index c973f0a0..64b32a7f 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -6617,9 +6617,12 @@ class basic_json @warning The mapping is **incomplete**, since only JSON-objects (and things contained therein) can be serialized to BSON. - Also, integers larger than 9223372036854775807 cannot be serialized to BSON. + Also, integers larger than 9223372036854775807 cannot be serialized to BSON, + and the keys may not contain U+0000, since they are serialized a + zero-terminated c-strings. @throw out_of_range.407 if `j.is_number_unsigned() && j.get() > 9223372036854775807` + @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) @throw type_error.317 if `!j.is_object()` @pre The input `j` is required to be an object: `j.is_object() == true`. diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 87abf2ca..b5aaecf8 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -865,6 +865,7 @@ json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch op json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | @liveexample{The following code shows how an `out_of_range` exception can be caught.,out_of_range} @@ -8530,6 +8531,11 @@ class binary_writer */ static std::size_t calc_bson_entry_header_size(const typename BasicJsonType::string_t& name) { + if (name.find(static_cast(0)) != BasicJsonType::string_t::npos) + { + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000")); + } + return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; } @@ -18203,9 +18209,12 @@ class basic_json @warning The mapping is **incomplete**, since only JSON-objects (and things contained therein) can be serialized to BSON. - Also, integers larger than 9223372036854775807 cannot be serialized to BSON. + Also, integers larger than 9223372036854775807 cannot be serialized to BSON, + and the keys may not contain U+0000, since they are serialized a + zero-terminated c-strings. @throw out_of_range.407 if `j.is_number_unsigned() && j.get() > 9223372036854775807` + @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) @throw type_error.317 if `!j.is_object()` @pre The input `j` is required to be an object: `j.is_object() == true`. diff --git a/test/src/unit-bson.cpp b/test/src/unit-bson.cpp index 58ad71bd..f622ff30 100644 --- a/test/src/unit-bson.cpp +++ b/test/src/unit-bson.cpp @@ -91,6 +91,16 @@ TEST_CASE("BSON") } } + SECTION("keys containing code-point U+0000 cannot be serialized to BSON") + { + json j = + { + { std::string("en\0try", 6), true } + }; + REQUIRE_THROWS_AS(json::to_bson(j), json::out_of_range); + CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.409] BSON key cannot contain code point U+0000"); + } + SECTION("objects") { SECTION("empty object")