Share one recursion depth limit, and copy the hash frame out of the stack

dump() and hash() each defined their own limit on how many nesting levels
they recurse into, and the operations still to come would have added more,
free to diverge over time. They now all use detail::recursion_depth_limit(),
in a header of its own; serializer::dump_depth_limit() and
hash_depth_limit() are gone.

hash_iteratively() now copies the frame it works on out of the stack and
changes the frame only through stack.back(), so nothing can refer into
the stack after entering an element has grown it.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-23 23:07:11 +02:00
parent 75c61f91f1
commit 57a5a5d48e
7 changed files with 113 additions and 58 deletions
+2 -2
View File
@@ -20,7 +20,7 @@ namespace
// how detail::hash defines the hash of an array or object: the seeds of the
// elements, combined in order. Recursive, so only usable on values nested a
// few hundred levels deep - which is exactly what is needed to check that the
// iterative path taken below detail::hash_depth_limit() computes the same.
// iterative path taken below detail::recursion_depth_limit() computes the same.
template<typename BasicJsonType>
std::size_t reference_hash(const BasicJsonType& j)
{
@@ -189,7 +189,7 @@ TEST_CASE("hash of deeply nested values")
SECTION("hashing past the descent bound computes the same values")
{
// every depth on either side of where the iterative path takes over
for (std::size_t depth = 0; depth <= 2 * nlohmann::detail::hash_depth_limit() + 10; ++depth)
for (std::size_t depth = 0; depth <= 2 * nlohmann::detail::recursion_depth_limit() + 10; ++depth)
{
CAPTURE(depth);
const auto arrays = nested<json>(depth, false);