From ccd24cd647356ff7f7d240e1a6fadfd6a7adb938 Mon Sep 17 00:00:00 2001 From: Thilo Schulz Date: Wed, 23 Feb 2011 16:17:09 +0000 Subject: [PATCH] - Fix unterminated string errors in Q_vsnprintf() on windows. Thanks to Eugene C. for reporting (#4907) - Get rid of bigbuffer in Com_sprintf() - Get rid of Q_snprintf and replace with Com_sprintf() --- code/qcommon/q_shared.c | 55 +++++++++++++++++++++++++++++------------ code/qcommon/q_shared.h | 16 +++++------- code/sys/sys_main.c | 2 +- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index 550d1005..6f68b2e9 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -726,6 +726,39 @@ qboolean Q_isintegral( float f ) return (int)f == f; } +#ifdef _MSC_VER +/* +============= +Q_vsnprintf + +Special wrapper function for Microsoft's broken _vsnprintf() function. +MinGW comes with its own snprintf() which is not broken. +============= +*/ + +int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap); +{ + int retval; + + retval = _vsnprintf(str, size, format, ap); + + if(retval < 0 || retval == size) + { + // Microsoft doesn't adhere to the C99 standard of vsnprintf, + // which states that the return value must be the number of + // bytes written if the output string had sufficient length. + // + // Obviously we cannot determine that value from Microsoft's + // implementation, so we have no choice but to return size. + + str[size - 1] = '\0'; + return size; + } + + return retval; +} +#endif + /* ============= Q_strncpyz @@ -934,28 +967,18 @@ int Q_CountChar(const char *string, char tocount) return count; } -void QDECL Com_sprintf( char *dest, int size, const char *fmt, ...) { +void QDECL Com_sprintf(char *dest, int size, const char *fmt, ...) +{ int len; va_list argptr; - char bigbuffer[32000]; // big, but small enough to fit in PPC stack va_start (argptr,fmt); - len = Q_vsnprintf (bigbuffer, sizeof(bigbuffer), fmt,argptr); + len = Q_vsnprintf(dest, size, fmt, argptr); va_end (argptr); - if ( len >= sizeof( bigbuffer ) ) { - Com_Error( ERR_FATAL, "Com_sprintf: overflowed bigbuffer" ); - } - if (len >= size) { - Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size); -#ifdef _DEBUG - __asm { - int 3; - } -#endif - } - Q_strncpyz (dest, bigbuffer, size ); -} + if(len >= size) + Com_Printf("Com_sprintf: Output length %d too short, require %d bytes.\n", size, len); +} /* ============ diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 2804a565..ea7521fe 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -132,16 +132,6 @@ typedef int intptr_t; #include #include -// vsnprintf is ISO/IEC 9899:1999 -// abstracting this to make it portable -#ifdef _WIN32 - #define Q_vsnprintf _vsnprintf - #define Q_snprintf _snprintf -#else - #define Q_vsnprintf vsnprintf - #define Q_snprintf snprintf -#endif - #ifdef _MSC_VER #include @@ -153,8 +143,14 @@ typedef int intptr_t; typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t; typedef unsigned __int8 uint8_t; + + // vsnprintf is ISO/IEC 9899:1999 + // abstracting this to make it portable + int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap); #else #include + + #define Q_vsnprintf vsnprintf #endif #endif diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index 6d9cfea8..84db658b 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -425,7 +425,7 @@ void *Sys_LoadDll( const char *name, assert( name ); - Q_snprintf (fname, sizeof(fname), "%s" ARCH_STRING DLL_EXT, name); + Com_sprintf(fname, sizeof(fname), "%s" ARCH_STRING DLL_EXT, name); netpath = FS_FindDll(fname);