From 19f1754a2a9db3f6a84b2e611b8956fd51ad748e Mon Sep 17 00:00:00 2001 From: Frank LENORMAND Date: Wed, 13 Nov 2019 10:30:25 +0100 Subject: [PATCH] src json: Limit the recursion depth to 100 --- src/json.cc | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/json.cc b/src/json.cc index dcb4005a..82db4576 100644 --- a/src/json.cc +++ b/src/json.cc @@ -40,11 +40,16 @@ String to_json(StringView str) static bool is_digit(char c) { return c >= '0' and c <= '9'; } -JsonResult parse_json(const char* pos, const char* end) +static constexpr size_t max_parsing_depth = 100; + +JsonResult parse_json_impl(const char* pos, const char* end, size_t depth) { if (not skip_while(pos, end, is_blank)) return {}; + if (depth >= max_parsing_depth) + throw runtime_error("maximum parsing depth reached"); + if (is_digit(*pos) or *pos == '-') { auto digit_end = pos + 1; @@ -90,7 +95,7 @@ JsonResult parse_json(const char* pos, const char* end) while (true) { - auto [element, new_pos] = parse_json(pos, end); + auto [element, new_pos] = parse_json_impl(pos, end, depth+1); if (not element) return {}; pos = new_pos; @@ -116,7 +121,7 @@ JsonResult parse_json(const char* pos, const char* end) while (true) { - auto [name_value, name_end] = parse_json(pos, end); + auto [name_value, name_end] = parse_json_impl(pos, end, depth+1); if (not name_value) return {}; pos = name_end; @@ -126,7 +131,7 @@ JsonResult parse_json(const char* pos, const char* end) if (*pos++ != ':') throw runtime_error("expected :"); - auto [element, element_end] = parse_json(pos, end); + auto [element, element_end] = parse_json_impl(pos, end, depth+1); if (not element) return {}; pos = element_end; @@ -145,7 +150,8 @@ JsonResult parse_json(const char* pos, const char* end) throw runtime_error("unable to parse json"); } -JsonResult parse_json(StringView json) { return parse_json(json.begin(), json.end()); } +JsonResult parse_json(const char* pos, const char* end) { return parse_json_impl(pos, end, 0); } +JsonResult parse_json(StringView json) { return parse_json_impl(json.begin(), json.end(), 0); } UnitTest test_json_parser{[]() { @@ -170,6 +176,16 @@ UnitTest test_json_parser{[]() kak_assert(value and value.is_a()); kak_assert(value.as().empty()); } + + { + String big_nested_array = {"", max_parsing_depth*2+2}; + for (size_t i = 0; i < max_parsing_depth+1; i++) + { + big_nested_array[i] = '['; + big_nested_array[i+max_parsing_depth+1] = ']'; + } + kak_expect_throw(runtime_error, parse_json(big_nested_array)); + } }}; }