summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin McAllister <colin.mcallister@garmin.com>2025-07-07 16:39:43 -0500
committerArmin Kuster <akuster808@gmail.com>2025-07-13 14:36:35 -0400
commit9daee866d1b4567a40c7af8067f0ade213a7091d (patch)
tree365bbafea0947f5096a1d70c2209b55bd5d04c19
parentf73c3e4b7729798d3c90c9e568378f74c57fdd83 (diff)
downloadmeta-openembedded-9daee866d1b4567a40c7af8067f0ade213a7091d.tar.gz
jq: Fix CVEs
Adds backported patches to fix CVE-2024-23339, CVE-2024-53427, and CVE-2025-48060. Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com> Change-Id: Ibc2db956b7fd5d0388dbed1a81ddf9aa58431fb1 Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-devtools/jq/jq/CVE-2024-23337.patch219
-rw-r--r--meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-01.patch69
-rw-r--r--meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-02.patch56
-rw-r--r--meta-oe/recipes-devtools/jq/jq/CVE-2025-48060.patch46
-rw-r--r--meta-oe/recipes-devtools/jq/jq_git.bb8
5 files changed, 397 insertions, 1 deletions
diff --git a/meta-oe/recipes-devtools/jq/jq/CVE-2024-23337.patch b/meta-oe/recipes-devtools/jq/jq/CVE-2024-23337.patch
new file mode 100644
index 0000000000..87e639aad7
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/CVE-2024-23337.patch
@@ -0,0 +1,219 @@
1From 35cde320ac7ee9ad6da5ce422922fafe592c4c60 Mon Sep 17 00:00:00 2001
2From: itchyny <itchyny@cybozu.co.jp>
3Date: Wed, 21 May 2025 07:45:00 +0900
4Subject: [PATCH 1/2] Fix signed integer overflow in jvp_array_write and
5 jvp_object_rehash
6
7This commit fixes signed integer overflow and SEGV issues on growing
8arrays and objects. The size of arrays and objects is now limited to
9`536870912` (`0x20000000`). This fixes CVE-2024-23337 and fixes #3262.
10
11CVE: CVE-2024-23337
12Upstream-Status: Backport [https://github.com/jqlang/jq/commit/de21386681c0df0104a99d9d09db23a9b2a78b1e]
13Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
14---
15 src/jv.c | 45 ++++++++++++++++++++++++++++++++++++---------
16 src/jv_aux.c | 9 +++++----
17 tests/jq.test | 4 ++++
18 3 files changed, 45 insertions(+), 13 deletions(-)
19
20diff --git a/src/jv.c b/src/jv.c
21index 9784b22..33ccee9 100644
22--- a/src/jv.c
23+++ b/src/jv.c
24@@ -1006,6 +1006,11 @@ jv jv_array_set(jv j, int idx, jv val) {
25 jv_free(val);
26 return jv_invalid_with_msg(jv_string("Out of bounds negative array index"));
27 }
28+ if (idx > (INT_MAX >> 2) - jvp_array_offset(j)) {
29+ jv_free(j);
30+ jv_free(val);
31+ return jv_invalid_with_msg(jv_string("Array index too large"));
32+ }
33 // copy/free of val,j coalesced
34 jv* slot = jvp_array_write(&j, idx);
35 jv_free(*slot);
36@@ -1025,6 +1030,7 @@ jv jv_array_concat(jv a, jv b) {
37 // FIXME: could be faster
38 jv_array_foreach(b, i, elem) {
39 a = jv_array_append(a, elem);
40+ if (!jv_is_valid(a)) break;
41 }
42 jv_free(b);
43 return a;
44@@ -1296,6 +1302,7 @@ jv jv_string_indexes(jv j, jv k) {
45 p = jstr;
46 while ((p = _jq_memmem(p, (jstr + jlen) - p, idxstr, idxlen)) != NULL) {
47 a = jv_array_append(a, jv_number(p - jstr));
48+ if (!jv_is_valid(a)) break;
49 p += idxlen;
50 }
51 }
52@@ -1318,14 +1325,17 @@ jv jv_string_split(jv j, jv sep) {
53
54 if (seplen == 0) {
55 int c;
56- while ((jstr = jvp_utf8_next(jstr, jend, &c)))
57+ while ((jstr = jvp_utf8_next(jstr, jend, &c))) {
58 a = jv_array_append(a, jv_string_append_codepoint(jv_string(""), c));
59+ if (!jv_is_valid(a)) break;
60+ }
61 } else {
62 for (p = jstr; p < jend; p = s + seplen) {
63 s = _jq_memmem(p, jend - p, sepstr, seplen);
64 if (s == NULL)
65 s = jend;
66 a = jv_array_append(a, jv_string_sized(p, s - p));
67+ if (!jv_is_valid(a)) break;
68 // Add an empty string to denote that j ends on a sep
69 if (s + seplen == jend && seplen != 0)
70 a = jv_array_append(a, jv_string(""));
71@@ -1343,8 +1353,10 @@ jv jv_string_explode(jv j) {
72 const char* end = i + len;
73 jv a = jv_array_sized(len);
74 int c;
75- while ((i = jvp_utf8_next(i, end, &c)))
76+ while ((i = jvp_utf8_next(i, end, &c))) {
77 a = jv_array_append(a, jv_number(c));
78+ if (!jv_is_valid(a)) break;
79+ }
80 jv_free(j);
81 return a;
82 }
83@@ -1617,10 +1629,13 @@ static void jvp_object_free(jv o) {
84 }
85 }
86
87-static jv jvp_object_rehash(jv object) {
88+static int jvp_object_rehash(jv *objectp) {
89+ jv object = *objectp;
90 assert(JVP_HAS_KIND(object, JV_KIND_OBJECT));
91 assert(jvp_refcnt_unshared(object.u.ptr));
92 int size = jvp_object_size(object);
93+ if (size > INT_MAX >> 2)
94+ return 0;
95 jv new_object = jvp_object_new(size * 2);
96 for (int i=0; i<size; i++) {
97 struct object_slot* slot = jvp_object_get_slot(object, i);
98@@ -1633,7 +1648,8 @@ static jv jvp_object_rehash(jv object) {
99 }
100 // references are transported, just drop the old table
101 jv_mem_free(jvp_object_ptr(object));
102- return new_object;
103+ *objectp = new_object;
104+ return 1;
105 }
106
107 static jv jvp_object_unshare(jv object) {
108@@ -1662,27 +1678,32 @@ static jv jvp_object_unshare(jv object) {
109 return new_object;
110 }
111
112-static jv* jvp_object_write(jv* object, jv key) {
113+static int jvp_object_write(jv* object, jv key, jv **valpp) {
114 *object = jvp_object_unshare(*object);
115 int* bucket = jvp_object_find_bucket(*object, key);
116 struct object_slot* slot = jvp_object_find_slot(*object, key, bucket);
117 if (slot) {
118 // already has the key
119 jvp_string_free(key);
120- return &slot->value;
121+ *valpp = &slot->value;
122+ return 1;
123 }
124 slot = jvp_object_add_slot(*object, key, bucket);
125 if (slot) {
126 slot->value = jv_invalid();
127 } else {
128- *object = jvp_object_rehash(*object);
129+ if (!jvp_object_rehash(object)) {
130+ *valpp = NULL;
131+ return 0;
132+ }
133 bucket = jvp_object_find_bucket(*object, key);
134 assert(!jvp_object_find_slot(*object, key, bucket));
135 slot = jvp_object_add_slot(*object, key, bucket);
136 assert(slot);
137 slot->value = jv_invalid();
138 }
139- return &slot->value;
140+ *valpp = &slot->value;
141+ return 1;
142 }
143
144 static int jvp_object_delete(jv* object, jv key) {
145@@ -1783,7 +1804,11 @@ jv jv_object_set(jv object, jv key, jv value) {
146 assert(JVP_HAS_KIND(object, JV_KIND_OBJECT));
147 assert(JVP_HAS_KIND(key, JV_KIND_STRING));
148 // copy/free of object, key, value coalesced
149- jv* slot = jvp_object_write(&object, key);
150+ jv* slot;
151+ if (!jvp_object_write(&object, key, &slot)) {
152+ jv_free(object);
153+ return jv_invalid_with_msg(jv_string("Object too big"));
154+ }
155 jv_free(*slot);
156 *slot = value;
157 return object;
158@@ -1808,6 +1833,7 @@ jv jv_object_merge(jv a, jv b) {
159 assert(JVP_HAS_KIND(a, JV_KIND_OBJECT));
160 jv_object_foreach(b, k, v) {
161 a = jv_object_set(a, k, v);
162+ if (!jv_is_valid(a)) break;
163 }
164 jv_free(b);
165 return a;
166@@ -1827,6 +1853,7 @@ jv jv_object_merge_recursive(jv a, jv b) {
167 jv_free(elem);
168 a = jv_object_set(a, k, v);
169 }
170+ if (!jv_is_valid(a)) break;
171 }
172 jv_free(b);
173 return a;
174diff --git a/src/jv_aux.c b/src/jv_aux.c
175index 994285a..0753aef 100644
176--- a/src/jv_aux.c
177+++ b/src/jv_aux.c
178@@ -162,18 +162,19 @@ jv jv_set(jv t, jv k, jv v) {
179 if (slice_len < insert_len) {
180 // array is growing
181 int shift = insert_len - slice_len;
182- for (int i = array_len - 1; i >= end; i--) {
183+ for (int i = array_len - 1; i >= end && jv_is_valid(t); i--) {
184 t = jv_array_set(t, i + shift, jv_array_get(jv_copy(t), i));
185 }
186 } else if (slice_len > insert_len) {
187 // array is shrinking
188 int shift = slice_len - insert_len;
189- for (int i = end; i < array_len; i++) {
190+ for (int i = end; i < array_len && jv_is_valid(t); i++) {
191 t = jv_array_set(t, i - shift, jv_array_get(jv_copy(t), i));
192 }
193- t = jv_array_slice(t, 0, array_len - shift);
194+ if (jv_is_valid(t))
195+ t = jv_array_slice(t, 0, array_len - shift);
196 }
197- for (int i=0; i < insert_len; i++) {
198+ for (int i = 0; i < insert_len && jv_is_valid(t); i++) {
199 t = jv_array_set(t, start + i, jv_array_get(jv_copy(v), i));
200 }
201 jv_free(v);
202diff --git a/tests/jq.test b/tests/jq.test
203index 2d5c36b..c6c6ee5 100644
204--- a/tests/jq.test
205+++ b/tests/jq.test
206@@ -186,6 +186,10 @@ null
207 [0,1,2]
208 [0,5,2]
209
210+try (.[999999999] = 0) catch .
211+null
212+"Array index too large"
213+
214 #
215 # Multiple outputs, iteration
216 #
217--
2182.49.0
219
diff --git a/meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-01.patch b/meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-01.patch
new file mode 100644
index 0000000000..dbced0a1a3
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-01.patch
@@ -0,0 +1,69 @@
1From 4240af6a20465894dce871707271e11a05432dac Mon Sep 17 00:00:00 2001
2From: itchyny <itchyny@cybozu.co.jp>
3Date: Sun, 16 Feb 2025 22:08:36 +0900
4Subject: [PATCH 1/2] fix: `jv_number_value` should cache the double value of
5 literal numbers (#3245)
6
7The code of `jv_number_value` is intended to cache the double value of
8literal numbers, but it does not work because it accepts the `jv` struct
9by value. This patch fixes the behavior by checking if the double value
10is `NaN`, which indicates the unconverted value. This patch improves the
11performance of major use cases; e.g. `range(1000000)` runs 25% faster.
12
13CVE: CVE-2024-53427
14Upstream-Status: Backport [https://github.com/jqlang/jq/commit/b86ff49f46a4a37e5a8e75a140cb5fd6e1331384]
15Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
16---
17 src/jv.c | 13 +++++++------
18 1 file changed, 7 insertions(+), 6 deletions(-)
19
20diff --git a/src/jv.c b/src/jv.c
21index 4d7bba1..9051f65 100644
22--- a/src/jv.c
23+++ b/src/jv.c
24@@ -209,9 +209,6 @@ enum {
25 JVP_NUMBER_DECIMAL = 1
26 };
27
28-#define JV_NUMBER_SIZE_INIT (0)
29-#define JV_NUMBER_SIZE_CONVERTED (1)
30-
31 #define JVP_FLAGS_NUMBER_NATIVE JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0))
32 #define JVP_FLAGS_NUMBER_NATIVE_STR JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 1))
33 #define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
34@@ -619,8 +616,12 @@ static jv jvp_literal_number_new(const char * literal) {
35 jv_mem_free(n);
36 return JV_INVALID;
37 }
38+ if (decNumberIsNaN(&n->num_decimal)) {
39+ jv_mem_free(n);
40+ return jv_number(NAN);
41+ }
42
43- jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}};
44+ jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&n->refcnt}};
45 return r;
46 }
47
48@@ -719,9 +720,8 @@ double jv_number_value(jv j) {
49 if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) {
50 jvp_literal_number* n = jvp_literal_number_ptr(j);
51
52- if (j.size != JV_NUMBER_SIZE_CONVERTED) {
53+ if (isnan(n->num_double)) {
54 n->num_double = jvp_literal_number_to_double(j);
55- j.size = JV_NUMBER_SIZE_CONVERTED;
56 }
57
58 return n->num_double;
59@@ -755,6 +755,7 @@ int jvp_number_is_nan(jv n) {
60 } else {
61 return n.u.number != n.u.number;
62 }
63+ return isnan(n.u.number);
64 }
65
66 int jvp_number_cmp(jv a, jv b) {
67--
682.49.0
69
diff --git a/meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-02.patch b/meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-02.patch
new file mode 100644
index 0000000000..f650d28c85
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-02.patch
@@ -0,0 +1,56 @@
1From aea65caf03c129f3303d044044d2d1105be81b71 Mon Sep 17 00:00:00 2001
2From: itchyny <itchyny@cybozu.co.jp>
3Date: Wed, 5 Mar 2025 07:43:54 +0900
4Subject: [PATCH 2/2] Reject NaN with payload while parsing JSON
5
6This commit drops support for parsing NaN with payload in JSON like
7`NaN123` and fixes CVE-2024-53427. Other JSON extensions like `NaN` and
8`Infinity` are still supported. Fixes #3023, fixes #3196, fixes #3246.
9
10CVE: CVE-2024-53427
11Upstream-Status: Backport [https://github.com/jqlang/jq/commit/a09a4dfd55e6c24d04b35062ccfe4509748b1dd3]
12Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
13---
14 src/jv.c | 5 +++++
15 tests/jq.test | 12 ++++++++++++
16 2 files changed, 17 insertions(+)
17
18diff --git a/src/jv.c b/src/jv.c
19index 9051f65..4da5ba8 100644
20--- a/src/jv.c
21+++ b/src/jv.c
22@@ -617,6 +617,11 @@ static jv jvp_literal_number_new(const char * literal) {
23 return JV_INVALID;
24 }
25 if (decNumberIsNaN(&n->num_decimal)) {
26+ // Reject NaN with payload.
27+ if (n->num_decimal.digits > 1 || *n->num_decimal.lsu != 0) {
28+ jv_mem_free(n);
29+ return JV_INVALID;
30+ }
31 jv_mem_free(n);
32 return jv_number(NAN);
33 }
34diff --git a/tests/jq.test b/tests/jq.test
35index f783493..0ab21ef 100644
36--- a/tests/jq.test
37+++ b/tests/jq.test
38@@ -1724,3 +1724,15 @@ false
39 try 0[implode] catch .
40 []
41 "Cannot index number with string \"\""
42+
43+# NaN with payload is not parsed
44+.[] | try (fromjson | isnan) catch .
45+["NaN","-NaN","NaN1","NaN10","NaN100","NaN1000","NaN10000","NaN100000"]
46+true
47+true
48+"Invalid numeric literal at EOF at line 1, column 4 (while parsing 'NaN1')"
49+"Invalid numeric literal at EOF at line 1, column 5 (while parsing 'NaN10')"
50+"Invalid numeric literal at EOF at line 1, column 6 (while parsing 'NaN100')"
51+"Invalid numeric literal at EOF at line 1, column 7 (while parsing 'NaN1000')"
52+"Invalid numeric literal at EOF at line 1, column 8 (while parsing 'NaN10000')"
53+"Invalid numeric literal at EOF at line 1, column 9 (while parsing 'NaN100000')"
54--
552.49.0
56
diff --git a/meta-oe/recipes-devtools/jq/jq/CVE-2025-48060.patch b/meta-oe/recipes-devtools/jq/jq/CVE-2025-48060.patch
new file mode 100644
index 0000000000..909a4963c9
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/CVE-2025-48060.patch
@@ -0,0 +1,46 @@
1From 9e23fd7e88bb2d76ddf3fbfc805199f848cd1b92 Mon Sep 17 00:00:00 2001
2From: itchyny <itchyny@cybozu.co.jp>
3Date: Sat, 31 May 2025 11:46:40 +0900
4Subject: [PATCH 2/2] Fix heap buffer overflow when formatting an empty string
5
6The `jv_string_empty` did not properly null-terminate the string data,
7which could lead to a heap buffer overflow. The test case of
8GHSA-p7rr-28xf-3m5w (`0[""*0]`) was fixed by the commit dc849e9bb74a,
9but another case (`0[[]|implode]`) was still vulnerable. This commit
10ensures string data is properly null-terminated, and fixes CVE-2025-48060.
11
12CVE: CVE-2025-48060
13Upstream-Status: Backport [https://github.com/jqlang/jq/commit/c6e041699d8cd31b97375a2596217aff2cfca85b]
14Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
15---
16 src/jv.c | 1 +
17 tests/jq.test | 4 ++++
18 2 files changed, 5 insertions(+)
19
20diff --git a/src/jv.c b/src/jv.c
21index 33ccee9..4d7bba1 100644
22--- a/src/jv.c
23+++ b/src/jv.c
24@@ -1131,6 +1131,7 @@ static jv jvp_string_empty_new(uint32_t length) {
25 jvp_string* s = jvp_string_alloc(length);
26 s->length_hashed = 0;
27 memset(s->data, 0, length);
28+ s->data[length] = 0;
29 jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}};
30 return r;
31 }
32diff --git a/tests/jq.test b/tests/jq.test
33index c6c6ee5..f783493 100644
34--- a/tests/jq.test
35+++ b/tests/jq.test
36@@ -1720,3 +1720,7 @@ false
37 . |= try . catch .
38 1
39 1
40+
41+try 0[implode] catch .
42+[]
43+"Cannot index number with string \"\""
44--
452.49.0
46
diff --git a/meta-oe/recipes-devtools/jq/jq_git.bb b/meta-oe/recipes-devtools/jq/jq_git.bb
index 8b0218c83e..d36723cff4 100644
--- a/meta-oe/recipes-devtools/jq/jq_git.bb
+++ b/meta-oe/recipes-devtools/jq/jq_git.bb
@@ -9,7 +9,13 @@ LICENSE = "MIT"
9LIC_FILES_CHKSUM = "file://COPYING;md5=2814b59e00e7918c864fa3b6bbe049b4" 9LIC_FILES_CHKSUM = "file://COPYING;md5=2814b59e00e7918c864fa3b6bbe049b4"
10 10
11PV = "1.6+git${SRCPV}" 11PV = "1.6+git${SRCPV}"
12SRC_URI = "git://github.com/stedolan/jq;protocol=https;branch=master" 12SRC_URI = " \
13 git://github.com/stedolan/jq;protocol=https;branch=master \
14 file://CVE-2024-23337.patch \
15 file://CVE-2025-48060.patch \
16 file://CVE-2024-53427-01.patch \
17 file://CVE-2024-53427-02.patch \
18 "
13SRCREV = "a9f97e9e61a910a374a5d768244e8ad63f407d3e" 19SRCREV = "a9f97e9e61a910a374a5d768244e8ad63f407d3e"
14S = "${WORKDIR}/git" 20S = "${WORKDIR}/git"
15 21