From 0da101b7ba1b2e2ed1a905586a72b49a8d5049a0 Mon Sep 17 00:00:00 2001 From: Sergey Nikiforov Date: Mon, 17 Oct 2022 16:12:31 -0300 Subject: [PATCH] Fix a crash while writing a long string to the log Corresponding code is improved to not overrun a buffer. Added an API to write long strings to the log without trimming them. --- common/logstuff.cpp | 42 +++++++++++++++++++++++++++++++++--------- common/logstuff.h | 3 +++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/common/logstuff.cpp b/common/logstuff.cpp index e3aa6ca2b..71d02c3e1 100644 --- a/common/logstuff.cpp +++ b/common/logstuff.cpp @@ -493,12 +493,19 @@ static void InternalLogMail( const char *msgbuffer, unsigned int msglen, int /*f // a (va_list *) instead to avoid this problem void LogWithPointer( int loggingTo, const char *format, va_list *arglist ) { - char msgbuffer[1024]; //min 1024!!, but also think of other OSs stack!! + int scrwidth = ASSUMED_SCREEN_WIDTH; /* assume this for consistency */ + ConGetSize(&scrwidth,NULL); /* sets to 80 or does not touch if not supported */ + + char fixed_msgbuffer[1024]; //min 1024!!, but also think of other OSs stack!! + char *msgbuffer = &fixed_msgbuffer[0]; + + //the code below may insert some characters + unsigned extra_bytes = scrwidth > 4 ? scrwidth : 4; + unsigned int msglen = 0, sel; char *buffptr, *obuffptr; int old_loggingTo = loggingTo; - msgbuffer[0]=0; loggingTo &= (logstatics.loggingTo|LOGTO_RAWMODE); if ( !format || !*format ) @@ -506,10 +513,21 @@ void LogWithPointer( int loggingTo, const char *format, va_list *arglist ) if ( loggingTo != LOGTO_NONE ) { - if ( arglist == NULL ) - strcat( msgbuffer, format ); - else - vsprintf( msgbuffer, format, *arglist ); + if ( arglist == NULL ) { + const size_t len = strlen(format); + if (len >= sizeof(fixed_msgbuffer) - extra_bytes) { + msgbuffer = (char *)malloc(len + 1 + extra_bytes); + if (msgbuffer) { + memcpy(msgbuffer, format, len + 1); + } else { + msgbuffer = &fixed_msgbuffer[0]; + memcpy(msgbuffer, format, sizeof(fixed_msgbuffer) - 1 - extra_bytes); + msgbuffer[sizeof(fixed_msgbuffer) - 1 - extra_bytes] = 0; + } + } else + memcpy(msgbuffer, format, len + 1); + } else + vsnprintf(msgbuffer, sizeof(fixed_msgbuffer) - extra_bytes, format, *arglist); msglen = strlen( msgbuffer ); if ( msglen == 0 ) @@ -571,9 +589,6 @@ void LogWithPointer( int loggingTo, const char *format, va_list *arglist ) if (( loggingTo & LOGTO_SCREEN ) != 0) { - int scrwidth = ASSUMED_SCREEN_WIDTH; /* assume this for consistancy */ - ConGetSize(&scrwidth,NULL); /* gets set to 80 or untouched, if not supported */ - #ifdef ASSERT_WIDTH_80 //"show" where badly formatted lines are cropping up //if (logstatics.stdoutisatty) { @@ -645,6 +660,10 @@ void LogWithPointer( int loggingTo, const char *format, va_list *arglist ) } } + if (msgbuffer != &fixed_msgbuffer[0]) { + free(msgbuffer); + } + return; } @@ -716,6 +735,11 @@ void LogRaw( const char *format, ... ) return; } +void LogRawString( const char *str ) +{ + LogWithPointer( LOGTO_RAWMODE | LOGAS_LOG, str, NULL); +} + void LogTo( int towhat, const char *format, ... ) { va_list argptr; diff --git a/common/logstuff.h b/common/logstuff.h index 7c1deeb86..f42ecbbc9 100644 --- a/common/logstuff.h +++ b/common/logstuff.h @@ -50,6 +50,9 @@ extern void LogScreenRaw( const char *format, ... ) __CHKFMT_PRINTF; //Log to mail+file+screen. No adjustments. extern void LogRaw( const char *format, ... ) __CHKFMT_PRINTF; +//Log to mail+file+screen. No adjustments. Supports very long strings but not formatting. +extern void LogRawString( const char *str ); + //Log to LOGTO_* flags (RAW implies screen) extern void LogTo( int towhat, const char *format, ... ) __CHKFMT_LOGTO;