jq/0002-CVE-2025-48060.patch
Tomas Halman e4f9c63227 AddressSanitizer: stack-buffer-overflow in jq_fuzz_execute
Fixing CVE-2025-48060
Resolves: RHEL-92982
2025-06-30 12:47:05 +02:00

142 lines
4.6 KiB
Diff

CVE-2025-48060 fix based on:
commit dc849e9bb74a7a164a3ea52f661cc712b1ffbd43
Author: itchyny <itchyny@cybozu.co.jp>
Date: Tue Mar 4 22:13:55 2025 +0900
Improve performance of repeating strings (#3272)
This commit improves the performance of repeating strings, by copying
the result string instead of the string being repeated. Also it adds
an error message when the result string is too long.
and
commit c6e041699d8cd31b97375a2596217aff2cfca85b
Author: itchyny <itchyny@cybozu.co.jp>
Date: Sat May 31 11:46:40 2025 +0900
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.
diff -up jq-jq-1.7.1/src/builtin.c.orig jq-jq-1.7.1/src/builtin.c
--- jq-jq-1.7.1/src/builtin.c.orig 2023-12-13 20:20:22.000000000 +0100
+++ jq-jq-1.7.1/src/builtin.c 2025-06-25 10:44:54.924284670 +0200
@@ -369,21 +369,10 @@ jv binop_multiply(jv a, jv b) {
str = b;
num = a;
}
- jv res;
double d = jv_number_value(num);
- if (d < 0 || isnan(d)) {
- res = jv_null();
- } else {
- int n = d;
- size_t alen = jv_string_length_bytes(jv_copy(str));
- res = jv_string_empty(alen * n);
- for (; n > 0; n--) {
- res = jv_string_append_buf(res, jv_string_value(str), alen);
- }
- }
- jv_free(str);
jv_free(num);
- return res;
+ return jv_string_repeat(str,
+ d < 0 || isnan(d) ? -1 : d > INT_MAX ? INT_MAX : (int)d);
} else if (ak == JV_KIND_OBJECT && bk == JV_KIND_OBJECT) {
return jv_object_merge_recursive(a, b);
} else {
diff -up jq-jq-1.7.1/src/jv.c.orig jq-jq-1.7.1/src/jv.c
--- jq-jq-1.7.1/src/jv.c.orig 2025-06-25 10:53:50.314332900 +0200
+++ jq-jq-1.7.1/src/jv.c 2025-06-25 10:51:23.208740329 +0200
@@ -1125,6 +1125,7 @@ static jv jvp_string_empty_new(uint32_t
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;
}
@@ -1307,6 +1308,32 @@ jv jv_string_indexes(jv j, jv k) {
return a;
}
+jv jv_string_repeat(jv j, int n) {
+ assert(JVP_HAS_KIND(j, JV_KIND_STRING));
+ if (n < 0) {
+ jv_free(j);
+ return jv_null();
+ }
+ int len = jv_string_length_bytes(jv_copy(j));
+ int64_t res_len = (int64_t)len * n;
+ if (res_len >= INT_MAX) {
+ jv_free(j);
+ return jv_invalid_with_msg(jv_string("Repeat string result too long"));
+ }
+ if (res_len == 0) {
+ jv_free(j);
+ return jv_string("");
+ }
+ jv res = jv_string_empty(res_len);
+ res = jvp_string_append(res, jv_string_value(j), len);
+ for (int curr = len, grow; curr < res_len; curr += grow) {
+ grow = MIN(res_len - curr, curr);
+ res = jvp_string_append(res, jv_string_value(res), grow);
+ }
+ jv_free(j);
+ return res;
+}
+
jv jv_string_split(jv j, jv sep) {
assert(JVP_HAS_KIND(j, JV_KIND_STRING));
assert(JVP_HAS_KIND(sep, JV_KIND_STRING));
diff -up jq-jq-1.7.1/src/jv.h.orig jq-jq-1.7.1/src/jv.h
--- jq-jq-1.7.1/src/jv.h.orig 2023-12-13 20:20:22.000000000 +0100
+++ jq-jq-1.7.1/src/jv.h 2025-06-25 10:44:54.925242109 +0200
@@ -131,6 +131,7 @@ jv jv_string_fmt(const char*, ...) JV_PR
jv jv_string_append_codepoint(jv a, uint32_t c);
jv jv_string_append_buf(jv a, const char* buf, int len);
jv jv_string_append_str(jv a, const char* str);
+jv jv_string_repeat(jv j, int n);
jv jv_string_split(jv j, jv sep);
jv jv_string_explode(jv j);
jv jv_string_implode(jv j);
diff -up jq-jq-1.7.1/tests/jq.test.orig jq-jq-1.7.1/tests/jq.test
--- jq-jq-1.7.1/tests/jq.test.orig 2025-06-25 10:53:02.390073835 +0200
+++ jq-jq-1.7.1/tests/jq.test 2025-06-25 10:51:23.209350316 +0200
@@ -1369,6 +1369,18 @@ indices(", ")
"abc"
[null,null]
+. * 100000 | [.[:10],.[-10:]]
+"abc"
+["abcabcabca","cabcabcabc"]
+
+. * 1000000000
+""
+""
+
+try (. * 1000000000) catch .
+"abc"
+"Repeat string result too long"
+
[.[] / ","]
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]
@@ -2030,6 +2042,10 @@ map(try implode catch .)
[123,["a"],[nan]]
["implode input must be an array","string (\"a\") can't be imploded, unicode codepoint needs to be numeric","number (null) can't be imploded, unicode codepoint needs to be numeric"]
+try 0[implode] catch .
+[]
+"Cannot index number with string \"\""
+
# walk
walk(.)
{"x":0}