summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrank LENORMAND <lenormf@gmail.com>2019-11-13 10:30:25 +0100
committerFrank LENORMAND <lenormf@gmail.com>2019-11-17 09:27:46 +0100
commit19f1754a2a9db3f6a84b2e611b8956fd51ad748e (patch)
tree08fbf9d33c28d2b27b543a7f57bec814e07f4f96 /src
parent7cdbe1d3d24c1cc13bd7cbc3fe252f1e88747ffb (diff)
src json: Limit the recursion depth to 100
Diffstat (limited to 'src')
-rw-r--r--src/json.cc26
1 files 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<JsonObject>());
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));
+ }
}};
}