Limit recursive object merge depth to prevent stack overflow
This fixes CVE-2026-43896.
This commit is contained in:
1 parent
33d7bce321
commit
532ccea608
2 files changed
+32
-2
No files matched your search
@@ -1899,16 +1899,33 @@ jv jv_object_merge(jv a, jv b) {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
jv jv_object_merge_recursive(jv a, jv b) {
|
#ifndef MAX_OBJECT_MERGE_DEPTH
|
||||||
|
#define MAX_OBJECT_MERGE_DEPTH (10000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static jv jvp_object_merge_recursive(jv a, jv b, int depth) {
|
||||||
assert(JVP_HAS_KIND(a, JV_KIND_OBJECT));
|
assert(JVP_HAS_KIND(a, JV_KIND_OBJECT));
|
||||||
assert(JVP_HAS_KIND(b, JV_KIND_OBJECT));
|
assert(JVP_HAS_KIND(b, JV_KIND_OBJECT));
|
||||||
|
|
||||||
|
if (depth > MAX_OBJECT_MERGE_DEPTH) {
|
||||||
|
jv_free(a);
|
||||||
|
jv_free(b);
|
||||||
|
return jv_invalid_with_msg(jv_string("Object merge too deep"));
|
||||||
|
}
|
||||||
|
|
||||||
jv_object_foreach(b, k, v) {
|
jv_object_foreach(b, k, v) {
|
||||||
jv elem = jv_object_get(jv_copy(a), jv_copy(k));
|
jv elem = jv_object_get(jv_copy(a), jv_copy(k));
|
||||||
if (jv_is_valid(elem) &&
|
if (jv_is_valid(elem) &&
|
||||||
JVP_HAS_KIND(elem, JV_KIND_OBJECT) &&
|
JVP_HAS_KIND(elem, JV_KIND_OBJECT) &&
|
||||||
JVP_HAS_KIND(v, JV_KIND_OBJECT)) {
|
JVP_HAS_KIND(v, JV_KIND_OBJECT)) {
|
||||||
a = jv_object_set(a, k, jv_object_merge_recursive(elem, v));
|
jv merged = jvp_object_merge_recursive(elem, v, depth + 1);
|
||||||
|
if (!jv_is_valid(merged)) {
|
||||||
|
jv_free(k);
|
||||||
|
jv_free(a);
|
||||||
|
jv_free(b);
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
a = jv_object_set(a, k, merged);
|
||||||
} else {
|
} else {
|
||||||
jv_free(elem);
|
jv_free(elem);
|
||||||
a = jv_object_set(a, k, v);
|
a = jv_object_set(a, k, v);
|
||||||
@@ -1919,6 +1936,10 @@ jv jv_object_merge_recursive(jv a, jv b) {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jv jv_object_merge_recursive(jv a, jv b) {
|
||||||
|
return jvp_object_merge_recursive(a, b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Object iteration (internal helpers)
|
* Object iteration (internal helpers)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2602,3 +2602,12 @@ true
|
|||||||
try (reduce range(10001) as $_ ([]; [.]) as $x | $x | contains($x)) catch .
|
try (reduce range(10001) as $_ ([]; [.]) as $x | $x | contains($x)) catch .
|
||||||
null
|
null
|
||||||
"Containment check too deep"
|
"Containment check too deep"
|
||||||
|
|
||||||
|
# regression test for CVE-2026-43896
|
||||||
|
reduce range(10000) as $_ ({}; {a: .}) as $x | $x * $x | length
|
||||||
|
null
|
||||||
|
1
|
||||||
|
|
||||||
|
try (reduce range(10001) as $_ ({}; {a: .}) as $x | $x * $x) catch .
|
||||||
|
null
|
||||||
|
"Object merge too deep"
|
||||||
Reference in new issue
Block a user