sd-json: limit the stack depth during parsing as well

This commit is contained in:
Frantisek Sumsal
2026-04-10 21:33:11 +01:00
committed by Luca Boccassi
parent 5cd61c1330
commit 1016dd315f
2 changed files with 55 additions and 0 deletions
+12
View File
@@ -3122,6 +3122,12 @@ static int json_parse_internal(
goto finish;
}
/* n_stack includes the top level entry, hence > instead of >= */
if (n_stack > DEPTH_MAX) {
r = -ELNRNG;
goto finish;
}
if (!GREEDY_REALLOC(stack, n_stack+1)) {
r = -ENOMEM;
goto finish;
@@ -3178,6 +3184,12 @@ static int json_parse_internal(
goto finish;
}
/* n_stack includes the top level entry, hence > instead of >= */
if (n_stack > DEPTH_MAX) {
r = -ELNRNG;
goto finish;
}
if (!GREEDY_REALLOC(stack, n_stack+1)) {
r = -ENOMEM;
goto finish;
+43
View File
@@ -556,6 +556,49 @@ TEST(depth) {
fputs("\n", stdout);
}
static char *prepare_nested_json(const char *open, unsigned depth) {
char *s, *p;
size_t olen;
assert_se(open);
olen = strlen(open);
s = p = new(char, olen * depth + 1);
if (!s)
return NULL;
for (unsigned i = 0; i < depth; i++)
p = mempcpy(p, open, olen);
*p = '\0';
return s;
}
TEST(parse_depth) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
_cleanup_free_ char *s = NULL;
/* Refuse parsing > DEPTH_MAX (currently 2048) levels of nested arrays */
s = prepare_nested_json("[", 2049);
ASSERT_ERROR(sd_json_parse(s, 0, &v, NULL, NULL), ELNRNG);
s = mfree(s);
/* Same for nested objects */
s = prepare_nested_json("{\"a\":", 2049);
ASSERT_ERROR(sd_json_parse(s, 0, &v, NULL, NULL), ELNRNG);
s = mfree(s);
/* <= DEPTH_MAX levels of nested arrays should be refused by EINVAL
* later in the parsing process */
s = prepare_nested_json("[", 2048);
ASSERT_ERROR(sd_json_parse(s, 0, &v, NULL, NULL), EINVAL);
s = mfree(s);
/* And the same for nested objects */
s = prepare_nested_json("{\"a\":", 2048);
ASSERT_ERROR(sd_json_parse(s, 0, &v, NULL, NULL), EINVAL);
}
TEST(normalize) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL, *w = NULL;
_cleanup_free_ char *t = NULL;