mirror of
https://github.com/nlohmann/json.git
synced 2026-09-29 19:20:30 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14558ba011 | ||
|
|
ccb419ca64 | ||
|
|
4494890be6 | ||
|
|
c4469c9f82 |
@@ -19,17 +19,11 @@ namespace detail
|
||||
/*!
|
||||
@brief the number of nesting levels an operation recurses into
|
||||
|
||||
Operations that walk a value (copying, comparing, serializing, hashing, merging,
|
||||
...) recurse once
|
||||
Operations that walk a value (serializing, hashing, merging, ...) recurse once
|
||||
per nesting level, which is fastest, but a value nested deeply enough would
|
||||
exhaust the call stack. So they recurse only this many levels deep and finish
|
||||
whatever lies below with an explicit stack. All of them share this limit.
|
||||
|
||||
Most of them pass the depth down as an argument. The copy constructor and the
|
||||
comparison operators cannot, as their signatures are fixed, so they count it
|
||||
in basic_json::nesting_depth() instead, a byte per thread; the limit must
|
||||
therefore stay below 255.
|
||||
|
||||
@sa https://github.com/nlohmann/json/issues/5387
|
||||
*/
|
||||
constexpr std::size_t recursion_depth_limit() noexcept
|
||||
|
||||
@@ -898,8 +898,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
}
|
||||
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
// nesting_depth() is a byte and may exceed the limit by one level
|
||||
static_assert(detail::recursion_depth_limit() < 255, "the nesting depth count must fit in a byte");
|
||||
/// the number of levels an operation descends into before it finishes the
|
||||
/// value below it without the call stack
|
||||
static constexpr std::uint8_t nesting_depth_limit()
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief how many levels the operation going on in this thread has descended into
|
||||
@@ -941,7 +945,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
static_cast<void>(may_descend);
|
||||
return true;
|
||||
#else
|
||||
return !may_descend || nesting_depth() >= detail::recursion_depth_limit();
|
||||
return !may_descend || nesting_depth() >= nesting_depth_limit();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -965,7 +969,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
#ifdef JSON_NO_THREAD_LOCAL
|
||||
: m_okay(false)
|
||||
#else
|
||||
: m_okay(nesting_depth() < detail::recursion_depth_limit())
|
||||
: m_okay(nesting_depth() < nesting_depth_limit())
|
||||
#endif
|
||||
{
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
@@ -1169,7 +1173,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
The values whose copy has not been created yet are kept on an explicit
|
||||
worklist rather than on the call stack. This is only reached for values
|
||||
nested deeper than @ref detail::recursion_depth_limit levels, which is why it copies
|
||||
nested deeper than @ref nesting_depth_limit levels, which is why it copies
|
||||
every container by hand instead of letting the container do it: the fast
|
||||
ways of doing so would descend into the elements and defeat the purpose.
|
||||
*/
|
||||
@@ -1235,7 +1239,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
Copying a container copies its elements, so a value nested deeply enough
|
||||
used to exhaust the call stack. The descent is bounded here: the first
|
||||
@ref detail::recursion_depth_limit levels are copied by the containers themselves, just
|
||||
@ref nesting_depth_limit levels are copied by the containers themselves, just
|
||||
as they always were, and anything below that is copied without the call
|
||||
stack by @ref copy_iteratively. Copying a value can therefore no longer
|
||||
exhaust the stack, however deeply it is nested, just like destroying one
|
||||
@@ -1373,7 +1377,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/*!
|
||||
@brief compare @a lhs and @a rhs without descending into them
|
||||
|
||||
Reached once a comparison has descended @ref detail::recursion_depth_limit levels, so
|
||||
Reached once a comparison has descended @ref nesting_depth_limit levels, so
|
||||
that comparing values cannot exhaust the call stack however deeply they are
|
||||
nested. The two values are walked in lockstep on an explicit stack and
|
||||
compared lexicographically, element by element in the order the containers
|
||||
|
||||
@@ -7281,17 +7281,11 @@ namespace detail
|
||||
/*!
|
||||
@brief the number of nesting levels an operation recurses into
|
||||
|
||||
Operations that walk a value (copying, comparing, serializing, hashing, merging,
|
||||
...) recurse once
|
||||
Operations that walk a value (serializing, hashing, merging, ...) recurse once
|
||||
per nesting level, which is fastest, but a value nested deeply enough would
|
||||
exhaust the call stack. So they recurse only this many levels deep and finish
|
||||
whatever lies below with an explicit stack. All of them share this limit.
|
||||
|
||||
Most of them pass the depth down as an argument. The copy constructor and the
|
||||
comparison operators cannot, as their signatures are fixed, so they count it
|
||||
in basic_json::nesting_depth() instead, a byte per thread; the limit must
|
||||
therefore stay below 255.
|
||||
|
||||
@sa https://github.com/nlohmann/json/issues/5387
|
||||
*/
|
||||
constexpr std::size_t recursion_depth_limit() noexcept
|
||||
@@ -26985,8 +26979,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
}
|
||||
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
// nesting_depth() is a byte and may exceed the limit by one level
|
||||
static_assert(detail::recursion_depth_limit() < 255, "the nesting depth count must fit in a byte");
|
||||
/// the number of levels an operation descends into before it finishes the
|
||||
/// value below it without the call stack
|
||||
static constexpr std::uint8_t nesting_depth_limit()
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief how many levels the operation going on in this thread has descended into
|
||||
@@ -27028,7 +27026,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
static_cast<void>(may_descend);
|
||||
return true;
|
||||
#else
|
||||
return !may_descend || nesting_depth() >= detail::recursion_depth_limit();
|
||||
return !may_descend || nesting_depth() >= nesting_depth_limit();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -27052,7 +27050,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
#ifdef JSON_NO_THREAD_LOCAL
|
||||
: m_okay(false)
|
||||
#else
|
||||
: m_okay(nesting_depth() < detail::recursion_depth_limit())
|
||||
: m_okay(nesting_depth() < nesting_depth_limit())
|
||||
#endif
|
||||
{
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
@@ -27256,7 +27254,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
The values whose copy has not been created yet are kept on an explicit
|
||||
worklist rather than on the call stack. This is only reached for values
|
||||
nested deeper than @ref detail::recursion_depth_limit levels, which is why it copies
|
||||
nested deeper than @ref nesting_depth_limit levels, which is why it copies
|
||||
every container by hand instead of letting the container do it: the fast
|
||||
ways of doing so would descend into the elements and defeat the purpose.
|
||||
*/
|
||||
@@ -27322,7 +27320,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
Copying a container copies its elements, so a value nested deeply enough
|
||||
used to exhaust the call stack. The descent is bounded here: the first
|
||||
@ref detail::recursion_depth_limit levels are copied by the containers themselves, just
|
||||
@ref nesting_depth_limit levels are copied by the containers themselves, just
|
||||
as they always were, and anything below that is copied without the call
|
||||
stack by @ref copy_iteratively. Copying a value can therefore no longer
|
||||
exhaust the stack, however deeply it is nested, just like destroying one
|
||||
@@ -27460,7 +27458,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/*!
|
||||
@brief compare @a lhs and @a rhs without descending into them
|
||||
|
||||
Reached once a comparison has descended @ref detail::recursion_depth_limit levels, so
|
||||
Reached once a comparison has descended @ref nesting_depth_limit levels, so
|
||||
that comparing values cannot exhaust the call stack however deeply they are
|
||||
nested. The two values are walked in lockstep on an explicit stack and
|
||||
compared lexicographically, element by element in the order the containers
|
||||
|
||||
@@ -766,6 +766,25 @@ TEST_CASE("regression tests 2")
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
SECTION("issue #5066 - MSVC converts json to std::variant<json> via the conversion operator")
|
||||
{
|
||||
// std::variant<json> must not be retrievable via get<>(), because otherwise the
|
||||
// implicit conversion operator becomes a candidate that MSVC picks over the variant's
|
||||
// converting constructor, routing a number through the string from_json overload
|
||||
static_assert(!nlohmann::detail::is_detected<nlohmann::detail::get_template_function, const json&, std::variant<json>>::value,
|
||||
"std::variant<json> must not be retrievable via get<>()");
|
||||
|
||||
// clang before 7 cannot instantiate libstdc++'s std::variant<json>
|
||||
#if !(defined(__clang__) && __clang_major__ < 7)
|
||||
// push_back, not emplace_back: #5066 needs the implicit conversion
|
||||
// from json to the vector's value type
|
||||
std::vector<std::variant<json>> v;
|
||||
v.push_back(json(1)); // NOLINT(hicpp-use-emplace,modernize-use-emplace)
|
||||
CHECK(std::get<0>(v[0]) == 1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("regression test - parser callback must not lose a duplicate key's prior value")
|
||||
|
||||
Reference in New Issue
Block a user