From fb59f1491058d58bdc3e8dd28f1773d1ac690a1f Mon Sep 17 00:00:00 2001 From: itchyny Date: Mon, 13 Apr 2026 11:23:40 +0900 Subject: [PATCH] Limit path depth to prevent stack overflow Deeply nested path arrays can cause unbounded recursion in `jv_setpath`, `jv_getpath`, and `jv_delpaths`, leading to stack overflow. Add a depth limit of 10000 to match the existing `tojson` depth limit. This fixes CVE-2026-33947. CVE: CVE-2026-33947 Upstream: https://github.com/jqlang/jq/commit/fb59f1491058d58bdc3e8dd28f1773d1ac690a1f [thomas: remove tests] Signed-off-by: Thomas Perale --- src/jv_aux.c | 21 +++++++++++++++++++++ tests/jq.test | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/jv_aux.c b/src/jv_aux.c index 018f380b10..fd5ff96684 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -375,6 +375,10 @@ static jv jv_dels(jv t, jv keys) { return t; } +#ifndef MAX_PATH_DEPTH +#define MAX_PATH_DEPTH (10000) +#endif + jv jv_setpath(jv root, jv path, jv value) { if (jv_get_kind(path) != JV_KIND_ARRAY) { jv_free(value); @@ -382,6 +386,12 @@ jv jv_setpath(jv root, jv path, jv value) { jv_free(path); return jv_invalid_with_msg(jv_string("Path must be specified as an array")); } + if (jv_array_length(jv_copy(path)) > MAX_PATH_DEPTH) { + jv_free(value); + jv_free(root); + jv_free(path); + return jv_invalid_with_msg(jv_string("Path too deep")); + } if (!jv_is_valid(root)){ jv_free(value); jv_free(path); @@ -434,6 +444,11 @@ jv jv_getpath(jv root, jv path) { jv_free(path); return jv_invalid_with_msg(jv_string("Path must be specified as an array")); } + if (jv_array_length(jv_copy(path)) > MAX_PATH_DEPTH) { + jv_free(root); + jv_free(path); + return jv_invalid_with_msg(jv_string("Path too deep")); + } if (!jv_is_valid(root)) { jv_free(path); return root; @@ -511,6 +526,12 @@ jv jv_delpaths(jv object, jv paths) { jv_free(elem); return err; } + if (jv_array_length(jv_copy(elem)) > MAX_PATH_DEPTH) { + jv_free(object); + jv_free(paths); + jv_free(elem); + return jv_invalid_with_msg(jv_string("Path too deep")); + } jv_free(elem); } if (jv_array_length(jv_copy(paths)) == 0) {