src json: Limit the recursion depth to 100

This commit is contained in:
Frank LENORMAND 2019-11-13 10:30:25 +01:00
parent 7cdbe1d3d2
commit 19f1754a2a

View File

@ -40,11 +40,16 @@ String to_json(StringView str)
static bool is_digit(char c) { return c >= '0' and c <= '9'; } 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)) if (not skip_while(pos, end, is_blank))
return {}; return {};
if (depth >= max_parsing_depth)
throw runtime_error("maximum parsing depth reached");
if (is_digit(*pos) or *pos == '-') if (is_digit(*pos) or *pos == '-')
{ {
auto digit_end = pos + 1; auto digit_end = pos + 1;
@ -90,7 +95,7 @@ JsonResult parse_json(const char* pos, const char* end)
while (true) while (true)
{ {
auto [element, new_pos] = parse_json(pos, end); auto [element, new_pos] = parse_json_impl(pos, end, depth+1);
if (not element) if (not element)
return {}; return {};
pos = new_pos; pos = new_pos;
@ -116,7 +121,7 @@ JsonResult parse_json(const char* pos, const char* end)
while (true) 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) if (not name_value)
return {}; return {};
pos = name_end; pos = name_end;
@ -126,7 +131,7 @@ JsonResult parse_json(const char* pos, const char* end)
if (*pos++ != ':') if (*pos++ != ':')
throw runtime_error("expected :"); 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) if (not element)
return {}; return {};
pos = element_end; pos = element_end;
@ -145,7 +150,8 @@ JsonResult parse_json(const char* pos, const char* end)
throw runtime_error("unable to parse json"); 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{[]() UnitTest test_json_parser{[]()
{ {
@ -170,6 +176,16 @@ UnitTest test_json_parser{[]()
kak_assert(value and value.is_a<JsonObject>()); kak_assert(value and value.is_a<JsonObject>());
kak_assert(value.as<JsonObject>().empty()); kak_assert(value.as<JsonObject>().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));
}
}}; }};
} }