Skip to content

Commit 439b873

Browse files
committed
jq: apply patches for CVE-2026-32316, CVE-2026-33947, CVE-2026-33948, CVE-2026-39979 & CVE-2026-40164
1 parent 91a301b commit 439b873

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
From fb59f1491058d58bdc3e8dd28f1773d1ac690a1f Mon Sep 17 00:00:00 2001
2+
From: itchyny <itchyny@cybozu.co.jp>
3+
Date: Mon, 13 Apr 2026 11:23:40 +0900
4+
Subject: [PATCH] Limit path depth to prevent stack overflow
5+
6+
Deeply nested path arrays can cause unbounded recursion in
7+
`jv_setpath`, `jv_getpath`, and `jv_delpaths`, leading to
8+
stack overflow. Add a depth limit of 10000 to match the
9+
existing `tojson` depth limit. This fixes CVE-2026-33947.
10+
---
11+
src/jv_aux.c | 21 +++++++++++++++++++++
12+
1 file changed, 21 insertions(+)
13+
14+
diff --git a/src/jv_aux.c b/src/jv_aux.c
15+
index 018f380b10..fd5ff96684 100644
16+
--- a/src/jv_aux.c
17+
+++ b/src/jv_aux.c
18+
@@ -365,6 +365,10 @@ static jv jv_dels(jv t, jv keys) {
19+
return t;
20+
}
21+
22+
+#ifndef MAX_PATH_DEPTH
23+
+#define MAX_PATH_DEPTH (10000)
24+
+#endif
25+
+
26+
jv jv_setpath(jv root, jv path, jv value) {
27+
if (jv_get_kind(path) != JV_KIND_ARRAY) {
28+
jv_free(value);
29+
@@ -372,6 +376,12 @@ jv jv_setpath(jv root, jv path, jv value) {
30+
jv_free(path);
31+
return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
32+
}
33+
+ if (jv_array_length(jv_copy(path)) > MAX_PATH_DEPTH) {
34+
+ jv_free(value);
35+
+ jv_free(root);
36+
+ jv_free(path);
37+
+ return jv_invalid_with_msg(jv_string("Path too deep"));
38+
+ }
39+
if (!jv_is_valid(root)){
40+
jv_free(value);
41+
jv_free(path);
42+
@@ -424,6 +434,11 @@ jv jv_getpath(jv root, jv path) {
43+
jv_free(path);
44+
return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
45+
}
46+
+ if (jv_array_length(jv_copy(path)) > MAX_PATH_DEPTH) {
47+
+ jv_free(root);
48+
+ jv_free(path);
49+
+ return jv_invalid_with_msg(jv_string("Path too deep"));
50+
+ }
51+
if (!jv_is_valid(root)) {
52+
jv_free(path);
53+
return root;
54+
@@ -502,6 +517,12 @@ jv jv_delpaths(jv object, jv paths) {
55+
jv_free(elem);
56+
return err;
57+
}
58+
+ if (jv_array_length(jv_copy(elem)) > MAX_PATH_DEPTH) {
59+
+ jv_free(object);
60+
+ jv_free(paths);
61+
+ jv_free(elem);
62+
+ return jv_invalid_with_msg(jv_string("Path too deep"));
63+
+ }
64+
jv_free(elem);
65+
}
66+
if (jv_array_length(jv_copy(paths)) == 0) {

pkgs/by-name/jq/jq/package.nix

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ stdenv.mkDerivation (finalAttrs: {
3232

3333
patches = [
3434
./musl.patch
35+
# CVE-2026-32316: integer overflow in jvp_string_append allows heap buffer overflow
36+
(fetchurl {
37+
url = "https://github.com/jqlang/jq/commit/e47e56d226519635768e6aab2f38f0ab037c09e5.patch";
38+
hash = "sha256-33WZJ3Klw7wwHz68yh/4qPWV8V4MFfqzBR332phtiY4=";
39+
})
40+
# CVE-2026-33948: NUL truncation in CLI JSON input path
41+
(fetchurl {
42+
url = "https://github.com/jqlang/jq/commit/6374ae0bcdfe33a18eb0ae6db28493b1f34a0a5b.patch";
43+
hash = "sha256-jXilw3tjsju1KlMyBrlo5CaKrRz38ONHgITDsbTjtEw=";
44+
})
45+
# CVE-2026-39979: out-of-bounds read in jv_parse_sized() error formatting
46+
(fetchurl {
47+
url = "https://github.com/jqlang/jq/commit/2f09060afab23fe9390cce7cb860b10416e1bf5f.patch";
48+
hash = "sha256-jB7fbllnvf++zRiiYk2jxuDkG9fnZO7acT+GMaQk/Mg=";
49+
})
50+
# CVE-2026-40164: hash collision DoS via hardcoded MurmurHash3 seed
51+
(fetchurl {
52+
url = "https://github.com/jqlang/jq/commit/0c7d133c3c7e37c00b6d46b658a02244fdd3c784.patch";
53+
hash = "sha256-Sgrtm/090o+eBrzE1vj3VIkP+W+5VwJnYsMCM/rn0E8=";
54+
})
55+
# CVE-2026-33947: unbounded recursion in jv_setpath/jv_getpath/delpaths_sorted
56+
# Test hunk removed: depends on tests added after 1.8.1 (upstream commit fdf8ef0f)
57+
./CVE-2026-33947.patch
3558
]
3659
++ lib.optionals stdenv.hostPlatform.is32bit [
3760
# needed because epoch conversion test here is right at the end of 32 bit integer space

0 commit comments

Comments
 (0)