From e47e56d226519635768e6aab2f38f0ab037c09e5 Mon Sep 17 00:00:00 2001 From: itchyny Date: Thu, 12 Mar 2026 20:28:43 +0900 Subject: [PATCH] Fix heap buffer overflow in `jvp_string_append` and `jvp_string_copy_replace_bad` In `jvp_string_append`, the allocation size `(currlen + len) * 2` could overflow `uint32_t` when `currlen + len` exceeds `INT_MAX`, causing a small allocation followed by a large `memcpy`. In `jvp_string_copy_replace_bad`, the output buffer size calculation `length * 3 + 1` could overflow `uint32_t`, again resulting in a small allocation followed by a large write. Add overflow checks to both functions to return an error for strings that would exceed `INT_MAX` in length. Fixes CVE-2026-32316. CVE: CVE-2026-32316 Upstream: https://github.com/jqlang/jq/commit/e47e56d226519635768e6aab2f38f0ab037c09e5 Signed-off-by: Thomas Perale --- src/jv.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/jv.c b/src/jv.c index 722a539391..2a62b48419 100644 --- a/src/jv.c +++ b/src/jv.c @@ -1114,7 +1114,12 @@ static jv jvp_string_copy_replace_bad(const char* data, uint32_t length) { const char* end = data + length; const char* i = data; - uint32_t maxlength = length * 3 + 1; // worst case: all bad bytes, each becomes a 3-byte U+FFFD + // worst case: all bad bytes, each becomes a 3-byte U+FFFD + uint64_t maxlength = (uint64_t)length * 3 + 1; + if (maxlength >= INT_MAX) { + return jv_invalid_with_msg(jv_string("String too long")); + } + jvp_string* s = jvp_string_alloc(maxlength); char* out = s->data; int c = 0; @@ -1174,6 +1179,10 @@ static uint32_t jvp_string_remaining_space(jvp_string* s) { static jv jvp_string_append(jv string, const char* data, uint32_t len) { jvp_string* s = jvp_string_ptr(string); uint32_t currlen = jvp_string_length(s); + if ((uint64_t)currlen + len >= INT_MAX) { + jv_free(string); + return jv_invalid_with_msg(jv_string("String too long")); + } if (jvp_refcnt_unshared(string.u.ptr) && jvp_string_remaining_space(s) >= len) {