mirror of
https://github.com/nlohmann/json.git
synced 2026-09-06 08:17:59 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aee9421883 |
@@ -301,6 +301,16 @@ class json_sax_dom_parser
|
|||||||
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len != detail::unknown_size())
|
||||||
|
{
|
||||||
|
// reserve upfront to avoid repeated reallocations while adding elements,
|
||||||
|
// but cap the reservation so a bogus/hostile length (which is not bounded
|
||||||
|
// by max_size(), unlike e.g. std::vector) cannot trigger an oversized
|
||||||
|
// allocation for a small or truncated input
|
||||||
|
constexpr std::size_t reserve_cap = 16384;
|
||||||
|
ref_stack.back()->m_data.m_value.array->reserve(len < reserve_cap ? len : reserve_cap);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,6 +671,16 @@ class json_sax_dom_callback_parser
|
|||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len != detail::unknown_size())
|
||||||
|
{
|
||||||
|
// reserve upfront to avoid repeated reallocations while adding elements,
|
||||||
|
// but cap the reservation so a bogus/hostile length (which is not bounded
|
||||||
|
// by max_size(), unlike e.g. std::vector) cannot trigger an oversized
|
||||||
|
// allocation for a small or truncated input
|
||||||
|
constexpr std::size_t reserve_cap = 16384;
|
||||||
|
ref_stack.back()->m_data.m_value.array->reserve(len < reserve_cap ? len : reserve_cap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1335,7 +1335,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief serialization
|
/// @brief serialization
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/dump/
|
/// @sa https://json.nlohmann.me/api/basic_json/dump/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
string_t dump(const int indent = -1,
|
string_t dump(const int indent = -1,
|
||||||
const char indent_char = ' ',
|
const char indent_char = ' ',
|
||||||
const bool ensure_ascii = false,
|
const bool ensure_ascii = false,
|
||||||
@@ -1358,7 +1357,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return the type of the JSON value (explicit)
|
/// @brief return the type of the JSON value (explicit)
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/type/
|
/// @sa https://json.nlohmann.me/api/basic_json/type/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr value_t type() const noexcept
|
constexpr value_t type() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type;
|
return m_data.m_type;
|
||||||
@@ -1366,7 +1364,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether type is primitive
|
/// @brief return whether type is primitive
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_primitive() const noexcept
|
constexpr bool is_primitive() const noexcept
|
||||||
{
|
{
|
||||||
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
|
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
|
||||||
@@ -1374,7 +1371,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether type is structured
|
/// @brief return whether type is structured
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_structured/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_structured/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_structured() const noexcept
|
constexpr bool is_structured() const noexcept
|
||||||
{
|
{
|
||||||
return is_array() || is_object();
|
return is_array() || is_object();
|
||||||
@@ -1382,7 +1378,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is null
|
/// @brief return whether value is null
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_null/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_null/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_null() const noexcept
|
constexpr bool is_null() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::null;
|
return m_data.m_type == value_t::null;
|
||||||
@@ -1390,7 +1385,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a boolean
|
/// @brief return whether value is a boolean
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_boolean() const noexcept
|
constexpr bool is_boolean() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::boolean;
|
return m_data.m_type == value_t::boolean;
|
||||||
@@ -1398,7 +1392,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a number
|
/// @brief return whether value is a number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number() const noexcept
|
constexpr bool is_number() const noexcept
|
||||||
{
|
{
|
||||||
return is_number_integer() || is_number_float();
|
return is_number_integer() || is_number_float();
|
||||||
@@ -1406,7 +1399,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an integer number
|
/// @brief return whether value is an integer number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number_integer() const noexcept
|
constexpr bool is_number_integer() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
|
return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
|
||||||
@@ -1414,7 +1406,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an unsigned integer number
|
/// @brief return whether value is an unsigned integer number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number_unsigned() const noexcept
|
constexpr bool is_number_unsigned() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::number_unsigned;
|
return m_data.m_type == value_t::number_unsigned;
|
||||||
@@ -1422,7 +1413,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a floating-point number
|
/// @brief return whether value is a floating-point number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number_float() const noexcept
|
constexpr bool is_number_float() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::number_float;
|
return m_data.m_type == value_t::number_float;
|
||||||
@@ -1430,7 +1420,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an object
|
/// @brief return whether value is an object
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_object/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_object/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_object() const noexcept
|
constexpr bool is_object() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::object;
|
return m_data.m_type == value_t::object;
|
||||||
@@ -1438,7 +1427,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an array
|
/// @brief return whether value is an array
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_array/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_array/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_array() const noexcept
|
constexpr bool is_array() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::array;
|
return m_data.m_type == value_t::array;
|
||||||
@@ -1446,7 +1434,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a string
|
/// @brief return whether value is a string
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_string/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_string/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_string() const noexcept
|
constexpr bool is_string() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::string;
|
return m_data.m_type == value_t::string;
|
||||||
@@ -1454,7 +1441,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a binary array
|
/// @brief return whether value is a binary array
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_binary/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_binary/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_binary() const noexcept
|
constexpr bool is_binary() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::binary;
|
return m_data.m_type == value_t::binary;
|
||||||
@@ -1462,7 +1448,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is discarded
|
/// @brief return whether value is discarded
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_discarded() const noexcept
|
constexpr bool is_discarded() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::discarded;
|
return m_data.m_type == value_t::discarded;
|
||||||
@@ -2794,7 +2779,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief returns the number of occurrences of a key in a JSON object
|
/// @brief returns the number of occurrences of a key in a JSON object
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type count(const typename object_t::key_type& key) const
|
size_type count(const typename object_t::key_type& key) const
|
||||||
{
|
{
|
||||||
// return 0 for all nonobject types
|
// return 0 for all nonobject types
|
||||||
@@ -2805,7 +2789,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<
|
||||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type count(KeyType && key) const
|
size_type count(KeyType && key) const
|
||||||
{
|
{
|
||||||
// return 0 for all nonobject types
|
// return 0 for all nonobject types
|
||||||
@@ -2814,7 +2797,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief check the existence of an element in a JSON object
|
/// @brief check the existence of an element in a JSON object
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool contains(const typename object_t::key_type& key) const
|
bool contains(const typename object_t::key_type& key) const
|
||||||
{
|
{
|
||||||
return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
|
return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
|
||||||
@@ -2824,7 +2806,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<
|
||||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool contains(KeyType && key) const
|
bool contains(KeyType && key) const
|
||||||
{
|
{
|
||||||
return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
|
return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
|
||||||
@@ -2832,14 +2813,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief check the existence of an element in a JSON object given a JSON pointer
|
/// @brief check the existence of an element in a JSON object given a JSON pointer
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool contains(const json_pointer& ptr) const
|
bool contains(const json_pointer& ptr) const
|
||||||
{
|
{
|
||||||
return ptr.contains(this);
|
return ptr.contains(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||||
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
|
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
|
||||||
{
|
{
|
||||||
@@ -2995,7 +2974,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief checks whether the container is empty.
|
/// @brief checks whether the container is empty.
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/empty/
|
/// @sa https://json.nlohmann.me/api/basic_json/empty/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool empty() const noexcept
|
bool empty() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
switch (m_data.m_type)
|
||||||
@@ -3035,7 +3013,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief returns the number of elements
|
/// @brief returns the number of elements
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/size/
|
/// @sa https://json.nlohmann.me/api/basic_json/size/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type size() const noexcept
|
size_type size() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
switch (m_data.m_type)
|
||||||
@@ -3075,7 +3052,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief returns the maximum possible number of elements
|
/// @brief returns the maximum possible number of elements
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/max_size/
|
/// @sa https://json.nlohmann.me/api/basic_json/max_size/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type max_size() const noexcept
|
size_type max_size() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
switch (m_data.m_type)
|
||||||
@@ -4153,7 +4129,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @brief check if the input is valid JSON
|
/// @brief check if the input is valid JSON
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
||||||
template<typename InputType>
|
template<typename InputType>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
static bool accept(InputType&& i,
|
static bool accept(InputType&& i,
|
||||||
const bool ignore_comments = false,
|
const bool ignore_comments = false,
|
||||||
const bool ignore_trailing_commas = false)
|
const bool ignore_trailing_commas = false)
|
||||||
@@ -4165,7 +4140,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
||||||
template<typename IteratorType, typename SentinelType = IteratorType,
|
template<typename IteratorType, typename SentinelType = IteratorType,
|
||||||
detail::enable_if_t<detail::can_compare_ne<IteratorType, SentinelType>::value, int> = 0>
|
detail::enable_if_t<detail::can_compare_ne<IteratorType, SentinelType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
static bool accept(IteratorType first, SentinelType last,
|
static bool accept(IteratorType first, SentinelType last,
|
||||||
const bool ignore_comments = false,
|
const bool ignore_comments = false,
|
||||||
const bool ignore_trailing_commas = false)
|
const bool ignore_trailing_commas = false)
|
||||||
@@ -4265,7 +4239,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return the type as string
|
/// @brief return the type as string
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/type_name/
|
/// @sa https://json.nlohmann.me/api/basic_json/type_name/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
const char* type_name() const noexcept
|
const char* type_name() const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9829,6 +9829,16 @@ class json_sax_dom_parser
|
|||||||
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len != detail::unknown_size())
|
||||||
|
{
|
||||||
|
// reserve upfront to avoid repeated reallocations while adding elements,
|
||||||
|
// but cap the reservation so a bogus/hostile length (which is not bounded
|
||||||
|
// by max_size(), unlike e.g. std::vector) cannot trigger an oversized
|
||||||
|
// allocation for a small or truncated input
|
||||||
|
constexpr std::size_t reserve_cap = 16384;
|
||||||
|
ref_stack.back()->m_data.m_value.array->reserve(len < reserve_cap ? len : reserve_cap);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10189,6 +10199,16 @@ class json_sax_dom_callback_parser
|
|||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len != detail::unknown_size())
|
||||||
|
{
|
||||||
|
// reserve upfront to avoid repeated reallocations while adding elements,
|
||||||
|
// but cap the reservation so a bogus/hostile length (which is not bounded
|
||||||
|
// by max_size(), unlike e.g. std::vector) cannot trigger an oversized
|
||||||
|
// allocation for a small or truncated input
|
||||||
|
constexpr std::size_t reserve_cap = 16384;
|
||||||
|
ref_stack.back()->m_data.m_value.array->reserve(len < reserve_cap ? len : reserve_cap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -22763,7 +22783,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief serialization
|
/// @brief serialization
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/dump/
|
/// @sa https://json.nlohmann.me/api/basic_json/dump/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
string_t dump(const int indent = -1,
|
string_t dump(const int indent = -1,
|
||||||
const char indent_char = ' ',
|
const char indent_char = ' ',
|
||||||
const bool ensure_ascii = false,
|
const bool ensure_ascii = false,
|
||||||
@@ -22786,7 +22805,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return the type of the JSON value (explicit)
|
/// @brief return the type of the JSON value (explicit)
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/type/
|
/// @sa https://json.nlohmann.me/api/basic_json/type/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr value_t type() const noexcept
|
constexpr value_t type() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type;
|
return m_data.m_type;
|
||||||
@@ -22794,7 +22812,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether type is primitive
|
/// @brief return whether type is primitive
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_primitive() const noexcept
|
constexpr bool is_primitive() const noexcept
|
||||||
{
|
{
|
||||||
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
|
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
|
||||||
@@ -22802,7 +22819,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether type is structured
|
/// @brief return whether type is structured
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_structured/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_structured/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_structured() const noexcept
|
constexpr bool is_structured() const noexcept
|
||||||
{
|
{
|
||||||
return is_array() || is_object();
|
return is_array() || is_object();
|
||||||
@@ -22810,7 +22826,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is null
|
/// @brief return whether value is null
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_null/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_null/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_null() const noexcept
|
constexpr bool is_null() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::null;
|
return m_data.m_type == value_t::null;
|
||||||
@@ -22818,7 +22833,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a boolean
|
/// @brief return whether value is a boolean
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_boolean() const noexcept
|
constexpr bool is_boolean() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::boolean;
|
return m_data.m_type == value_t::boolean;
|
||||||
@@ -22826,7 +22840,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a number
|
/// @brief return whether value is a number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number() const noexcept
|
constexpr bool is_number() const noexcept
|
||||||
{
|
{
|
||||||
return is_number_integer() || is_number_float();
|
return is_number_integer() || is_number_float();
|
||||||
@@ -22834,7 +22847,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an integer number
|
/// @brief return whether value is an integer number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number_integer() const noexcept
|
constexpr bool is_number_integer() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
|
return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
|
||||||
@@ -22842,7 +22854,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an unsigned integer number
|
/// @brief return whether value is an unsigned integer number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number_unsigned() const noexcept
|
constexpr bool is_number_unsigned() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::number_unsigned;
|
return m_data.m_type == value_t::number_unsigned;
|
||||||
@@ -22850,7 +22861,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a floating-point number
|
/// @brief return whether value is a floating-point number
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_number_float() const noexcept
|
constexpr bool is_number_float() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::number_float;
|
return m_data.m_type == value_t::number_float;
|
||||||
@@ -22858,7 +22868,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an object
|
/// @brief return whether value is an object
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_object/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_object/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_object() const noexcept
|
constexpr bool is_object() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::object;
|
return m_data.m_type == value_t::object;
|
||||||
@@ -22866,7 +22875,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is an array
|
/// @brief return whether value is an array
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_array/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_array/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_array() const noexcept
|
constexpr bool is_array() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::array;
|
return m_data.m_type == value_t::array;
|
||||||
@@ -22874,7 +22882,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a string
|
/// @brief return whether value is a string
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_string/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_string/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_string() const noexcept
|
constexpr bool is_string() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::string;
|
return m_data.m_type == value_t::string;
|
||||||
@@ -22882,7 +22889,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is a binary array
|
/// @brief return whether value is a binary array
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_binary/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_binary/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_binary() const noexcept
|
constexpr bool is_binary() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::binary;
|
return m_data.m_type == value_t::binary;
|
||||||
@@ -22890,7 +22896,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return whether value is discarded
|
/// @brief return whether value is discarded
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
|
/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
constexpr bool is_discarded() const noexcept
|
constexpr bool is_discarded() const noexcept
|
||||||
{
|
{
|
||||||
return m_data.m_type == value_t::discarded;
|
return m_data.m_type == value_t::discarded;
|
||||||
@@ -24222,7 +24227,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief returns the number of occurrences of a key in a JSON object
|
/// @brief returns the number of occurrences of a key in a JSON object
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type count(const typename object_t::key_type& key) const
|
size_type count(const typename object_t::key_type& key) const
|
||||||
{
|
{
|
||||||
// return 0 for all nonobject types
|
// return 0 for all nonobject types
|
||||||
@@ -24233,7 +24237,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<
|
||||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type count(KeyType && key) const
|
size_type count(KeyType && key) const
|
||||||
{
|
{
|
||||||
// return 0 for all nonobject types
|
// return 0 for all nonobject types
|
||||||
@@ -24242,7 +24245,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief check the existence of an element in a JSON object
|
/// @brief check the existence of an element in a JSON object
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool contains(const typename object_t::key_type& key) const
|
bool contains(const typename object_t::key_type& key) const
|
||||||
{
|
{
|
||||||
return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
|
return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
|
||||||
@@ -24252,7 +24254,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<
|
||||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool contains(KeyType && key) const
|
bool contains(KeyType && key) const
|
||||||
{
|
{
|
||||||
return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
|
return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
|
||||||
@@ -24260,14 +24261,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief check the existence of an element in a JSON object given a JSON pointer
|
/// @brief check the existence of an element in a JSON object given a JSON pointer
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool contains(const json_pointer& ptr) const
|
bool contains(const json_pointer& ptr) const
|
||||||
{
|
{
|
||||||
return ptr.contains(this);
|
return ptr.contains(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||||
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
|
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
|
||||||
{
|
{
|
||||||
@@ -24423,7 +24422,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief checks whether the container is empty.
|
/// @brief checks whether the container is empty.
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/empty/
|
/// @sa https://json.nlohmann.me/api/basic_json/empty/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
bool empty() const noexcept
|
bool empty() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
switch (m_data.m_type)
|
||||||
@@ -24463,7 +24461,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief returns the number of elements
|
/// @brief returns the number of elements
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/size/
|
/// @sa https://json.nlohmann.me/api/basic_json/size/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type size() const noexcept
|
size_type size() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
switch (m_data.m_type)
|
||||||
@@ -24503,7 +24500,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief returns the maximum possible number of elements
|
/// @brief returns the maximum possible number of elements
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/max_size/
|
/// @sa https://json.nlohmann.me/api/basic_json/max_size/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
size_type max_size() const noexcept
|
size_type max_size() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
switch (m_data.m_type)
|
||||||
@@ -25581,7 +25577,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @brief check if the input is valid JSON
|
/// @brief check if the input is valid JSON
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
||||||
template<typename InputType>
|
template<typename InputType>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
static bool accept(InputType&& i,
|
static bool accept(InputType&& i,
|
||||||
const bool ignore_comments = false,
|
const bool ignore_comments = false,
|
||||||
const bool ignore_trailing_commas = false)
|
const bool ignore_trailing_commas = false)
|
||||||
@@ -25593,7 +25588,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
/// @sa https://json.nlohmann.me/api/basic_json/accept/
|
||||||
template<typename IteratorType, typename SentinelType = IteratorType,
|
template<typename IteratorType, typename SentinelType = IteratorType,
|
||||||
detail::enable_if_t<detail::can_compare_ne<IteratorType, SentinelType>::value, int> = 0>
|
detail::enable_if_t<detail::can_compare_ne<IteratorType, SentinelType>::value, int> = 0>
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
static bool accept(IteratorType first, SentinelType last,
|
static bool accept(IteratorType first, SentinelType last,
|
||||||
const bool ignore_comments = false,
|
const bool ignore_comments = false,
|
||||||
const bool ignore_trailing_commas = false)
|
const bool ignore_trailing_commas = false)
|
||||||
@@ -25693,7 +25687,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief return the type as string
|
/// @brief return the type as string
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/type_name/
|
/// @sa https://json.nlohmann.me/api/basic_json/type_name/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
const char* type_name() const noexcept
|
const char* type_name() const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3489,6 +3489,65 @@ TEST_CASE("BJData")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("issue #5405 - array reserve for definite-length BJData arrays")
|
||||||
|
{
|
||||||
|
SECTION("a huge claimed length with no element data must not over-allocate")
|
||||||
|
{
|
||||||
|
// optimized form [$type#count: type 'i' (int8), count as a four-byte
|
||||||
|
// little-endian 'l' (int32) of 0x7FFFFFFF (2147483647), but no
|
||||||
|
// element data at all. max_size() for a std::vector is far larger
|
||||||
|
// than this count, so it does not reject the header outright; the
|
||||||
|
// (capped) reservation must not attempt to allocate space for
|
||||||
|
// billions of elements before the missing data is detected.
|
||||||
|
json _;
|
||||||
|
const std::vector<uint8_t> input = {'[', '$', 'i', '#', 'l', 0xFF, 0xFF, 0xFF, 0x7F};
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(input),
|
||||||
|
"[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData number: unexpected end of input",
|
||||||
|
json::parse_error&);
|
||||||
|
CHECK(json::from_bjdata(input, true, false).is_discarded());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("arrays of various sizes decode to the same value as before the reserve optimization")
|
||||||
|
{
|
||||||
|
for (const auto size :
|
||||||
|
{
|
||||||
|
std::size_t(0), std::size_t(1), std::size_t(5), // small
|
||||||
|
std::size_t(16384), // exactly at the reserve cap
|
||||||
|
std::size_t(20000) // above the reserve cap
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(size)
|
||||||
|
json j = json::array();
|
||||||
|
for (std::size_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(static_cast<int>(i % 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
// exercise both the plain and the optimized [$type#count encoding
|
||||||
|
const auto packed_plain = json::to_bjdata(j);
|
||||||
|
CHECK(json::from_bjdata(packed_plain) == j);
|
||||||
|
|
||||||
|
const auto packed_optimized = json::to_bjdata(j, true, true);
|
||||||
|
CHECK(json::from_bjdata(packed_optimized) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a user-defined SAX consumer is unaffected by the internal DOM reserve optimization")
|
||||||
|
{
|
||||||
|
// the reserve() call is local to json_sax_dom_parser / json_sax_dom_callback_parser;
|
||||||
|
// a custom SAX consumer that does not touch a DOM array sees identical events
|
||||||
|
json j = json::array();
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(i);
|
||||||
|
}
|
||||||
|
const auto packed = json::to_bjdata(j, true, true);
|
||||||
|
|
||||||
|
SaxCountdown scp(1000000); // large enough to never trigger an abort
|
||||||
|
CHECK(json::sax_parse(packed, &scp, json::input_format_t::bjdata));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Universal Binary JSON Specification Examples 1")
|
TEST_CASE("Universal Binary JSON Specification Examples 1")
|
||||||
{
|
{
|
||||||
SECTION("Null Value")
|
SECTION("Null Value")
|
||||||
|
|||||||
@@ -2035,6 +2035,60 @@ TEST_CASE("CBOR definite length equal to the indefinite-length sentinel")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("issue #5405 - array reserve for definite-length CBOR arrays")
|
||||||
|
{
|
||||||
|
SECTION("a huge claimed length with no element data must not over-allocate")
|
||||||
|
{
|
||||||
|
// 0x9A: array with a four-byte length; claims 0xFFFFFFFF (4294967295)
|
||||||
|
// elements but provides none. max_size() for a std::vector is far
|
||||||
|
// larger than this count, so it does not reject the header outright;
|
||||||
|
// the (capped) reservation must not attempt to allocate space for
|
||||||
|
// billions of elements before the missing data is detected.
|
||||||
|
json _;
|
||||||
|
const std::vector<uint8_t> input = {0x9A, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_cbor(input),
|
||||||
|
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR value: unexpected end of input",
|
||||||
|
json::parse_error&);
|
||||||
|
CHECK(json::from_cbor(input, true, false).is_discarded());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("arrays of various sizes decode to the same value as before the reserve optimization")
|
||||||
|
{
|
||||||
|
for (const auto size :
|
||||||
|
{
|
||||||
|
std::size_t(0), std::size_t(1), std::size_t(5), // small
|
||||||
|
std::size_t(16384), // exactly at the reserve cap
|
||||||
|
std::size_t(20000) // above the reserve cap
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(size)
|
||||||
|
json j = json::array();
|
||||||
|
for (std::size_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(static_cast<int>(i % 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto packed = json::to_cbor(j);
|
||||||
|
CHECK(json::from_cbor(packed) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a user-defined SAX consumer is unaffected by the internal DOM reserve optimization")
|
||||||
|
{
|
||||||
|
// the reserve() call is local to json_sax_dom_parser / json_sax_dom_callback_parser;
|
||||||
|
// a custom SAX consumer that does not touch a DOM array sees identical events
|
||||||
|
json j = json::array();
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(i);
|
||||||
|
}
|
||||||
|
const auto packed = json::to_cbor(j);
|
||||||
|
|
||||||
|
SaxCountdown scp(1000000); // large enough to never trigger an abort
|
||||||
|
CHECK(json::sax_parse(packed, &scp, json::input_format_t::cbor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("CBOR roundtrips" * doctest::skip())
|
TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||||
{
|
{
|
||||||
SECTION("input from flynn")
|
SECTION("input from flynn")
|
||||||
|
|||||||
@@ -1597,6 +1597,60 @@ TEST_CASE("MessagePack")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("issue #5405 - array reserve for definite-length MessagePack arrays")
|
||||||
|
{
|
||||||
|
SECTION("a huge claimed length with no element data must not over-allocate")
|
||||||
|
{
|
||||||
|
// 0xdd: array 32 (four-byte length); claims 0xFFFFFFFF (4294967295)
|
||||||
|
// elements but provides none. max_size() for a std::vector is far
|
||||||
|
// larger than this count, so it does not reject the header outright;
|
||||||
|
// the (capped) reservation must not attempt to allocate space for
|
||||||
|
// billions of elements before the missing data is detected.
|
||||||
|
json _;
|
||||||
|
const std::vector<uint8_t> input = {0xdd, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(input),
|
||||||
|
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing MessagePack value: unexpected end of input",
|
||||||
|
json::parse_error&);
|
||||||
|
CHECK(json::from_msgpack(input, true, false).is_discarded());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("arrays of various sizes decode to the same value as before the reserve optimization")
|
||||||
|
{
|
||||||
|
for (const auto size :
|
||||||
|
{
|
||||||
|
std::size_t(0), std::size_t(1), std::size_t(5), // small
|
||||||
|
std::size_t(16384), // exactly at the reserve cap
|
||||||
|
std::size_t(20000) // above the reserve cap
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(size)
|
||||||
|
json j = json::array();
|
||||||
|
for (std::size_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(static_cast<int>(i % 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto packed = json::to_msgpack(j);
|
||||||
|
CHECK(json::from_msgpack(packed) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a user-defined SAX consumer is unaffected by the internal DOM reserve optimization")
|
||||||
|
{
|
||||||
|
// the reserve() call is local to json_sax_dom_parser / json_sax_dom_callback_parser;
|
||||||
|
// a custom SAX consumer that does not touch a DOM array sees identical events
|
||||||
|
json j = json::array();
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(i);
|
||||||
|
}
|
||||||
|
const auto packed = json::to_msgpack(j);
|
||||||
|
|
||||||
|
SaxCountdown scp(1000000); // large enough to never trigger an abort
|
||||||
|
CHECK(json::sax_parse(packed, &scp, json::input_format_t::msgpack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// use this testcase outside [hide] to run it with Valgrind
|
// use this testcase outside [hide] to run it with Valgrind
|
||||||
TEST_CASE("single MessagePack roundtrip")
|
TEST_CASE("single MessagePack roundtrip")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -639,8 +639,7 @@ TEST_CASE("regression tests 2")
|
|||||||
s += static_cast<char>(i);
|
s += static_cast<char>(i);
|
||||||
}
|
}
|
||||||
dump_test["1"] = s;
|
dump_test["1"] = s;
|
||||||
// dump() is nodiscard; this only checks that dumping does not throw/crash
|
dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
|
||||||
(void)dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2149,6 +2149,65 @@ TEST_CASE("UBJSON")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("issue #5405 - array reserve for definite-length UBJSON arrays")
|
||||||
|
{
|
||||||
|
SECTION("a huge claimed length with no element data must not over-allocate")
|
||||||
|
{
|
||||||
|
// optimized form [$type#count: type 'i' (int8), count as a four-byte
|
||||||
|
// 'l' (int32) of 0x7FFFFFFF (2147483647), but no element data at all.
|
||||||
|
// max_size() for a std::vector is far larger than this count, so it
|
||||||
|
// does not reject the header outright; the (capped) reservation must
|
||||||
|
// not attempt to allocate space for billions of elements before the
|
||||||
|
// missing data is detected.
|
||||||
|
json _;
|
||||||
|
const std::vector<uint8_t> input = {'[', '$', 'i', '#', 'l', 0x7F, 0xFF, 0xFF, 0xFF};
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(input),
|
||||||
|
"[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON number: unexpected end of input",
|
||||||
|
json::parse_error&);
|
||||||
|
CHECK(json::from_ubjson(input, true, false).is_discarded());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("arrays of various sizes decode to the same value as before the reserve optimization")
|
||||||
|
{
|
||||||
|
for (const auto size :
|
||||||
|
{
|
||||||
|
std::size_t(0), std::size_t(1), std::size_t(5), // small
|
||||||
|
std::size_t(16384), // exactly at the reserve cap
|
||||||
|
std::size_t(20000) // above the reserve cap
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(size)
|
||||||
|
json j = json::array();
|
||||||
|
for (std::size_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(static_cast<int>(i % 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
// exercise both the plain and the optimized [$type#count encoding
|
||||||
|
const auto packed_plain = json::to_ubjson(j);
|
||||||
|
CHECK(json::from_ubjson(packed_plain) == j);
|
||||||
|
|
||||||
|
const auto packed_optimized = json::to_ubjson(j, true, true);
|
||||||
|
CHECK(json::from_ubjson(packed_optimized) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a user-defined SAX consumer is unaffected by the internal DOM reserve optimization")
|
||||||
|
{
|
||||||
|
// the reserve() call is local to json_sax_dom_parser / json_sax_dom_callback_parser;
|
||||||
|
// a custom SAX consumer that does not touch a DOM array sees identical events
|
||||||
|
json j = json::array();
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
j.push_back(i);
|
||||||
|
}
|
||||||
|
const auto packed = json::to_ubjson(j, true, true);
|
||||||
|
|
||||||
|
SaxCountdown scp(1000000); // large enough to never trigger an abort
|
||||||
|
CHECK(json::sax_parse(packed, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Universal Binary JSON Specification Examples 1")
|
TEST_CASE("Universal Binary JSON Specification Examples 1")
|
||||||
{
|
{
|
||||||
SECTION("Null Value")
|
SECTION("Null Value")
|
||||||
|
|||||||
Reference in New Issue
Block a user