From 9a86ff8f85ba4103eea17d6db5def12eeedc1a00 Mon Sep 17 00:00:00 2001
From: "M. Kristall" <mkpdev@gmail.com>
Date: Sat, 3 Oct 2009 11:48:20 +0000
Subject: * (bug 3673) Add boundary checking to G_SanitiseName()  and
 G_DecolorString() * s/G_SanitiseName/G_SanitiseString/ *
 s/trap_Printf/trap_Print/ * Change a few occurences of MAX_STRING_CHARS to
 MAX_NAME_LENGTH

---
 src/game/g_admin.c      | 61 +++++++++++++++++++++++++------------------------
 src/game/g_cmds.c       | 36 +++++++++++++++++------------
 src/game/g_local.h      |  8 +++----
 src/game/g_main.c       |  2 +-
 src/game/g_syscalls.asm |  2 +-
 src/game/g_syscalls.c   |  2 +-
 6 files changed, 58 insertions(+), 53 deletions(-)

diff --git a/src/game/g_admin.c b/src/game/g_admin.c
index 6ca68010..b3f1ace2 100644
--- a/src/game/g_admin.c
+++ b/src/game/g_admin.c
@@ -269,7 +269,7 @@ qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len )
   char testName[ MAX_NAME_LENGTH ] = {""};
   char name2[ MAX_NAME_LENGTH ] = {""};
 
-  G_SanitiseName( name, name2 );
+  G_SanitiseString( name, name2, sizeof( name2 ) );
 
   if( !Q_stricmp( name2, "UnnamedPlayer" ) )
     return qtrue;
@@ -284,7 +284,7 @@ qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len )
     if( i == ( ent - g_entities ) )
       continue;
 
-    G_SanitiseName( client->pers.netname, testName );
+    G_SanitiseString( client->pers.netname, testName, sizeof( testName ) );
     if( !Q_stricmp( name2, testName ) )
     {
       Com_sprintf( err, len, "The name '%s^7' is already in use", name );
@@ -299,7 +299,7 @@ qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len )
   {
     if( g_admin_admins[ i ]->level < 1 )
       continue;
-    G_SanitiseName( g_admin_admins[ i ]->name, testName );
+    G_SanitiseString( g_admin_admins[ i ]->name, testName, sizeof( testName ) );
     if( !Q_stricmp( name2, testName ) &&
       Q_stricmp( ent->client->pers.guid, g_admin_admins[ i ]->guid ) )
     {
@@ -747,7 +747,7 @@ static int admin_listadmins( gentity_t *ent, int start, char *search )
 
     l = vic->client->pers.adminLevel;
 
-    G_SanitiseName( vic->client->pers.netname, name );
+    G_SanitiseString( vic->client->pers.netname, name, sizeof( name ) );
     if( !strstr( name, search ) )
       continue;
 
@@ -761,7 +761,7 @@ static int admin_listadmins( gentity_t *ent, int start, char *search )
     {
       if( g_admin_levels[ j ]->level == l )
       {
-        G_DecolorString( g_admin_levels[ j ]->name, lname );
+        G_DecolorString( g_admin_levels[ j ]->name, lname, sizeof( lname ) );
         Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is",
           ( admin_level_maxname + strlen( g_admin_levels[ j ]->name )
             - strlen( lname ) ) );
@@ -784,7 +784,7 @@ static int admin_listadmins( gentity_t *ent, int start, char *search )
   {
     if( search[ 0 ] )
     {
-      G_SanitiseName( g_admin_admins[ i ]->name, name );
+      G_SanitiseString( g_admin_admins[ i ]->name, name, sizeof( name ) );
       if( !strstr( name, search ) )
         continue;
 
@@ -796,7 +796,7 @@ static int admin_listadmins( gentity_t *ent, int start, char *search )
         vic = &g_entities[ j ];
         if( !vic->client || vic->client->pers.connected != CON_CONNECTED )
           continue;
-        G_SanitiseName( vic->client->pers.netname, name2 );
+        G_SanitiseString( vic->client->pers.netname, name2, sizeof( name2 ) );
         if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid ) &&
           strstr( name2, search ) )
         {
@@ -817,7 +817,7 @@ static int admin_listadmins( gentity_t *ent, int start, char *search )
     {
       if( g_admin_levels[ j ]->level == g_admin_admins[ i ]->level )
       {
-        G_DecolorString( g_admin_levels[ j ]->name, lname );
+        G_DecolorString( g_admin_levels[ j ]->name, lname, sizeof( lname ) );
         Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is",
           ( admin_level_maxname + strlen( g_admin_levels[ j ]->name )
             - strlen( lname ) ) );
@@ -1003,7 +1003,7 @@ void G_admin_namelog_update( gclient_t *client, qboolean disconnect )
   char n2[ MAX_NAME_LENGTH ];
   int clientNum = ( client - level.clients );
 
-  G_SanitiseName( client->pers.netname, n1 );
+  G_SanitiseString( client->pers.netname, n1, sizeof( n1 ) );
   for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
   {
     if( disconnect && g_admin_namelog[ i ]->slot != clientNum )
@@ -1021,7 +1021,7 @@ void G_admin_namelog_update( gclient_t *client, qboolean disconnect )
       for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&
          g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
       {
-        G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 );
+        G_SanitiseString( g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) );
         if( !Q_stricmp( n1, n2 ) )
           break;
       }
@@ -1313,7 +1313,7 @@ qboolean G_admin_readconfig( gentity_t *ent, int skiparg )
     // max printable name length for formatting
     for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ )
     {
-      G_DecolorString( l->name, n );
+      G_DecolorString( l->name, n, sizeof( n ) );
       if( strlen( n ) > admin_level_maxname )
         admin_level_maxname = strlen( n );
     }
@@ -1364,7 +1364,7 @@ qboolean G_admin_setlevel( gentity_t *ent, int skiparg )
   G_SayArgv( 1 + skiparg, testname, sizeof( testname ) );
   G_SayArgv( 2 + skiparg, lstr, sizeof( lstr ) );
   l = atoi( lstr );
-  G_SanitiseName( testname, name );
+  G_SanitiseString( testname, name, sizeof( name ) );
   for( i = 0; i < sizeof( name ) && name[ i ]; i++ )
   {
     if( !isdigit( name[ i ] ) )
@@ -1424,7 +1424,7 @@ qboolean G_admin_setlevel( gentity_t *ent, int skiparg )
   {
     for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ] && matches < 2; i++ )
     {
-      G_SanitiseName( g_admin_admins[ i ]->name, testname );
+      G_SanitiseString( g_admin_admins[ i ]->name, testname, sizeof( testname ) );
       if( strstr( testname, name ) )
       {
         Q_strncpyz( adminname, g_admin_admins[ i ]->name, sizeof( adminname ) );
@@ -1443,7 +1443,8 @@ qboolean G_admin_setlevel( gentity_t *ent, int skiparg )
         continue;
 
       }
-      G_SanitiseName( level.clients[ i ].pers.netname, testname );
+      G_SanitiseString( level.clients[ i ].pers.netname, testname,
+        sizeof( testname ) );
       if( strstr( testname, name ) )
       {
         vic = &g_entities[ i ];
@@ -1662,7 +1663,7 @@ qboolean G_admin_ban( gentity_t *ent, int skiparg )
     return qfalse;
   }
   G_SayArgv( 1 + skiparg, search, sizeof( search ) );
-  G_SanitiseName( search, s2 );
+  G_SanitiseString( search, s2, sizeof( s2 ) );
   G_SayArgv( 2 + skiparg, secs, sizeof( secs ) );
 
   // support "w" (weeks), "d" (days), "h" (hours), and "m" (minutes) modifiers
@@ -1739,7 +1740,7 @@ qboolean G_admin_ban( gentity_t *ent, int skiparg )
     for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&
        g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
     {
-      G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 );
+      G_SanitiseString( g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) );
       if( strstr( n2, s2 ) )
       {
         if( logmatch != i )
@@ -1766,7 +1767,7 @@ qboolean G_admin_ban( gentity_t *ent, int skiparg )
       for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&
          g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
       {
-        G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 );
+        G_SanitiseString( g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) );
         if( strstr( n2, s2 ) )
         {
           if( g_admin_namelog[ i ]->slot > -1 )
@@ -2127,7 +2128,7 @@ qboolean G_admin_listadmins( gentity_t *ent, int skiparg )
         start = found + start;
     }
     else
-      G_SanitiseName( s, search );
+      G_SanitiseString( s, search, sizeof( search ) );
   }
 
   if( start >= found || start < 0 )
@@ -2264,7 +2265,7 @@ qboolean G_admin_listplayers( gentity_t *ent, int skiparg )
     }
 
     l = 0;
-    G_SanitiseName( p->pers.netname, n2 );
+    G_SanitiseString( p->pers.netname, n2, sizeof( n2 ) );
     n[ 0 ] = '\0';
     for( j = 0; j < MAX_ADMIN_ADMINS && g_admin_admins[ j ]; j++ )
     {
@@ -2276,7 +2277,7 @@ qboolean G_admin_listplayers( gentity_t *ent, int skiparg )
           break;
         }
         l = g_admin_admins[ j ]->level;
-        G_SanitiseName( g_admin_admins[ j ]->name, n3 );
+        G_SanitiseString( g_admin_admins[ j ]->name, n3, sizeof( n3 ) );
         if( Q_stricmp( n2, n3 ) )
         {
           Q_strncpyz( n, g_admin_admins[ j ]->name, sizeof( n ) );
@@ -2293,7 +2294,7 @@ qboolean G_admin_listplayers( gentity_t *ent, int skiparg )
         Q_strncpyz( lname, g_admin_levels[ j ]->name, sizeof( lname ) );
         if( *lname )
         {
-          G_DecolorString( lname, lname2 );
+          G_DecolorString( lname, lname2, sizeof( lname2 ) );
           Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is",
             ( admin_level_maxname + strlen( lname ) - strlen( lname2 ) ) );
           Com_sprintf( lname2, sizeof( lname2 ), lname_fmt, lname );
@@ -2380,8 +2381,8 @@ qboolean G_admin_showbans( gentity_t *ent, int skiparg )
   for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ] &&
      ( i - start ) < MAX_ADMIN_SHOWBANS; i++ )
   {
-    G_DecolorString( g_admin_bans[ i ]->name, n1 );
-    G_DecolorString( g_admin_bans[ i ]->banner, n2 );
+    G_DecolorString( g_admin_bans[ i ]->name, n1, sizeof( n1 ) );
+    G_DecolorString( g_admin_bans[ i ]->banner, n2, sizeof( n2 ) );
     if( strlen( n1 ) > max_name )
     {
       max_name = strlen( n1 );
@@ -2420,12 +2421,12 @@ qboolean G_admin_showbans( gentity_t *ent, int skiparg )
     secs = ( g_admin_bans[ i ]->expires - t );
     G_admin_duration( secs, duration, sizeof( duration ) );
 
-    G_DecolorString( g_admin_bans[ i ]->name, n1 );
+    G_DecolorString( g_admin_bans[ i ]->name, n1, sizeof( n1 ) );
     Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is",
       ( max_name + strlen( g_admin_bans[ i ]->name ) - strlen( n1 ) ) );
     Com_sprintf( n1, sizeof( n1 ), name_fmt, g_admin_bans[ i ]->name );
 
-    G_DecolorString( g_admin_bans[ i ]->banner, n2 );
+    G_DecolorString( g_admin_bans[ i ]->banner, n2, sizeof( n2 ) );
     Com_sprintf( banner_fmt, sizeof( banner_fmt ), "%%%is",
       ( max_banner + strlen( g_admin_bans[ i ]->banner ) - strlen( n2 ) ) );
     Com_sprintf( n2, sizeof( n2 ), banner_fmt, g_admin_bans[ i ]->banner );
@@ -2802,7 +2803,7 @@ qboolean G_admin_namelog( gentity_t *ent, int skiparg )
   if( G_SayArgc() > 1 + skiparg )
   {
     G_SayArgv( 1 + skiparg, search, sizeof( search ) );
-    G_SanitiseName( search, s2 );
+    G_SanitiseString( search, s2, sizeof( s2 ) );
   }
   ADMBP_begin();
   for( i = 0; i < MAX_ADMIN_NAMELOGS && g_admin_namelog[ i ]; i++ )
@@ -2813,7 +2814,7 @@ qboolean G_admin_namelog( gentity_t *ent, int skiparg )
       for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&
         g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )
       {
-        G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 );
+        G_SanitiseString( g_admin_namelog[ i ]->name[ j ], n2, sizeof( n2 ) );
         if( strstr( n2, s2 ) )
         {
           found = qtrue;
@@ -2956,11 +2957,11 @@ void G_admin_print( gentity_t *ent, char *m )
     char m2[ MAX_STRING_CHARS ];
     if( !trap_Cvar_VariableIntegerValue( "com_ansiColor" ) )
     {
-      G_DecolorString( m, m2 );
-      G_Printf( m2 );
+      G_DecolorString( m, m2, sizeof( m2 ) );
+      trap_Print( m2 );
     }
     else
-      G_Printf( m );
+      trap_Print( m );
   }
 }
 
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 11952834..61f39b76 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -25,17 +25,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 /*
 ==================
-G_SanitiseName
+G_SanitiseString
 
-Remove case and control characters from a player name
+Remove case and control characters from a string
 ==================
 */
-void G_SanitiseName( char *in, char *out )
+void G_SanitiseString( char *in, char *out, int len )
 {
   qboolean skip = qtrue;
   int spaces = 0;
 
-  while( *in )
+  len--;
+
+  while( *in && len > 0 )
   {
     // strip leading white space
     if( *in == ' ' )
@@ -66,6 +68,7 @@ void G_SanitiseName( char *in, char *out )
     }
 
     *out++ = tolower( *in++ );
+    len--;
   }
   out -= spaces;
   *out = 0;
@@ -83,8 +86,8 @@ int G_ClientNumberFromString( char *s )
 {
   gclient_t *cl;
   int       i;
-  char      s2[ MAX_STRING_CHARS ];
-  char      n2[ MAX_STRING_CHARS ];
+  char      s2[ MAX_NAME_LENGTH ];
+  char      n2[ MAX_NAME_LENGTH ];
 
   // numeric values are just slot numbers
   for( i = 0; s[ i ] && isdigit( s[ i ] ); i++ );
@@ -104,14 +107,14 @@ int G_ClientNumberFromString( char *s )
   }
 
   // check for a name match
-  G_SanitiseName( s, s2 );
+  G_SanitiseString( s, s2, sizeof( s2 ) );
 
   for( i = 0, cl = level.clients; i < level.maxclients; i++, cl++ )
   {
     if( cl->pers.connected == CON_DISCONNECTED )
       continue;
 
-    G_SanitiseName( cl->pers.netname, n2 );
+    G_SanitiseString( cl->pers.netname, n2, sizeof( n2 ) );
 
     if( !strcmp( n2, s2 ) )
       return i;
@@ -195,7 +198,7 @@ int G_ClientNumbersFromString( char *s, int *plist, int max )
   }
 
   // now look for name matches
-  G_SanitiseName( s, s2 );
+  G_SanitiseString( s, s2, sizeof( s2 ) );
   if( strlen( s2 ) < 1 )
     return 0;
   for( i = 0; i < level.maxclients && found <= max; i++ )
@@ -205,7 +208,7 @@ int G_ClientNumbersFromString( char *s, int *plist, int max )
     {
       continue;
     }
-    G_SanitiseName( p->pers.netname, n2 );
+    G_SanitiseString( p->pers.netname, n2, sizeof( n2 ) );
     if( strstr( n2, s2 ) )
     {
       *plist++ = i;
@@ -1076,7 +1079,7 @@ void Cmd_CallVote_f( gentity_t *ent )
 {
   int   i;
   char  arg1[ MAX_STRING_TOKENS ];
-  char  arg2[ MAX_STRING_TOKENS ];
+  char  arg2[ MAX_NAME_LENGTH ];
   int   clientNum = -1;
   char  name[ MAX_NETNAME ];
 
@@ -1310,7 +1313,7 @@ void Cmd_CallTeamVote_f( gentity_t *ent )
 {
   int   i, team, cs_offset = 0;
   char  arg1[ MAX_STRING_TOKENS ];
-  char  arg2[ MAX_STRING_TOKENS ];
+  char  arg2[ MAX_NAME_LENGTH ];
   int   clientNum = -1;
   char  name[ MAX_NETNAME ];
 
@@ -2722,7 +2725,7 @@ void Cmd_Follow_f( gentity_t *ent )
 {
   int   i;
   int   pids[ MAX_CLIENTS ];
-  char  arg[ MAX_TOKEN_CHARS ];
+  char  arg[ MAX_NAME_LENGTH ];
 
   if( trap_Argc( ) != 2 )
   {
@@ -3216,9 +3219,11 @@ char *G_SayConcatArgs( int start )
   return s;
 }
 
-void G_DecolorString( char *in, char *out )
+void G_DecolorString( char *in, char *out, int len )
 {
-  while( *in ) {
+  len--;
+
+  while( *in && len > 0 ) {
     if( *in == 27 || Q_IsColorString( in ) ) {
       in++;
       if( *in )
@@ -3226,6 +3231,7 @@ void G_DecolorString( char *in, char *out )
       continue;
     }
     *out++ = *in++;
+    len--;
   }
   *out = '\0';
 }
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 05f1fe21..ab6d82f0 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -654,8 +654,6 @@ char      *G_NewString( const char *string );
 //
 // g_cmds.c
 //
-void      Cmd_Score_f( gentity_t *ent );
-void      G_StopFromFollowing( gentity_t *ent );
 void      G_StopFollowing( gentity_t *ent );
 void      G_FollowLockView( gentity_t *ent );
 qboolean  G_FollowNewClient( gentity_t *ent, int dir );
@@ -665,10 +663,10 @@ int       G_ClientNumbersFromString( char *s, int *plist, int max );
 int       G_SayArgc( void );
 qboolean  G_SayArgv( int n, char *buffer, int bufferLength );
 char      *G_SayConcatArgs( int start );
-void      G_DecolorString( char *in, char *out );
+void      G_DecolorString( char *in, char *out, int len );
 void      G_LeaveTeam( gentity_t *self );
 void      G_ChangeTeam( gentity_t *ent, team_t newTeam );
-void      G_SanitiseName( char *in, char *out );
+void      G_SanitiseString( char *in, char *out, int len );
 void      G_PrivateMessage( gentity_t *ent );
 void      Cmd_Test_f( gentity_t *ent );
 
@@ -1157,7 +1155,7 @@ extern  vmCvar_t  g_dretchPunt;
 
 extern  vmCvar_t  g_privateMessages;
 
-void      trap_Printf( const char *fmt );
+void      trap_Print( const char *fmt );
 void      trap_Error( const char *fmt );
 int       trap_Milliseconds( void );
 int       trap_RealTime( qtime_t *qtime );
diff --git a/src/game/g_main.c b/src/game/g_main.c
index bb79e173..a4af138a 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -341,7 +341,7 @@ void QDECL G_Printf( const char *fmt, ... )
   vsprintf( text, fmt, argptr );
   va_end( argptr );
 
-  trap_Printf( text );
+  trap_Print( text );
 }
 
 void QDECL G_Error( const char *fmt, ... )
diff --git a/src/game/g_syscalls.asm b/src/game/g_syscalls.asm
index e77017b7..132ca1e1 100644
--- a/src/game/g_syscalls.asm
+++ b/src/game/g_syscalls.asm
@@ -1,6 +1,6 @@
 code
 
-equ trap_Printf                     -1
+equ trap_Print                      -1
 equ trap_Error                      -2
 equ trap_Milliseconds               -3
 equ trap_Cvar_Register              -4
diff --git a/src/game/g_syscalls.c b/src/game/g_syscalls.c
index cb4ceb66..1f790cfc 100644
--- a/src/game/g_syscalls.c
+++ b/src/game/g_syscalls.c
@@ -41,7 +41,7 @@ int PASSFLOAT( float x )
   return *(int *)&floatTemp;
 }
 
-void  trap_Printf( const char *fmt )
+void  trap_Print( const char *fmt )
 {
   syscall( G_PRINT, fmt );
 }
-- 
cgit