All natives that use a recipient filter now actually validate the clients passed to them.
authorScott Ehlert <ds@alliedmods.net>
Wed Jun 11 08:07:17 2008 +0000 (2008-06-11)
changeset 21122a83a521287c
parent 2111 5c01f6c73dc8
child 2113 8e8b28162e23
All natives that use a recipient filter now actually validate the clients passed to them.
This includes StartMessage(), StartMessageEx() from Core as well as EmitSound(), EmitSentence(), and TE_Send() from SDKTools

(Warning: This may potentially cause a minor compatibility problem with plugins that don't check client validity before passing to these natives)
core/sm_stringutil.cpp
core/smn_usermsgs.cpp
extensions/sdktools/tenatives.cpp
extensions/sdktools/vsound.cpp
plugins/include/usermessages.inc
     1.1 --- a/core/sm_stringutil.cpp	Mon Jun 09 22:17:09 2008 +0000
     1.2 +++ b/core/sm_stringutil.cpp	Wed Jun 11 08:07:17 2008 +0000
     1.3 @@ -1385,7 +1385,7 @@
     1.4   * NOTE: Do not edit this for the love of god unless you have 
     1.5   * read the test cases and understand the code behind each one.
     1.6   * While I don't guarantee there aren't mistakes, I do guarantee
     1.7 - * that plugins will end up relying on tiny idiosyncracies of this
     1.8 + * that plugins will end up relying on tiny idiosyncrasies of this
     1.9   * function, just like they did with AMX Mod X.
    1.10   *
    1.11   * There are explicitly more cases than the AMX Mod X version because
     2.1 --- a/core/smn_usermsgs.cpp	Mon Jun 09 22:17:09 2008 +0000
     2.2 +++ b/core/smn_usermsgs.cpp	Wed Jun 11 08:07:17 2008 +0000
     2.3 @@ -32,6 +32,7 @@
     2.4  #include "HandleSys.h"
     2.5  #include "PluginSys.h"
     2.6  #include "UserMessages.h"
     2.7 +#include "PlayerManager.h"
     2.8  #include "smn_usermsgs.h"
     2.9  
    2.10  HandleType_t g_WrBitBufType;
    2.11 @@ -349,8 +350,11 @@
    2.12  {
    2.13  	char *msgname;
    2.14  	cell_t *cl_array;
    2.15 +	unsigned int numClients;
    2.16  	int msgid;
    2.17  	bf_write *pBitBuf;
    2.18 +	int client;
    2.19 +	CPlayer *pPlayer = NULL;
    2.20  
    2.21  	if (g_IsMsgInExec)
    2.22  	{
    2.23 @@ -366,7 +370,23 @@
    2.24  
    2.25  	pCtx->LocalToPhysAddr(params[2], &cl_array);
    2.26  
    2.27 -	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
    2.28 +	numClients = params[3];
    2.29 +
    2.30 +	/* Client validation */
    2.31 +	for (unsigned int i = 0; i < numClients; i++)
    2.32 +	{
    2.33 +		client = cl_array[i];
    2.34 +		pPlayer = g_Players.GetPlayerByIndex(client);
    2.35 +
    2.36 +		if (!pPlayer)
    2.37 +		{
    2.38 +			return pCtx->ThrowNativeError("Client index %d is invalid", client);
    2.39 +		} else if (!pPlayer->IsConnected()) {
    2.40 +			return pCtx->ThrowNativeError("Client %d is not connected", client);
    2.41 +		}
    2.42 +	}
    2.43 +
    2.44 +	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
    2.45  	if (!pBitBuf)
    2.46  	{
    2.47  		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
    2.48 @@ -381,7 +401,10 @@
    2.49  static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
    2.50  {
    2.51  	cell_t *cl_array;
    2.52 +	unsigned int numClients;
    2.53  	bf_write *pBitBuf;
    2.54 +	int client;
    2.55 +	CPlayer *pPlayer = NULL;
    2.56  	int msgid = params[1];
    2.57  
    2.58  	if (g_IsMsgInExec)
    2.59 @@ -396,7 +419,23 @@
    2.60  
    2.61  	pCtx->LocalToPhysAddr(params[2], &cl_array);
    2.62  
    2.63 -	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
    2.64 +	numClients = params[3];
    2.65 +
    2.66 +	/* Client validation */
    2.67 +	for (unsigned int i = 0; i < numClients; i++)
    2.68 +	{
    2.69 +		client = cl_array[i];
    2.70 +		pPlayer = g_Players.GetPlayerByIndex(client);
    2.71 +
    2.72 +		if (!pPlayer)
    2.73 +		{
    2.74 +			return pCtx->ThrowNativeError("Client index %d is invalid", client);
    2.75 +		} else if (!pPlayer->IsConnected()) {
    2.76 +			return pCtx->ThrowNativeError("Client %d is not connected", client);
    2.77 +		}
    2.78 +	}
    2.79 +
    2.80 +	pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
    2.81  	if (!pBitBuf)
    2.82  	{
    2.83  		return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
     3.1 --- a/extensions/sdktools/tenatives.cpp	Mon Jun 09 22:17:09 2008 +0000
     3.2 +++ b/extensions/sdktools/tenatives.cpp	Wed Jun 11 08:07:17 2008 +0000
     3.3 @@ -445,10 +445,29 @@
     3.4  	}
     3.5  
     3.6  	cell_t *cl_array;
     3.7 +	unsigned int numClients;
     3.8 +	int client;
     3.9 +	IGamePlayer *pPlayer = NULL;
    3.10 +
    3.11  	pContext->LocalToPhysAddr(params[1], &cl_array);
    3.12 +	numClients = params[2];
    3.13 +
    3.14 +	/* Client validation */
    3.15 +	for (unsigned int i = 0; i < numClients; i++)
    3.16 +	{
    3.17 +		client = cl_array[i];
    3.18 +		pPlayer = playerhelpers->GetGamePlayer(client);
    3.19 +
    3.20 +		if (!pPlayer)
    3.21 +		{
    3.22 +			return pContext->ThrowNativeError("Client index %d is invalid", client);
    3.23 +		} else if (!pPlayer->IsInGame()) {
    3.24 +			return pContext->ThrowNativeError("Client %d is not connected", client);
    3.25 +		}
    3.26 +	}
    3.27  
    3.28  	g_TERecFilter.Reset();
    3.29 -	g_TERecFilter.Initialize(cl_array, params[2]);
    3.30 +	g_TERecFilter.Initialize(cl_array, numClients);
    3.31  
    3.32  	g_CurrentTE->Send(g_TERecFilter, sp_ctof(params[3]));
    3.33  	g_CurrentTE = NULL;
     4.1 --- a/extensions/sdktools/vsound.cpp	Mon Jun 09 22:17:09 2008 +0000
     4.2 +++ b/extensions/sdktools/vsound.cpp	Wed Jun 11 08:07:17 2008 +0000
     4.3 @@ -449,11 +449,30 @@
     4.4  
     4.5  static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
     4.6  {
     4.7 -	cell_t *addr, *pl_addr;
     4.8 -
     4.9 +	cell_t *addr, *cl_array;
    4.10  	CellRecipientFilter crf;
    4.11 -	pContext->LocalToPhysAddr(params[1], &pl_addr);
    4.12 -	crf.Initialize(pl_addr, params[2]);
    4.13 +	unsigned int numClients;
    4.14 +	int client;
    4.15 +	IGamePlayer *pPlayer = NULL;
    4.16 +
    4.17 +	pContext->LocalToPhysAddr(params[1], &cl_array);
    4.18 +	numClients = params[2];
    4.19 +
    4.20 +	/* Client validation */
    4.21 +	for (unsigned int i = 0; i < numClients; i++)
    4.22 +	{
    4.23 +		client = cl_array[i];
    4.24 +		pPlayer = playerhelpers->GetGamePlayer(client);
    4.25 +
    4.26 +		if (!pPlayer)
    4.27 +		{
    4.28 +			return pContext->ThrowNativeError("Client index %d is invalid", client);
    4.29 +		} else if (!pPlayer->IsInGame()) {
    4.30 +			return pContext->ThrowNativeError("Client %d is not connected", client);
    4.31 +		}
    4.32 +	}
    4.33 +
    4.34 +	crf.Initialize(cl_array, numClients);
    4.35  
    4.36  	char *sample;
    4.37  	pContext->LocalToString(params[3], &sample);
    4.38 @@ -512,10 +531,10 @@
    4.39  
    4.40  	if (entity == -2 && engine->IsDedicatedServer())
    4.41  	{
    4.42 -		for (cell_t i=0; i<params[2]; i++)
    4.43 +		for (unsigned int i = 0; i < numClients; i++)
    4.44  		{
    4.45  			cell_t player[1];
    4.46 -			player[0] = pl_addr[i];
    4.47 +			player[0] = cl_array[i];
    4.48  			crf.Reset();
    4.49  			crf.Initialize(player, 1);
    4.50  			if (g_InSoundHook)
    4.51 @@ -604,10 +623,29 @@
    4.52  static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
    4.53  {
    4.54  	cell_t *addr;
    4.55 +	CellRecipientFilter crf;
    4.56 +	unsigned int numClients;
    4.57 +	int client;
    4.58 +	IGamePlayer *pPlayer = NULL;
    4.59  
    4.60 -	CellRecipientFilter crf;
    4.61  	pContext->LocalToPhysAddr(params[1], &addr);
    4.62 -	crf.Initialize(addr, params[2]);
    4.63 +	numClients = params[2];
    4.64 +
    4.65 +	/* Client validation */
    4.66 +	for (unsigned int i = 0; i < numClients; i++)
    4.67 +	{
    4.68 +		client = addr[i];
    4.69 +		pPlayer = playerhelpers->GetGamePlayer(client);
    4.70 +
    4.71 +		if (!pPlayer)
    4.72 +		{
    4.73 +			return pContext->ThrowNativeError("Client index %d is invalid", client);
    4.74 +		} else if (!pPlayer->IsInGame()) {
    4.75 +			return pContext->ThrowNativeError("Client %d is not connected", client);
    4.76 +		}
    4.77 +	}
    4.78 +
    4.79 +	crf.Initialize(addr, numClients);
    4.80  
    4.81  	int sentence = params[3];
    4.82  	int entity = params[4];
     5.1 --- a/plugins/include/usermessages.inc	Mon Jun 09 22:17:09 2008 +0000
     5.2 +++ b/plugins/include/usermessages.inc	Wed Jun 11 08:07:17 2008 +0000
     5.3 @@ -83,7 +83,8 @@
     5.4   * @param flags			Optional flags to set.
     5.5   * @return				A handle to a bf_write bit packing structure, or
     5.6   *						INVALID_HANDLE on failure.
     5.7 - * @error				Invalid message name or unable to start a message.
     5.8 + * @error				Invalid message name, unable to start a message, invalid client,
     5.9 + *						or client not connected.
    5.10   */
    5.11  native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0);
    5.12  
    5.13 @@ -98,7 +99,8 @@
    5.14   * @param flags			Optional flags to set.
    5.15   * @return				A handle to a bf_write bit packing structure, or
    5.16   *						INVALID_HANDLE on failure.
    5.17 - * @error				Invalid message name or unable to start a message.
    5.18 + * @error				Invalid message name, unable to start a message, invalid client,
    5.19 + *						or client not connected.
    5.20   */
    5.21  native Handle:StartMessageEx(UserMsg:msg, clients[], numClients, flags=0);
    5.22