engine: check for overflow in split packet reassembly

This commit is contained in:
Alibek Omarov
2026-05-16 21:13:47 +05:00
parent 166763a887
commit fb6c4a224c
3 changed files with 23 additions and 19 deletions

View File

@@ -1657,9 +1657,9 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
}
int CL_GetSplitSize( void )
size_t CL_GetSplitSize( void )
{
int splitsize = (int)cl_dlmax.value;
size_t splitsize = (int)cl_dlmax.value;
if( !FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
return 1400;
@@ -1670,7 +1670,7 @@ int CL_GetSplitSize( void )
return FRAGMENT_DEFAULT_SIZE;
}
return (int)cl_dlmax.value;
return splitsize;
}
void CL_SetupNetchanForProtocol( connprotocol_t proto )

View File

@@ -1239,25 +1239,21 @@ NET_GetLong
receive long packet from network
==================
*/
static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsize, connprotocol_t proto )
static qboolean NET_GetLong( byte *pData, size_t size, size_t *outSize, size_t splitsize, connprotocol_t proto )
{
int i, sequence_number, offset;
int packet_number;
int packet_count;
short packet_id;
size_t header_size = proto == PROTO_GOLDSRC ? sizeof( SPLITPACKETGS ) : sizeof( SPLITPACKET );
int body_size = splitsize - header_size;
int max_splits;
const size_t header_size = proto == PROTO_GOLDSRC ? sizeof( SPLITPACKETGS ) : sizeof( SPLITPACKET );
if( body_size < 0 )
if( splitsize < header_size )
return false;
if( size < header_size )
{
Con_Printf( S_ERROR "invalid split packet length %i\n", size );
Con_Printf( S_ERROR "invalid split packet length %zu\n", size );
return false;
}
int sequence_number, packet_count, packet_number, max_splits;
short packet_id;
if( proto == PROTO_GOLDSRC )
{
SPLITPACKETGS *pHeader = (SPLITPACKETGS *)pData;
@@ -1281,7 +1277,7 @@ static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsi
max_splits = ARRAYSIZE( net.split_flags );
}
if( packet_number >= max_splits || packet_count > max_splits )
if( packet_number < 0 || packet_count <= 0 || packet_number >= max_splits || packet_count > max_splits || packet_number >= packet_count )
{
Con_Printf( S_ERROR "malformed packet number (%i/%i)\n", packet_number + 1, packet_count );
return false;
@@ -1294,7 +1290,7 @@ static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsi
net.split.total_size = 0;
// clear part's sequence
for( i = 0; i < ARRAYSIZE( net.split_flags ); i++ )
for( int i = 0; i < ARRAYSIZE( net.split_flags ); i++ )
net.split_flags[i] = -1;
if( net_showpackets.value == 4.0f )
@@ -1303,6 +1299,15 @@ static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsi
size -= header_size;
size_t body_size = splitsize - header_size;
size_t offset = (size_t)packet_number * body_size;
if( offset + size > sizeof( net.split.buffer ))
{
Con_Printf( S_ERROR "%s: split packet would overflow reassembly buffer (offset %zu + size %zu > %zu)\n",
__func__, offset, size, sizeof( net.split.buffer ));
return false;
}
if( net.split_flags[packet_number] != sequence_number )
{
if( packet_number == ( packet_count - 1 ))
@@ -1312,14 +1317,13 @@ static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsi
net.split_flags[packet_number] = sequence_number;
if( net_showpackets.value == 4.0f )
Con_Printf( "<-- Split packet %i of %i, %i bytes %i seq\n", packet_number + 1, packet_count, size, sequence_number );
Con_Printf( "<-- Split packet %i of %i, %zu bytes %i seq\n", packet_number + 1, packet_count, size, sequence_number );
}
else
{
Con_DPrintf( "%s: Ignoring duplicated split packet %i of %i ( %i bytes )\n", __func__, packet_number + 1, packet_count, size );
Con_DPrintf( "%s: Ignoring duplicated split packet %i of %i ( %zu bytes )\n", __func__, packet_number + 1, packet_count, size );
}
offset = (packet_number * body_size);
memcpy( net.split.buffer + offset, pData + header_size, size );
// have we received all of the pieces to the packet?

View File

@@ -86,7 +86,7 @@ static inline qboolean NET_IsLocalAddress( netadr_t adr )
void NET_GetLocalAddress( netadr_t *ip4, netadr_t *ip6 );
#if !XASH_DEDICATED
int CL_GetSplitSize( void );
size_t CL_GetSplitSize( void );
#endif
void HTTP_AddCustomServer( const char *url );