The recursion depth limit added to JsonDecode() in 2.16.2 gave the C++
function a second parameter with a default value. Function pointers do not
carry default arguments, so the DSL function binding deduced an arity of 2
via boost::function_types::function_arity and required two arguments. As a
result `Json.decode("...")` failed with "Too few arguments for function",
an undocumented breaking change in a patch release.
Wrap JsonDecode() in a single-argument shim (mirroring the existing
JsonEncodeShim) so the registered function keeps its one-parameter contract
while still applying the default depth limit internally.
refs #10913
Depending on the Boost version, the existing test case based on Boost.Asio
coroutines might use a stack allocated without a guard page and might not
reliably detect an overflow. This commit additionally runs the same test
function within a pthread thread started with the same stack size as used by
our coroutines.
If parsing JSON is rejected due to the depth limit introduced in the last
commit, also include the path (like root["object"]["children"]...) that exceeds
the allowed nesting depth.
Data structures parsed from JSON may be accessed recursively, so deeply nested
structures may wreak havoc by overflowing the stack. Thus, enforce a general
nesting depth limit of 24 by default (which should be more than enough for
reasonable use), with the ability to pass a different limit to JsonDecode() if
needed.
This commit refactors the ValueGenerator class to be a template that can
work with any container type. Previously, one has to manually take care
of the used container by lazily iterating over it within a lambda. Now,
the `ValueGenerator` class itself takes care of all the iteration,
making it easier to use and less error-prone. The new base `Generator`
class is required to allow the `JsonEncoder` to handle generators in a
type-erased manner.