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,69 @@
+From 4240af6a20465894dce871707271e11a05432dac Mon Sep 17 00:00:00 2001
+From: itchyny <itchyny@cybozu.co.jp>
+Date: Sun, 16 Feb 2025 22:08:36 +0900
+Subject: [PATCH 1/2] fix: `jv_number_value` should cache the double value of
+ literal numbers (#3245)
+
+The code of `jv_number_value` is intended to cache the double value of
+literal numbers, but it does not work because it accepts the `jv` struct
+by value. This patch fixes the behavior by checking if the double value
+is `NaN`, which indicates the unconverted value. This patch improves the
+performance of major use cases; e.g. `range(1000000)` runs 25% faster.
+
+CVE: CVE-2024-53427
+Upstream-Status: Backport [https://github.com/jqlang/jq/commit/b86ff49f46a4a37e5a8e75a140cb5fd6e1331384]
+Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
+---
+ src/jv.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/src/jv.c b/src/jv.c
+index 4d7bba1..9051f65 100644
+--- a/src/jv.c
++++ b/src/jv.c
+@@ -209,9 +209,6 @@ enum {
+ JVP_NUMBER_DECIMAL = 1
+ };
+
+-#define JV_NUMBER_SIZE_INIT (0)
+-#define JV_NUMBER_SIZE_CONVERTED (1)
+-
+ #define JVP_FLAGS_NUMBER_NATIVE JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0))
+ #define JVP_FLAGS_NUMBER_NATIVE_STR JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 1))
+ #define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
+@@ -619,8 +616,12 @@ static jv jvp_literal_number_new(const char * literal) {
+ jv_mem_free(n);
+ return JV_INVALID;
+ }
++ if (decNumberIsNaN(&n->num_decimal)) {
++ jv_mem_free(n);
++ return jv_number(NAN);
++ }
+
+- jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}};
++ jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&n->refcnt}};
+ return r;
+ }
+
+@@ -719,9 +720,8 @@ double jv_number_value(jv j) {
+ if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) {
+ jvp_literal_number* n = jvp_literal_number_ptr(j);
+
+- if (j.size != JV_NUMBER_SIZE_CONVERTED) {
++ if (isnan(n->num_double)) {
+ n->num_double = jvp_literal_number_to_double(j);
+- j.size = JV_NUMBER_SIZE_CONVERTED;
+ }
+
+ return n->num_double;
+@@ -755,6 +755,7 @@ int jvp_number_is_nan(jv n) {
+ } else {
+ return n.u.number != n.u.number;
+ }
++ return isnan(n.u.number);
+ }
+
+ int jvp_number_cmp(jv a, jv b) {
+--
+2.49.0
+
new file mode 100644
@@ -0,0 +1,56 @@
+From aea65caf03c129f3303d044044d2d1105be81b71 Mon Sep 17 00:00:00 2001
+From: itchyny <itchyny@cybozu.co.jp>
+Date: Wed, 5 Mar 2025 07:43:54 +0900
+Subject: [PATCH 2/2] Reject NaN with payload while parsing JSON
+
+This commit drops support for parsing NaN with payload in JSON like
+`NaN123` and fixes CVE-2024-53427. Other JSON extensions like `NaN` and
+`Infinity` are still supported. Fixes #3023, fixes #3196, fixes #3246.
+
+CVE: CVE-2024-53427
+Upstream-Status: Backport [https://github.com/jqlang/jq/commit/a09a4dfd55e6c24d04b35062ccfe4509748b1dd3]
+Signed-off-by: Colin Pinnell McAllister <colin.mcallister@garmin.com>
+---
+ src/jv.c | 5 +++++
+ tests/jq.test | 12 ++++++++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/src/jv.c b/src/jv.c
+index 9051f65..4da5ba8 100644
+--- a/src/jv.c
++++ b/src/jv.c
+@@ -617,6 +617,11 @@ static jv jvp_literal_number_new(const char * literal) {
+ return JV_INVALID;
+ }
+ if (decNumberIsNaN(&n->num_decimal)) {
++ // Reject NaN with payload.
++ if (n->num_decimal.digits > 1 || *n->num_decimal.lsu != 0) {
++ jv_mem_free(n);
++ return JV_INVALID;
++ }
+ jv_mem_free(n);
+ return jv_number(NAN);
+ }
+diff --git a/tests/jq.test b/tests/jq.test
+index f783493..0ab21ef 100644
+--- a/tests/jq.test
++++ b/tests/jq.test
+@@ -1724,3 +1724,15 @@ false
+ try 0[implode] catch .
+ []
+ "Cannot index number with string \"\""
++
++# NaN with payload is not parsed
++.[] | try (fromjson | isnan) catch .
++["NaN","-NaN","NaN1","NaN10","NaN100","NaN1000","NaN10000","NaN100000"]
++true
++true
++"Invalid numeric literal at EOF at line 1, column 4 (while parsing 'NaN1')"
++"Invalid numeric literal at EOF at line 1, column 5 (while parsing 'NaN10')"
++"Invalid numeric literal at EOF at line 1, column 6 (while parsing 'NaN100')"
++"Invalid numeric literal at EOF at line 1, column 7 (while parsing 'NaN1000')"
++"Invalid numeric literal at EOF at line 1, column 8 (while parsing 'NaN10000')"
++"Invalid numeric literal at EOF at line 1, column 9 (while parsing 'NaN100000')"
+--
+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,13 @@ 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 \
+ file://CVE-2024-53427-01.patch \
+ file://CVE-2024-53427-02.patch \
+ "
SRCREV = "a9f97e9e61a910a374a5d768244e8ad63f407d3e"
S = "${WORKDIR}/git"
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 --- Updated patch to include a fix for CVE-2024-53427. Also, just as a note, all of these patches were verified with the jq test suite that can be ran with `make check`. Verified on x86_64. .../jq/jq/CVE-2024-23337.patch | 219 ++++++++++++++++++ .../jq/jq/CVE-2024-53427-01.patch | 69 ++++++ .../jq/jq/CVE-2024-53427-02.patch | 56 +++++ .../jq/jq/CVE-2025-48060.patch | 46 ++++ meta-oe/recipes-devtools/jq/jq_git.bb | 8 +- 5 files changed, 397 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-2024-53427-01.patch create mode 100644 meta-oe/recipes-devtools/jq/jq/CVE-2024-53427-02.patch create mode 100644 meta-oe/recipes-devtools/jq/jq/CVE-2025-48060.patch