From e0ae55262c874a8846d6f882fa2416c0ed62d5cd Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Wed, 24 Jul 2024 07:32:50 +1000 Subject: [PATCH] com: fix loop/crash in dpvsnprintf() error handling Somehow I didn't notice Sys_Printf() calls dpvsnprintf(), see 21fa9010ae6de8792f36cca08cb77aaa95d4b928. Also fixes a minor bug where Sys_Print() could output more bytes than it should, introduced in 01642af37128bffc1accbf2e92cb2428ea570720. Signed-off-by: bones_was_here --- common.c | 23 +++++++++++++++++++---- sys_shared.c | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/common.c b/common.c index f0f2fcce..0d701bca 100644 --- a/common.c +++ b/common.c @@ -1018,12 +1018,27 @@ int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list ar #endif if (result < 0 || (size_t)result >= buffersize) { - buffer[buffersize - 1] = '\0'; - // we could be inside Con_Printf + // _vsnprintf_s returns -1 on error and on truncation (indistinguishable), + // vsnprintf returns negative on error and the desired strlen on truncation. + buffer[buffersize - 1] = '\0'; // should be unnecessary, but just in case + // Basic stdout only: we could be inside Con_Printf, Sys_Printf calls dpvsnprintf, + // Windows console doesn't support colours. if (result < 0) - Sys_Printf("dpvsnprintf: output error, buffer size %lu\n", (unsigned long)buffersize); + Sys_Print("dpvsnprintf: output error!\n", 27); else - Sys_Printf("dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer); + { + char msg[MAX_INPUTLINE]; +#if _MSC_VER >= 1400 + result = _snprintf_s(msg, sizeof(msg), _TRUNCATE, "dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer); +#else + result = snprintf(msg, sizeof(msg), "dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer); +#endif + if (result > 0) + { + msg[sizeof(msg) - 1] = '\n'; // may have been lost in truncation + Sys_Print(msg, min((size_t)result, sizeof(msg))); + } + } return -1; } diff --git a/sys_shared.c b/sys_shared.c index 46cec642..b955e827 100644 --- a/sys_shared.c +++ b/sys_shared.c @@ -629,12 +629,13 @@ void Sys_Print(const char *text, size_t textlen) #else #define write _write #endif - while(*text) + while(*text && textlen) { fs_offset_t written = (fs_offset_t)write(sys.outfd, text, textlen); if(written <= 0) break; // sorry, I cannot do anything about this error - without an output text += written; + textlen -= written; } #ifndef WIN32 if (sys_stdout_blocks.integer) -- 2.39.2