From 599b1b48ecf778e8296c7a6479d9fb0f88a6242b Mon Sep 17 00:00:00 2001 From: SNMetamorph <25657591+SNMetamorph@users.noreply.github.com> Date: Tue, 15 Jul 2025 17:34:28 +0400 Subject: [PATCH] engine: voice: added wrapper for players voice status array to avoid mess with off-by-one errors --- engine/client/voice.c | 41 +++++++++++++++++++++++++++++++++-------- engine/client/voice.h | 2 +- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/engine/client/voice.c b/engine/client/voice.c index 007c3add..527f980d 100644 --- a/engine/client/voice.c +++ b/engine/client/voice.c @@ -69,6 +69,24 @@ static qboolean Voice_IsOpusCustomMode( const char *codec ) return Q_strcmp( codec, VOICE_OPUS_CUSTOM_CODEC ) == 0; } + +/* +========================= +Voice_GetPlayerStatus + +Does proper entity index range checking and helps to avoid mess with off-by-one errors +========================= +*/ +static voice_status_t *Voice_GetPlayerStatus( int playerent ) +{ + if ( playerent < 1 || playerent > MAX_CLIENTS ) + { + Con_Printf( S_ERROR "%s: detected out-of-range player entity index\n", __func__ ); + return NULL; + } + return &voice.players_status[playerent - 1]; +} + /* ========================= Voice_GetBitrateForQuality @@ -933,12 +951,13 @@ void Voice_Disconnect( void ) voice.local.talking_ack = false; } - for( i = 0; i < MAX_CLIENTS; i++ ) + for( i = 1; i <= MAX_CLIENTS; i++ ) { - if( voice.players_status[i].talking_ack ) + voice_status_t *status = Voice_GetPlayerStatus( i ); + if( status->talking_ack ) { Voice_Status( i, false ); - voice.players_status[i].talking_ack = false; + status->talking_ack = false; } } @@ -974,6 +993,7 @@ void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames ) const int playernum = ent - 1; int samples = 0; int ofs = 0; + voice_status_t *status = NULL; if( !voice.initialized || !voice_enable.value ) return; @@ -982,7 +1002,8 @@ void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames ) if( ent == cl.playernum ) Voice_StatusAck( &voice.local, VOICE_LOOPBACK_INDEX ); - Voice_StatusAck( &voice.players_status[playernum], ent ); + status = Voice_GetPlayerStatus( ent ); + Voice_StatusAck( status, ent ); if( voice.goldsrc ) { @@ -1115,9 +1136,10 @@ static void Voice_Shutdown( void ) if( voice.local.talking_ack ) Voice_Status( VOICE_LOOPBACK_INDEX, false ); - for( i = 0; i < MAX_CLIENTS; i++ ) + for( i = 1; i <= MAX_CLIENTS; i++ ) { - if( voice.players_status[i].talking_ack ) + voice_status_t *status = Voice_GetPlayerStatus( i ); + if( status->talking_ack ) Voice_Status( i, false ); } @@ -1167,8 +1189,11 @@ void Voice_Idle( double frametime ) // update local player status first Voice_StatusTimeout( &voice.local, VOICE_LOOPBACK_INDEX, frametime ); - for( i = 0; i < MAX_CLIENTS; i++ ) - Voice_StatusTimeout( &voice.players_status[i], i, frametime ); + for( i = 1; i <= MAX_CLIENTS; i++ ) + { + voice_status_t *status = Voice_GetPlayerStatus( i ); + Voice_StatusTimeout( status, i, frametime ); + } } /* diff --git a/engine/client/voice.h b/engine/client/voice.h index aeb7ab18..bbb77d7c 100644 --- a/engine/client/voice.h +++ b/engine/client/voice.h @@ -89,7 +89,7 @@ typedef struct voice_state_s double start_time; voice_status_t local; - voice_status_t players_status[MAX_CLIENTS]; + voice_status_t players_status[MAX_CLIENTS]; // do not access this directly, use Voice_GetPlayerStatus instead // opus stuff OpusCustomMode *custom_mode;