new file mode 100644
@@ -0,0 +1,219 @@
+From 35cde320ac7ee9ad6da5ce422922fafe592c4c60 Mon Sep 17 00:00:00 2001
+From: itchyny <itchyny@cybozu.co.jp>
+Date: Wed, 21 May 2025 07:45:00 +0900
+Subject: [PATCH 1/2] Fix signed integer overflow in jvp_array_write and
+ jvp_object_rehash
+
+This commit fixes signed integer overflow and SEGV issues on growing
+arrays and objects. The size of arrays and objects is now limited to
+`536870912` (`0x20000000`). This fixes CVE-2024-23337 and fixes #3262.
+
+CVE: CVE-2024-23337
+Upstream-Status: Backport [https://github.com/jqlang/jq/commit/de21386681c0df0104a99d9d09db23a9b2a78b1e]
+Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
+---
+ src/jv.c | 45 ++++++++++++++++++++++++++++++++++++---------
+ src/jv_aux.c | 9 +++++----
+ tests/jq.test | 4 ++++
+ 3 files changed, 45 insertions(+), 13 deletions(-)
+
+diff --git a/src/jv.c b/src/jv.c
+index 9784b22..33ccee9 100644
+--- a/src/jv.c
++++ b/src/jv.c
+@@ -1006,6 +1006,11 @@ jv jv_array_set(jv j, int idx, jv val) {
+ jv_free(val);
+ return jv_invalid_with_msg(jv_string("Out of bounds negative array index"));
+ }
++ if (idx > (INT_MAX >> 2) - jvp_array_offset(j)) {
++ jv_free(j);
++ jv_free(val);
++ return jv_invalid_with_msg(jv_string("Array index too large"));
++ }
+ // copy/free of val,j coalesced
+ jv* slot = jvp_array_write(&j, idx);
+ jv_free(*slot);
+@@ -1025,6 +1030,7 @@ jv jv_array_concat(jv a, jv b) {
+ // FIXME: could be faster
+ jv_array_foreach(b, i, elem) {
+ a = jv_array_append(a, elem);
++ if (!jv_is_valid(a)) break;
+ }
+ jv_free(b);
+ return a;
+@@ -1296,6 +1302,7 @@ jv jv_string_indexes(jv j, jv k) {
+ p = jstr;
+ while ((p = _jq_memmem(p, (jstr + jlen) - p, idxstr, idxlen)) != NULL) {
+ a = jv_array_append(a, jv_number(p - jstr));
++ if (!jv_is_valid(a)) break;
+ p += idxlen;
+ }
+ }
+@@ -1318,14 +1325,17 @@ jv jv_string_split(jv j, jv sep) {
+
+ if (seplen == 0) {
+ int c;
+- while ((jstr = jvp_utf8_next(jstr, jend, &c)))
++ while ((jstr = jvp_utf8_next(jstr, jend, &c))) {
+ a = jv_array_append(a, jv_string_append_codepoint(jv_string(""), c));
++ if (!jv_is_valid(a)) break;
++ }
+ } else {
+ for (p = jstr; p < jend; p = s + seplen) {
+ s = _jq_memmem(p, jend - p, sepstr, seplen);
+ if (s == NULL)
+ s = jend;
+ a = jv_array_append(a, jv_string_sized(p, s - p));
++ if (!jv_is_valid(a)) break;
+ // Add an empty string to denote that j ends on a sep
+ if (s + seplen == jend && seplen != 0)
+ a = jv_array_append(a, jv_string(""));
+@@ -1343,8 +1353,10 @@ jv jv_string_explode(jv j) {
+ const char* end = i + len;
+ jv a = jv_array_sized(len);
+ int c;
+- while ((i = jvp_utf8_next(i, end, &c)))
++ while ((i = jvp_utf8_next(i, end, &c))) {
+ a = jv_array_append(a, jv_number(c));
++ if (!jv_is_valid(a)) break;
++ }
+ jv_free(j);
+ return a;
+ }
+@@ -1617,10 +1629,13 @@ static void jvp_object_free(jv o) {
+ }
+ }
+
+-static jv jvp_object_rehash(jv object) {
++static int jvp_object_rehash(jv *objectp) {
++ jv object = *objectp;
+ assert(JVP_HAS_KIND(object, JV_KIND_OBJECT));
+ assert(jvp_refcnt_unshared(object.u.ptr));
+ int size = jvp_object_size(object);
++ if (size > INT_MAX >> 2)
++ return 0;
+ jv new_object = jvp_object_new(size * 2);
+ for (int i=0; i<size; i++) {
+ struct object_slot* slot = jvp_object_get_slot(object, i);
+@@ -1633,7 +1648,8 @@ static jv jvp_object_rehash(jv object) {
+ }
+ // references are transported, just drop the old table
+ jv_mem_free(jvp_object_ptr(object));
+- return new_object;
++ *objectp = new_object;
++ return 1;
+ }
+
+ static jv jvp_object_unshare(jv object) {
+@@ -1662,27 +1678,32 @@ static jv jvp_object_unshare(jv object) {
+ return new_object;
+ }
+
+-static jv* jvp_object_write(jv* object, jv key) {
++static int jvp_object_write(jv* object, jv key, jv **valpp) {
+ *object = jvp_object_unshare(*object);
+ int* bucket = jvp_object_find_bucket(*object, key);
+ struct object_slot* slot = jvp_object_find_slot(*object, key, bucket);
+ if (slot) {
+ // already has the key
+ jvp_string_free(key);
+- return &slot->value;
++ *valpp = &slot->value;
++ return 1;
+ }
+ slot = jvp_object_add_slot(*object, key, bucket);
+ if (slot) {
+ slot->value = jv_invalid();
+ } else {
+- *object = jvp_object_rehash(*object);
++ if (!jvp_object_rehash(object)) {
++ *valpp = NULL;
++ return 0;
++ }
+ bucket = jvp_object_find_bucket(*object, key);
+ assert(!jvp_object_find_slot(*object, key, bucket));
+ slot = jvp_object_add_slot(*object, key, bucket);
+ assert(slot);
+ slot->value = jv_invalid();
+ }
+- return &slot->value;
++ *valpp = &slot->value;
++ return 1;
+ }
+
+ static int jvp_object_delete(jv* object, jv key) {
+@@ -1783,7 +1804,11 @@ jv jv_object_set(jv object, jv key, jv value) {
+ assert(JVP_HAS_KIND(object, JV_KIND_OBJECT));
+ assert(JVP_HAS_KIND(key, JV_KIND_STRING));
+ // copy/free of object, key, value coalesced
+- jv* slot = jvp_object_write(&object, key);
++ jv* slot;
++ if (!jvp_object_write(&object, key, &slot)) {
++ jv_free(object);
++ return jv_invalid_with_msg(jv_string("Object too big"));
++ }
+ jv_free(*slot);
+ *slot = value;
+ return object;
+@@ -1808,6 +1833,7 @@ jv jv_object_merge(jv a, jv b) {
+ assert(JVP_HAS_KIND(a, JV_KIND_OBJECT));
+ jv_object_foreach(b, k, v) {
+ a = jv_object_set(a, k, v);
++ if (!jv_is_valid(a)) break;
+ }
+ jv_free(b);
+ return a;
+@@ -1827,6 +1853,7 @@ jv jv_object_merge_recursive(jv a, jv b) {
+ jv_free(elem);
+ a = jv_object_set(a, k, v);
+ }
++ if (!jv_is_valid(a)) break;
+ }
+ jv_free(b);
+ return a;
+diff --git a/src/jv_aux.c b/src/jv_aux.c
+index 994285a..0753aef 100644
+--- a/src/jv_aux.c
++++ b/src/jv_aux.c
+@@ -162,18 +162,19 @@ jv jv_set(jv t, jv k, jv v) {
+ if (slice_len < insert_len) {
+ // array is growing
+ int shift = insert_len - slice_len;
+- for (int i = array_len - 1; i >= end; i--) {
++ for (int i = array_len - 1; i >= end && jv_is_valid(t); i--) {
+ t = jv_array_set(t, i + shift, jv_array_get(jv_copy(t), i));
+ }
+ } else if (slice_len > insert_len) {
+ // array is shrinking
+ int shift = slice_len - insert_len;
+- for (int i = end; i < array_len; i++) {
++ for (int i = end; i < array_len && jv_is_valid(t); i++) {
+ t = jv_array_set(t, i - shift, jv_array_get(jv_copy(t), i));
+ }
+- t = jv_array_slice(t, 0, array_len - shift);
++ if (jv_is_valid(t))
++ t = jv_array_slice(t, 0, array_len - shift);
+ }
+- for (int i=0; i < insert_len; i++) {
++ for (int i = 0; i < insert_len && jv_is_valid(t); i++) {
+ t = jv_array_set(t, start + i, jv_array_get(jv_copy(v), i));
+ }
+ jv_free(v);
+diff --git a/tests/jq.test b/tests/jq.test
+index 2d5c36b..c6c6ee5 100644
+--- a/tests/jq.test
++++ b/tests/jq.test
+@@ -186,6 +186,10 @@ null
+ [0,1,2]
+ [0,5,2]
+
++try (.[999999999] = 0) catch .
++null
++"Array index too large"
++
+ #
+ # Multiple outputs, iteration
+ #
+--
+2.49.0
+
new file mode 100644
@@ -0,0 +1,46 @@
+From 9e23fd7e88bb2d76ddf3fbfc805199f848cd1b92 Mon Sep 17 00:00:00 2001
+From: itchyny <itchyny@cybozu.co.jp>
+Date: Sat, 31 May 2025 11:46:40 +0900
+Subject: [PATCH 2/2] Fix heap buffer overflow when formatting an empty string
+
+The `jv_string_empty` did not properly null-terminate the string data,
+which could lead to a heap buffer overflow. The test case of
+GHSA-p7rr-28xf-3m5w (`0[""*0]`) was fixed by the commit dc849e9bb74a,
+but another case (`0[[]|implode]`) was still vulnerable. This commit
+ensures string data is properly null-terminated, and fixes CVE-2025-48060.
+
+CVE: CVE-2025-48060
+Upstream-Status: Backport [https://github.com/jqlang/jq/commit/c6e041699d8cd31b97375a2596217aff2cfca85b]
+Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
+---
+ src/jv.c | 1 +
+ tests/jq.test | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/src/jv.c b/src/jv.c
+index 33ccee9..4d7bba1 100644
+--- a/src/jv.c
++++ b/src/jv.c
+@@ -1131,6 +1131,7 @@ static jv jvp_string_empty_new(uint32_t length) {
+ jvp_string* s = jvp_string_alloc(length);
+ s->length_hashed = 0;
+ memset(s->data, 0, length);
++ s->data[length] = 0;
+ jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}};
+ return r;
+ }
+diff --git a/tests/jq.test b/tests/jq.test
+index c6c6ee5..f783493 100644
+--- a/tests/jq.test
++++ b/tests/jq.test
+@@ -1720,3 +1720,7 @@ false
+ . |= try . catch .
+ 1
+ 1
++
++try 0[implode] catch .
++[]
++"Cannot index number with string \"\""
+--
+2.49.0
+
@@ -9,7 +9,11 @@ LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=2814b59e00e7918c864fa3b6bbe049b4"
PV = "1.6+git${SRCPV}"
-SRC_URI = "git://github.com/stedolan/jq;protocol=https;branch=master"
+SRC_URI = " \
+ git://github.com/stedolan/jq;protocol=https;branch=master \
+ file://CVE-2024-23337.patch \
+ file://CVE-2025-48060.patch \
+ "
SRCREV = "a9f97e9e61a910a374a5d768244e8ad63f407d3e"
S = "${WORKDIR}/git"
Adds backported patches to fix CVE-2024-23337 & CVE-2025-48060. Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com> --- .../jq/jq/CVE-2024-23337.patch | 219 ++++++++++++++++++ .../jq/jq/CVE-2025-48060.patch | 46 ++++ meta-oe/recipes-devtools/jq/jq_git.bb | 6 +- 3 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 meta-oe/recipes-devtools/jq/jq/CVE-2024-23337.patch create mode 100644 meta-oe/recipes-devtools/jq/jq/CVE-2025-48060.patch