json icon indicating copy to clipboard operation
json copied to clipboard

stack overflow

Open 0dayhunter777 opened this issue 4 months ago • 7 comments

Description

json.zip

I would like to report one stack overflow bug I encountered while testing the latest version(v 3.12.0) of json. It appears that json may crash when given malformed input.

The gdb debugging log is in json/gdb_debug_log, and the input is in json/input

Reproduction steps

  1. gdb json
  2. run input/stack_overflow

Expected vs. actual results

expected: program runs normally

actual results: Program received signal SIGSEGV, Segmentation fault. 0x000000000047b85b in nlohmann::json_abi_v3_12_0::detail::binary_reader<nlohmann::json_abi_v3_12_0::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits, std::allocator >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_12_0::adl_serializer, std::vector<unsigned char, std::allocator >, void>, nlohmann::json_abi_v3_12_0::detail::iterator_input_adapter<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator > > >, nlohmann::json_abi_v3_12_0::detail::json_sax_dom_parser<nlohmann::json_abi_v3_12_0::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits, std::allocator >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_12_0::adl_serializer, std::vector<unsigned char, std::allocator >, void>, nlohmann::json_abi_v3_12_0::detail::iterator_input_adapter<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator > > > > >::get_ubjson_size_type(std::pair<unsigned long, unsigned long>&, bool) ()

Minimal code example


Error messages


Compiler and operating system

g++ 9.4.0 ubuntu22.04.1

Library version

3.12.0

Validation

0dayhunter777 avatar Aug 22 '25 01:08 0dayhunter777

This is a known issue of the library. The input creates 5538 nested arrays which are parsed with 5538 recursive calls. That issue exists for all input formats - both binary and JSON.

nlohmann avatar Aug 22 '25 08:08 nlohmann

Unless somebody wants to look into this issue and makes the parser non-recursive, I would close the issue as "won't fix".

nlohmann avatar Aug 22 '25 08:08 nlohmann

Hi, Can I look into this?

rajnsunny avatar Sep 08 '25 22:09 rajnsunny

Sure.

nlohmann avatar Sep 09 '25 04:09 nlohmann

Hi @nlohmann,

I'm working on a coroutine-based approach (C++20) to eliminate stack overflow in the binary format parsers (UBJSON/BSON/CBOR) when handling deeply nested data.

The implementation would use feature flags to preserve the current implementation for older standards while providing stack-safe parsing for C++20+.

Provided I guard it for older C++ standards, would this be something you'd consider for the library?

AhmedMagdy9876 avatar Nov 23 '25 00:11 AhmedMagdy9876

Probably not. What do you have in mind?

nlohmann avatar Nov 23 '25 13:11 nlohmann

Here is a prototype implementation in my fork: https://github.com/AhmedMagdy9876/nlohmann_json/commit/ce5d490e63a42699c7faf654ba939a3ddc13d130

The idea is to remove the unbounded call-stack recursion in the binary parsers and the serializer by replacing the strict recursive descent with small coroutine steps. Each parsing step becomes a coroutine that co_awaits the next one, so a suspension chain replaces the recursion chain without changing the control flow logic. This keeps the existing structure but moves the recursion off the C++ call stack and into the coroutine frame.

The coroutine implementation only activates when the compiler supports C++20 coroutines; otherwise the original recursive codepath is used untouched, and the stack overflow issue will still exist. This commit is just intended to explain the approach. I’m happy to simplify or adjust the design if you think the direction is viable.

AhmedMagdy9876 avatar Nov 24 '25 13:11 AhmedMagdy9876