From 8805ab208fea4c089acbe8d9911dcfea27e45d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Sat, 16 Sep 2023 13:04:37 +0200 Subject: [PATCH] Fix CVE-2022-24795 There was an integer overflow in yajl_buf_ensure_available() leading to allocating less memory than requested. Then data were written past the allocated heap buffer in yajl_buf_append(), the only caller of yajl_buf_ensure_available(). Another result of the overflow was an infinite loop without a return from yajl_buf_ensure_available(). yajl-ruby project, which bundles yajl, fixed it by checking for the integer overflow, fortifying buffer allocations, and report the failures to a caller. But then the caller yajl_buf_append() skips a memory write if yajl_buf_ensure_available() failed leading to a data corruption. A yajl fork mainter recommended calling memory allocation callbacks with the large memory request and let them to handle it. But that has the problem that it's not possible pass the overely large size to the callbacks. This patch catches the integer overflow and terminates the process with abort(). https://github.com/brianmario/yajl-ruby/security/advisories/GHSA-jj47-x69x-mxrm Origin: https://github.com/ppisar/yajl/commit/23cea2d7677e396efed78bbf1bf153961fab6bad Bug: https://github.com/lloyd/yajl/issues/239 Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1040036 --- src/cdogs/yajl/yajl_buf.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cdogs/yajl/yajl_buf.c b/src/cdogs/yajl/yajl_buf.c index 1aeafde08..55c11add6 100644 --- a/src/cdogs/yajl/yajl_buf.c +++ b/src/cdogs/yajl/yajl_buf.c @@ -45,7 +45,17 @@ void yajl_buf_ensure_available(yajl_buf buf, size_t want) need = buf->len; - while (want >= (need - buf->used)) need <<= 1; + if (((buf->used > want) ? buf->used : want) > (size_t)(buf->used + want)) { + /* We cannot allocate more memory than SIZE_MAX. */ + abort(); + } + while (want >= (need - buf->used)) { + if (need >= (size_t)((size_t)(-1)<<1)>>1) { + /* need would overflow. */ + abort(); + } + need <<= 1; + } if (need != buf->len) { buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);