From b21124169b6f9decbb5ec71ef547c2a6642995f8 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 1 Nov 2024 14:03:38 +0100 Subject: [PATCH] api: fix a buffer overflow in x86emu_log() There seems to be an assumption that vsnprintf() returns a number of characters that were written. That is actually not the case -- it returns number of characters that *would* have been written regardless of truncation to specified size. Therefore, on x86emu_log() that would cross the buffer end will move .log.ptr beyond the end of the buffer, and the subsequent .flush() will be called back with a size argument larger than the buffer. Moreover, given the .flush() is essentially only invoked upon x86emu_clear_log(), this is almost bound to happen for instances that run for a long time. Let's solve the buffer fillup differently: 1.) flush the buffer when it fills up (we'd be crossing the buffer boundary) and 2.) make sure .log.ptr is allways clipped to point inside the allocated buffer. --- api.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/api.c b/api.c index 71a46ae..55b14f8 100644 --- a/api.c +++ b/api.c @@ -337,19 +337,21 @@ API_SYM void x86emu_log(x86emu_t *emu, const char *format, ...) if(!emu || !emu->log.ptr) return; - size = emu->log.size - (emu->log.ptr - emu->log.buf); - va_start(args, format); - if(size > 0) { - size = vsnprintf(emu->log.ptr, size, format, args); - if(size > 0) { - emu->log.ptr += size; - } - else { - *emu->log.ptr = 0; - } + size = vsnprintf(emu->log.ptr, LOG_FREE(emu), format, args); + va_end(args); + + if (emu->log.ptr + size > emu->log.buf + emu->log.size) { + x86emu_clear_log(emu, 1); + va_start(args, format); + size = vsnprintf(emu->log.ptr, emu->log.size, format, args); + va_end(args); } - va_end(args); + + if (size > 0) + emu->log.ptr += size; + if (emu->log.ptr > emu->log.buf + emu->log.size) + emu->log.ptr = emu->log.buf + emu->log.size; }