1From 17de4d15687aa30c49660dc4b792b1fb4d38b569 Mon Sep 17 00:00:00 2001 2From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com> 3Date: Thu, 7 Apr 2022 17:29:54 +0200 4Subject: [PATCH] Fix CVE-2022-24795 5 6There was an integer overflow in yajl_buf_ensure_available() leading 7to allocating less memory than requested. Then data were written past 8the allocated heap buffer in yajl_buf_append(), the only caller of 9yajl_buf_ensure_available(). Another result of the overflow was an 10infinite loop without a return from yajl_buf_ensure_available(). 11 12yajl-ruby project, which bundles yajl, fixed it 13<https://github.com/brianmario/yajl-ruby/pull/211> by checking for the 14integer overflow, fortifying buffer allocations, and report the 15failures to a caller. But then the caller yajl_buf_append() skips 16a memory write if yajl_buf_ensure_available() failed leading to a data 17corruption. 18 19A yajl fork mainter recommended calling memory allocation callbacks with 20the large memory request and let them to handle it. But that has the 21problem that it's not possible pass the overely large size to the 22callbacks. 23 24This patch catches the integer overflow and terminates the process 25with abort(). 26 27CVE: CVE-2022-24795 28Upstream-Status: Submitted [https://github.com/lloyd/yajl/issues/239] 29Signed-off-by: Ross Burton <ross.burton@arm.com> 30--- 31 src/yajl_buf.c | 12 +++++++++++- 32 1 file changed, 11 insertions(+), 1 deletion(-) 33 34diff --git a/src/yajl_buf.c b/src/yajl_buf.c 35index 1aeafde..55c11ad 100644 36--- a/src/yajl_buf.c 37+++ b/src/yajl_buf.c 38@@ -45,7 +45,17 @@ void yajl_buf_ensure_available(yajl_buf buf, size_t want) 39 40 need = buf->len; 41 42- while (want >= (need - buf->used)) need <<= 1; 43+ if (((buf->used > want) ? buf->used : want) > (size_t)(buf->used + want)) { 44+ /* We cannot allocate more memory than SIZE_MAX. */ 45+ abort(); 46+ } 47+ while (want >= (need - buf->used)) { 48+ if (need >= (size_t)((size_t)(-1)<<1)>>1) { 49+ /* need would overflow. */ 50+ abort(); 51+ } 52+ need <<= 1; 53+ } 54 55 if (need != buf->len) { 56 buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need); 57-- 582.34.1 59 60