json: Stack-overflow (OSS-Fuzz 4234)
Detailed report: https://oss-fuzz.com/testcase?key=5854339613589504
Project: json
Fuzzer: libFuzzer_json_parse_cbor_fuzzer
Job Type: libfuzzer_asan_json
Platform Id: linux
Crash Type: Stack-overflow
Crash Address: 0x7ffc55e22ce8
Crash State:
nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<cha
nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::ve
nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<cha
Sanitizer: address (ASAN)
Regressed: https://oss-fuzz.com/revisions?job=libfuzzer_asan_json&range=201701031958:201701032147
Reproducer Testcase: https://oss-fuzz.com/download?testcase_id=5854339613589504
Issue filed automatically.
See https://github.com/google/oss-fuzz/blob/master/docs/reproducing.md for more information.
This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without an upstream patch, then the bug report will automatically
become visible to the public.
clusterfuzz-testcase-minimized-5854339613589504.dms.zip
Stack trace:
AddressSanitizer:DEADLYSIGNAL
--
| =================================================================
| ==1==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc55e22ce8 (pc 0x000000515f22 bp 0x7ffc55e23530 sp 0x7ffc55e22cd0 T0)
| SCARINESS: 10 (stack-overflow)
| #0 0x515f21 in operator new(unsigned long) _asan_rtl_
| #1 0x5a6470 in __allocate /usr/local/include/c++/v1/new:226:10
| #2 0x5a6470 in allocate /usr/local/include/c++/v1/memory:1747
| #3 0x5a6470 in std::__1::vector<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>, std::__1::allocator<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> > >* nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>::create<std::__1::vector<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>, std::__1::allocator<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> > >>() json/src/json.hpp:7939
| #4 0x5a5fcf in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>::json_value::json_value(nlohmann::detail::value_t) json/src/json.hpp:8013:29
| #5 0x5a0061 in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>::basic_json(nlohmann::detail::value_t) json/src/json.hpp:8249:22
| #6 0x59ed6a in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int) json/src/json.hpp:5374:32
| #7 0x59bd2e in nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::parse_cbor_internal(bool) json/src/json.hpp:4717:24
| #8 0x5a4bd0 in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int)::{lambda()#1}::operator()() const json/src/json.hpp:5377:20
| #9 0x59ee2e in generate_n<std::__1::back_insert_iterator<std::__1::vector<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer>, std::__1::allocator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer> > > >, int, (lambda at ../src/json.hpp:5375:73)> /usr/local/include/c++/v1/algorithm:2186:20
| #10 0x59ee2e in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int) json/src/json.hpp:5375
| #11 0x59bd2e in nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::parse_cbor_internal(bool) json/src/json.hpp:4717:24
| #12 0x5a4bd0 in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int)::{lambda()#1}::operator()() const json/src/json.hpp:5377:20
| #13 0x59ee2e in generate_n<std::__1::back_insert_iterator<std::__1::vector<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer>, std::__1::allocator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer> > > >, int, (lambda at ../src/json.hpp:5375:73)> /usr/local/include/c++/v1/algorithm:2186:20
| #14 0x59ee2e in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int) json/src/json.hpp:5375
| #15 0x59bd2e in nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::parse_cbor_internal(bool) json/src/json.hpp:4717:24
| #16 0x5a4bd0 in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int)::{lambda()#1}::operator()() const json/src/json.hpp:5377:20
| #17 0x59ee2e in generate_n<std::__1::back_insert_iterator<std::__1::vector<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer>, std::__1::allocator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer> > > >, int, (lambda at ../src/json.hpp:5375:73)> /usr/local/include/c++/v1/algorithm:2186:20
| #18 0x59ee2e in nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::get_cbor_array<int>(int) json/src/json.hpp:5375
| #19 0x59bd2e in nlohmann::detail::binary_reader<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::parse_cbor_internal(bool) json/src/json.hpp:4717:24
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 27 (16 by maintainers)
FYI: The JSON parser in #971 is now non-recursive. It uses a
std::vector<bool>
to track the nesting of objects and arrays. This approach may also be applicable to the binary formats. In any case, it is now simpler to set and check a limit.@JoelStienlet That’s a pretty cool idea technically, but I’m not sure if it would be worth to maintain it / work around the problems, like:
Also, doing it dynamically adds some latency and allows untrusted payloads to be processed longer than required.
Still, I like the idea from a technical perspective - a pretty neat trick 😃