mirror of
https://github.com/nlohmann/json.git
synced 2026-09-07 16:57:59 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32349b379b |
@@ -996,21 +996,23 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief reads a definite-length CBOR string
|
@brief reads a CBOR string
|
||||||
|
|
||||||
Reads everything @ref get_cbor_string accepts except the indefinite-length
|
This function first reads starting bytes to determine the expected
|
||||||
form, which that function handles itself. The bytes are appended to @a
|
string length and then copies this number of bytes into a string.
|
||||||
result, so consecutive chunks of an indefinite-length string can be read
|
Additionally, CBOR's strings with indefinite lengths are supported.
|
||||||
into the same string.
|
|
||||||
|
|
||||||
@param[out] result string the bytes are appended to
|
@param[out] result created string
|
||||||
|
|
||||||
@return whether string creation completed
|
@return whether string creation completed
|
||||||
|
|
||||||
@pre @a current is not EOF
|
|
||||||
*/
|
*/
|
||||||
bool get_cbor_string_chunk(string_t& result)
|
bool get_cbor_string(string_t& result)
|
||||||
{
|
{
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
// UTF-8 string (0x00..0x17 bytes follow)
|
// UTF-8 string (0x00..0x17 bytes follow)
|
||||||
@@ -1066,6 +1068,20 @@ class binary_reader
|
|||||||
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
|
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x7F: // UTF-8 string (indefinite length)
|
||||||
|
{
|
||||||
|
while (get() != 0xFF)
|
||||||
|
{
|
||||||
|
string_t chunk;
|
||||||
|
if (!get_cbor_string(chunk))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result.append(chunk);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
auto last_token = get_token_string();
|
auto last_token = get_token_string();
|
||||||
@@ -1076,82 +1092,23 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief reads a CBOR string
|
@brief reads a CBOR byte array
|
||||||
|
|
||||||
This function first reads starting bytes to determine the expected
|
This function first reads starting bytes to determine the expected
|
||||||
string length and then copies this number of bytes into a string.
|
byte array length and then copies this number of bytes into the byte array.
|
||||||
Additionally, CBOR's strings with indefinite lengths are supported.
|
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
||||||
|
|
||||||
@param[out] result created string
|
@param[out] result created byte array
|
||||||
|
|
||||||
@return whether string creation completed
|
|
||||||
*/
|
|
||||||
bool get_cbor_string(string_t& result)
|
|
||||||
{
|
|
||||||
// number of indefinite-length strings that have been opened and not
|
|
||||||
// closed yet. RFC 8949, Section 3.2.3 does not permit nesting them,
|
|
||||||
// but this reader has always accepted it, so the open levels are
|
|
||||||
// counted instead of recursed through, which overflowed the stack for
|
|
||||||
// an input of repeated 0x7F bytes (see #5104). Every chunk is appended
|
|
||||||
// to the same result, so no per-level state is needed.
|
|
||||||
std::size_t open = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == 0x7F) // UTF-8 string (indefinite length)
|
|
||||||
{
|
|
||||||
++open;
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a break marker closes the innermost indefinite-length string;
|
|
||||||
// outside of one it is not a string and falls through to the error
|
|
||||||
if (open != 0 && current == 0xFF)
|
|
||||||
{
|
|
||||||
if (--open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string_chunk(result)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reads a definite-length CBOR byte array
|
|
||||||
|
|
||||||
Reads everything @ref get_cbor_binary accepts except the indefinite-length
|
|
||||||
form, which that function handles itself. The bytes are appended to @a
|
|
||||||
result, so consecutive chunks of an indefinite-length byte array can be
|
|
||||||
read into the same byte array.
|
|
||||||
|
|
||||||
@param[out] result byte array the bytes are appended to
|
|
||||||
|
|
||||||
@return whether byte array creation completed
|
@return whether byte array creation completed
|
||||||
|
|
||||||
@pre @a current is not EOF
|
|
||||||
*/
|
*/
|
||||||
bool get_cbor_binary_chunk(binary_t& result)
|
bool get_cbor_binary(binary_t& result)
|
||||||
{
|
{
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
// Binary data (0x00..0x17 bytes follow)
|
// Binary data (0x00..0x17 bytes follow)
|
||||||
@@ -1211,6 +1168,20 @@ class binary_reader
|
|||||||
get_binary(input_format_t::cbor, len, result);
|
get_binary(input_format_t::cbor, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x5F: // Binary data (indefinite length)
|
||||||
|
{
|
||||||
|
while (get() != 0xFF)
|
||||||
|
{
|
||||||
|
binary_t chunk;
|
||||||
|
if (!get_cbor_binary(chunk))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result.insert(result.end(), chunk.begin(), chunk.end());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
auto last_token = get_token_string();
|
auto last_token = get_token_string();
|
||||||
@@ -1220,63 +1191,6 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reads a CBOR byte array
|
|
||||||
|
|
||||||
This function first reads starting bytes to determine the expected
|
|
||||||
byte array length and then copies this number of bytes into the byte array.
|
|
||||||
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
|
||||||
|
|
||||||
@param[out] result created byte array
|
|
||||||
|
|
||||||
@return whether byte array creation completed
|
|
||||||
*/
|
|
||||||
bool get_cbor_binary(binary_t& result)
|
|
||||||
{
|
|
||||||
// the open indefinite-length byte arrays are counted rather than
|
|
||||||
// recursed through, for the reason given in @ref get_cbor_string
|
|
||||||
std::size_t open = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == 0x5F) // Binary data (indefinite length)
|
|
||||||
{
|
|
||||||
++open;
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a break marker closes the innermost indefinite-length byte
|
|
||||||
// array; outside of one it falls through to the error below
|
|
||||||
if (open != 0 && current == 0xFF)
|
|
||||||
{
|
|
||||||
if (--open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_binary_chunk(result)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief narrow a definite CBOR array/map length to std::size_t
|
@brief narrow a definite CBOR array/map length to std::size_t
|
||||||
|
|
||||||
|
|||||||
@@ -748,6 +748,20 @@ class json_pointer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the reference token consists only of digits at this point (cf. checks
|
||||||
|
// above); however, its numeric value might not be representable, in which
|
||||||
|
// case array_index() would throw out_of_range.404/410 -- contains() must
|
||||||
|
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||||
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
|
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||||
|
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
|
{
|
||||||
|
// the array index cannot be represented as size_type
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto idx = array_index<BasicJsonType>(reference_token);
|
const auto idx = array_index<BasicJsonType>(reference_token);
|
||||||
if (idx >= ptr->size())
|
if (idx >= ptr->size())
|
||||||
{
|
{
|
||||||
|
|||||||
+28
-70
@@ -4473,11 +4473,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -4493,11 +4490,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -4522,11 +4516,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in MessagePack format
|
/// @brief create a JSON value from an input in MessagePack format
|
||||||
@@ -4540,11 +4531,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -4559,11 +4547,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -4586,11 +4571,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in UBJSON format
|
/// @brief create a JSON value from an input in UBJSON format
|
||||||
@@ -4604,11 +4586,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -4623,11 +4602,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -4650,11 +4626,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BJData format
|
/// @brief create a JSON value from an input in BJData format
|
||||||
@@ -4668,11 +4641,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -4687,11 +4657,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BSON format
|
/// @brief create a JSON value from an input in BSON format
|
||||||
@@ -4705,11 +4672,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -4724,11 +4688,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -4751,11 +4712,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
@@ -11683,21 +11683,23 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief reads a definite-length CBOR string
|
@brief reads a CBOR string
|
||||||
|
|
||||||
Reads everything @ref get_cbor_string accepts except the indefinite-length
|
This function first reads starting bytes to determine the expected
|
||||||
form, which that function handles itself. The bytes are appended to @a
|
string length and then copies this number of bytes into a string.
|
||||||
result, so consecutive chunks of an indefinite-length string can be read
|
Additionally, CBOR's strings with indefinite lengths are supported.
|
||||||
into the same string.
|
|
||||||
|
|
||||||
@param[out] result string the bytes are appended to
|
@param[out] result created string
|
||||||
|
|
||||||
@return whether string creation completed
|
@return whether string creation completed
|
||||||
|
|
||||||
@pre @a current is not EOF
|
|
||||||
*/
|
*/
|
||||||
bool get_cbor_string_chunk(string_t& result)
|
bool get_cbor_string(string_t& result)
|
||||||
{
|
{
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
// UTF-8 string (0x00..0x17 bytes follow)
|
// UTF-8 string (0x00..0x17 bytes follow)
|
||||||
@@ -11753,6 +11755,20 @@ class binary_reader
|
|||||||
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
|
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x7F: // UTF-8 string (indefinite length)
|
||||||
|
{
|
||||||
|
while (get() != 0xFF)
|
||||||
|
{
|
||||||
|
string_t chunk;
|
||||||
|
if (!get_cbor_string(chunk))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result.append(chunk);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
auto last_token = get_token_string();
|
auto last_token = get_token_string();
|
||||||
@@ -11763,82 +11779,23 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief reads a CBOR string
|
@brief reads a CBOR byte array
|
||||||
|
|
||||||
This function first reads starting bytes to determine the expected
|
This function first reads starting bytes to determine the expected
|
||||||
string length and then copies this number of bytes into a string.
|
byte array length and then copies this number of bytes into the byte array.
|
||||||
Additionally, CBOR's strings with indefinite lengths are supported.
|
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
||||||
|
|
||||||
@param[out] result created string
|
@param[out] result created byte array
|
||||||
|
|
||||||
@return whether string creation completed
|
|
||||||
*/
|
|
||||||
bool get_cbor_string(string_t& result)
|
|
||||||
{
|
|
||||||
// number of indefinite-length strings that have been opened and not
|
|
||||||
// closed yet. RFC 8949, Section 3.2.3 does not permit nesting them,
|
|
||||||
// but this reader has always accepted it, so the open levels are
|
|
||||||
// counted instead of recursed through, which overflowed the stack for
|
|
||||||
// an input of repeated 0x7F bytes (see #5104). Every chunk is appended
|
|
||||||
// to the same result, so no per-level state is needed.
|
|
||||||
std::size_t open = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == 0x7F) // UTF-8 string (indefinite length)
|
|
||||||
{
|
|
||||||
++open;
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a break marker closes the innermost indefinite-length string;
|
|
||||||
// outside of one it is not a string and falls through to the error
|
|
||||||
if (open != 0 && current == 0xFF)
|
|
||||||
{
|
|
||||||
if (--open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string_chunk(result)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reads a definite-length CBOR byte array
|
|
||||||
|
|
||||||
Reads everything @ref get_cbor_binary accepts except the indefinite-length
|
|
||||||
form, which that function handles itself. The bytes are appended to @a
|
|
||||||
result, so consecutive chunks of an indefinite-length byte array can be
|
|
||||||
read into the same byte array.
|
|
||||||
|
|
||||||
@param[out] result byte array the bytes are appended to
|
|
||||||
|
|
||||||
@return whether byte array creation completed
|
@return whether byte array creation completed
|
||||||
|
|
||||||
@pre @a current is not EOF
|
|
||||||
*/
|
*/
|
||||||
bool get_cbor_binary_chunk(binary_t& result)
|
bool get_cbor_binary(binary_t& result)
|
||||||
{
|
{
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
// Binary data (0x00..0x17 bytes follow)
|
// Binary data (0x00..0x17 bytes follow)
|
||||||
@@ -11898,6 +11855,20 @@ class binary_reader
|
|||||||
get_binary(input_format_t::cbor, len, result);
|
get_binary(input_format_t::cbor, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x5F: // Binary data (indefinite length)
|
||||||
|
{
|
||||||
|
while (get() != 0xFF)
|
||||||
|
{
|
||||||
|
binary_t chunk;
|
||||||
|
if (!get_cbor_binary(chunk))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result.insert(result.end(), chunk.begin(), chunk.end());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
auto last_token = get_token_string();
|
auto last_token = get_token_string();
|
||||||
@@ -11907,63 +11878,6 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reads a CBOR byte array
|
|
||||||
|
|
||||||
This function first reads starting bytes to determine the expected
|
|
||||||
byte array length and then copies this number of bytes into the byte array.
|
|
||||||
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
|
||||||
|
|
||||||
@param[out] result created byte array
|
|
||||||
|
|
||||||
@return whether byte array creation completed
|
|
||||||
*/
|
|
||||||
bool get_cbor_binary(binary_t& result)
|
|
||||||
{
|
|
||||||
// the open indefinite-length byte arrays are counted rather than
|
|
||||||
// recursed through, for the reason given in @ref get_cbor_string
|
|
||||||
std::size_t open = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == 0x5F) // Binary data (indefinite length)
|
|
||||||
{
|
|
||||||
++open;
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a break marker closes the innermost indefinite-length byte
|
|
||||||
// array; outside of one it falls through to the error below
|
|
||||||
if (open != 0 && current == 0xFF)
|
|
||||||
{
|
|
||||||
if (--open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
get();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_binary_chunk(result)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief narrow a definite CBOR array/map length to std::size_t
|
@brief narrow a definite CBOR array/map length to std::size_t
|
||||||
|
|
||||||
@@ -16480,6 +16394,20 @@ class json_pointer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the reference token consists only of digits at this point (cf. checks
|
||||||
|
// above); however, its numeric value might not be representable, in which
|
||||||
|
// case array_index() would throw out_of_range.404/410 -- contains() must
|
||||||
|
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||||
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
|
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||||
|
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
|
{
|
||||||
|
// the array index cannot be represented as size_type
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto idx = array_index<BasicJsonType>(reference_token);
|
const auto idx = array_index<BasicJsonType>(reference_token);
|
||||||
if (idx >= ptr->size())
|
if (idx >= ptr->size())
|
||||||
{
|
{
|
||||||
@@ -25987,11 +25915,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -26007,11 +25932,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -26036,11 +25958,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in MessagePack format
|
/// @brief create a JSON value from an input in MessagePack format
|
||||||
@@ -26054,11 +25973,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -26073,11 +25989,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -26100,11 +26013,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in UBJSON format
|
/// @brief create a JSON value from an input in UBJSON format
|
||||||
@@ -26118,11 +26028,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -26137,11 +26044,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -26164,11 +26068,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BJData format
|
/// @brief create a JSON value from an input in BJData format
|
||||||
@@ -26182,11 +26083,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -26201,11 +26099,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BSON format
|
/// @brief create a JSON value from an input in BSON format
|
||||||
@@ -26219,11 +26114,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||||
@@ -26238,11 +26130,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
basic_json result;
|
basic_json result;
|
||||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -26265,11 +26154,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
auto ia = i.get();
|
auto ia = i.get();
|
||||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||||
{
|
return res ? result : basic_json(value_t::discarded);
|
||||||
result = value_t::discarded;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
@@ -2035,58 +2035,6 @@ TEST_CASE("CBOR definite length equal to the indefinite-length sentinel")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("CBOR indefinite-length strings do not recurse per chunk")
|
|
||||||
{
|
|
||||||
// Reading an indefinite-length string or byte array used to call itself
|
|
||||||
// once per chunk, so a payload of repeated 0x7F (or 0x5F) bytes exhausted
|
|
||||||
// the call stack before any of the input was rejected. The open levels are
|
|
||||||
// counted now, and the levels below prove the reader still reads the same
|
|
||||||
// values and reports the same errors at the same byte offsets.
|
|
||||||
json _;
|
|
||||||
|
|
||||||
SECTION("many open levels are reported, not crashed on")
|
|
||||||
{
|
|
||||||
const std::vector<uint8_t> input(200000, 0x7F);
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(input), "[json.exception.parse_error.110] parse error at byte 200001: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
|
|
||||||
CHECK(json::from_cbor(input, true, false).is_discarded());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("many open levels are reported, not crashed on (binary)")
|
|
||||||
{
|
|
||||||
const std::vector<uint8_t> input(200000, 0x5F);
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(input), "[json.exception.parse_error.110] parse error at byte 200001: syntax error while parsing CBOR binary: unexpected end of input", json::parse_error&);
|
|
||||||
CHECK(json::from_cbor(input, true, false).is_discarded());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("chunks are still concatenated")
|
|
||||||
{
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0xFF})) == json(""));
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x61, 0x61, 0xFF})) == json("a"));
|
|
||||||
// nested indefinite-length strings are concatenated across levels
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x7F, 0x61, 0x61, 0xFF, 0x61, 0x62, 0xFF})) == json("ab"));
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x7F, 0x7F, 0x61, 0x7A, 0xFF, 0xFF, 0xFF})) == json("z"));
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0xA1, 0x7F, 0x61, 0x61, 0xFF, 0x01})) == json({{"a", 1}}));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("chunks are still concatenated (binary)")
|
|
||||||
{
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x5F, 0x41, 0x61, 0xFF})) == json::binary({0x61}));
|
|
||||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x5F, 0x5F, 0x41, 0x61, 0xFF, 0x41, 0x62, 0xFF})) == json::binary({0x61, 0x62}));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("a chunk that is not a string is still rejected")
|
|
||||||
{
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x7F, 0x7F, 0x00})), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x00", json::parse_error&);
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x5F, 0x5F, 0x00})), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing CBOR binary: expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x00", json::parse_error&);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("a break marker outside an indefinite-length string is not a string")
|
|
||||||
{
|
|
||||||
// 0xFF only closes a string that was opened; on its own it is not one
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0xFF, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("CBOR roundtrips" * doctest::skip())
|
TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||||
{
|
{
|
||||||
SECTION("input from flynn")
|
SECTION("input from flynn")
|
||||||
|
|||||||
@@ -319,6 +319,44 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j[jp] = 1, throw_msg.c_str(), json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j[jp] = 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(j_const[jp] == 1, throw_msg.c_str(), json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j_const[jp] == 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
|
||||||
|
// #5395: contains() must not throw for a reference token that is a
|
||||||
|
// syntactically valid array index but numerically exceeds ULLONG_MAX
|
||||||
|
// (causing strtoull() to set errno to ERANGE) -- it should just report
|
||||||
|
// that the pointer does not resolve to an element
|
||||||
|
CHECK(!j.contains(jp));
|
||||||
|
CHECK(!j_const.contains(jp));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// #5395: same as above, but using the exact reproduction from the issue
|
||||||
|
json::json_pointer const jp("/99999999999999999999");
|
||||||
|
std::string const throw_msg = "[json.exception.out_of_range.404] unresolved reference token '99999999999999999999'";
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(j[jp] = 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_const[jp] == 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.at(jp) = 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_const.at(jp) == 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
|
||||||
|
CHECK(!j.contains(jp));
|
||||||
|
CHECK(!j_const.contains(jp));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// #5395: a reference token that is numerically representable in
|
||||||
|
// unsigned long long but exceeds size_type's max (e.g. ULLONG_MAX
|
||||||
|
// itself on typical 64-bit platforms, where size_type's max equals
|
||||||
|
// ULLONG_MAX) must not make contains() throw either
|
||||||
|
json::json_pointer const jp("/18446744073709551615");
|
||||||
|
std::string const throw_msg = "[json.exception.out_of_range.410] array index 18446744073709551615 exceeds size_type";
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(j[jp] = 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_const[jp] == 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.at(jp) = 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_const.at(jp) == 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
|
||||||
|
CHECK(!j.contains(jp));
|
||||||
|
CHECK(!j_const.contains(jp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// on some machines, the check below is not constant
|
// on some machines, the check below is not constant
|
||||||
@@ -334,6 +372,10 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j[jp] = 1, throw_msg.c_str(), json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j[jp] = 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(j_const[jp] == 1, throw_msg.c_str(), json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j_const[jp] == 1, throw_msg.c_str(), json::out_of_range&);
|
||||||
|
|
||||||
|
// #5395: contains() must not throw for a reference token exceeding size_type's max
|
||||||
|
CHECK(!j.contains(jp));
|
||||||
|
CHECK(!j_const.contains(jp));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOCTEST_MSVC_SUPPRESS_WARNING_POP
|
DOCTEST_MSVC_SUPPRESS_WARNING_POP
|
||||||
|
|||||||
Reference in New Issue
Block a user