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) --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402252
This commit is contained in:
parent
119592eefe
commit
ac68a441ee
@ -1385,7 +1385,7 @@ unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search
|
|||||||
* NOTE: Do not edit this for the love of god unless you have
|
* NOTE: Do not edit this for the love of god unless you have
|
||||||
* read the test cases and understand the code behind each one.
|
* read the test cases and understand the code behind each one.
|
||||||
* While I don't guarantee there aren't mistakes, I do guarantee
|
* While I don't guarantee there aren't mistakes, I do guarantee
|
||||||
* that plugins will end up relying on tiny idiosyncracies of this
|
* that plugins will end up relying on tiny idiosyncrasies of this
|
||||||
* function, just like they did with AMX Mod X.
|
* function, just like they did with AMX Mod X.
|
||||||
*
|
*
|
||||||
* There are explicitly more cases than the AMX Mod X version because
|
* There are explicitly more cases than the AMX Mod X version because
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "HandleSys.h"
|
#include "HandleSys.h"
|
||||||
#include "PluginSys.h"
|
#include "PluginSys.h"
|
||||||
#include "UserMessages.h"
|
#include "UserMessages.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
#include "smn_usermsgs.h"
|
#include "smn_usermsgs.h"
|
||||||
|
|
||||||
HandleType_t g_WrBitBufType;
|
HandleType_t g_WrBitBufType;
|
||||||
@ -349,8 +350,11 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
|
|||||||
{
|
{
|
||||||
char *msgname;
|
char *msgname;
|
||||||
cell_t *cl_array;
|
cell_t *cl_array;
|
||||||
|
unsigned int numClients;
|
||||||
int msgid;
|
int msgid;
|
||||||
bf_write *pBitBuf;
|
bf_write *pBitBuf;
|
||||||
|
int client;
|
||||||
|
CPlayer *pPlayer = NULL;
|
||||||
|
|
||||||
if (g_IsMsgInExec)
|
if (g_IsMsgInExec)
|
||||||
{
|
{
|
||||||
@ -366,7 +370,23 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
|
|||||||
|
|
||||||
pCtx->LocalToPhysAddr(params[2], &cl_array);
|
pCtx->LocalToPhysAddr(params[2], &cl_array);
|
||||||
|
|
||||||
pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
|
numClients = params[3];
|
||||||
|
|
||||||
|
/* Client validation */
|
||||||
|
for (unsigned int i = 0; i < numClients; i++)
|
||||||
|
{
|
||||||
|
client = cl_array[i];
|
||||||
|
pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
return pCtx->ThrowNativeError("Client index %d is invalid", client);
|
||||||
|
} else if (!pPlayer->IsConnected()) {
|
||||||
|
return pCtx->ThrowNativeError("Client %d is not connected", client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
|
||||||
if (!pBitBuf)
|
if (!pBitBuf)
|
||||||
{
|
{
|
||||||
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
||||||
@ -381,7 +401,10 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params)
|
|||||||
static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
|
static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
|
||||||
{
|
{
|
||||||
cell_t *cl_array;
|
cell_t *cl_array;
|
||||||
|
unsigned int numClients;
|
||||||
bf_write *pBitBuf;
|
bf_write *pBitBuf;
|
||||||
|
int client;
|
||||||
|
CPlayer *pPlayer = NULL;
|
||||||
int msgid = params[1];
|
int msgid = params[1];
|
||||||
|
|
||||||
if (g_IsMsgInExec)
|
if (g_IsMsgInExec)
|
||||||
@ -396,7 +419,23 @@ static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params)
|
|||||||
|
|
||||||
pCtx->LocalToPhysAddr(params[2], &cl_array);
|
pCtx->LocalToPhysAddr(params[2], &cl_array);
|
||||||
|
|
||||||
pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, params[3], params[4]);
|
numClients = params[3];
|
||||||
|
|
||||||
|
/* Client validation */
|
||||||
|
for (unsigned int i = 0; i < numClients; i++)
|
||||||
|
{
|
||||||
|
client = cl_array[i];
|
||||||
|
pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
return pCtx->ThrowNativeError("Client index %d is invalid", client);
|
||||||
|
} else if (!pPlayer->IsConnected()) {
|
||||||
|
return pCtx->ThrowNativeError("Client %d is not connected", client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitBuf = g_UserMsgs.StartMessage(msgid, cl_array, numClients, params[4]);
|
||||||
if (!pBitBuf)
|
if (!pBitBuf)
|
||||||
{
|
{
|
||||||
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
return pCtx->ThrowNativeError("Unable to execute a new message while in hook");
|
||||||
|
@ -445,10 +445,29 @@ static cell_t smn_TESend(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cell_t *cl_array;
|
cell_t *cl_array;
|
||||||
|
unsigned int numClients;
|
||||||
|
int client;
|
||||||
|
IGamePlayer *pPlayer = NULL;
|
||||||
|
|
||||||
pContext->LocalToPhysAddr(params[1], &cl_array);
|
pContext->LocalToPhysAddr(params[1], &cl_array);
|
||||||
|
numClients = params[2];
|
||||||
|
|
||||||
|
/* Client validation */
|
||||||
|
for (unsigned int i = 0; i < numClients; i++)
|
||||||
|
{
|
||||||
|
client = cl_array[i];
|
||||||
|
pPlayer = playerhelpers->GetGamePlayer(client);
|
||||||
|
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||||
|
} else if (!pPlayer->IsInGame()) {
|
||||||
|
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_TERecFilter.Reset();
|
g_TERecFilter.Reset();
|
||||||
g_TERecFilter.Initialize(cl_array, params[2]);
|
g_TERecFilter.Initialize(cl_array, numClients);
|
||||||
|
|
||||||
g_CurrentTE->Send(g_TERecFilter, sp_ctof(params[3]));
|
g_CurrentTE->Send(g_TERecFilter, sp_ctof(params[3]));
|
||||||
g_CurrentTE = NULL;
|
g_CurrentTE = NULL;
|
||||||
|
@ -449,11 +449,30 @@ static cell_t StopSound(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
|
static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
cell_t *addr, *pl_addr;
|
cell_t *addr, *cl_array;
|
||||||
|
|
||||||
CellRecipientFilter crf;
|
CellRecipientFilter crf;
|
||||||
pContext->LocalToPhysAddr(params[1], &pl_addr);
|
unsigned int numClients;
|
||||||
crf.Initialize(pl_addr, params[2]);
|
int client;
|
||||||
|
IGamePlayer *pPlayer = NULL;
|
||||||
|
|
||||||
|
pContext->LocalToPhysAddr(params[1], &cl_array);
|
||||||
|
numClients = params[2];
|
||||||
|
|
||||||
|
/* Client validation */
|
||||||
|
for (unsigned int i = 0; i < numClients; i++)
|
||||||
|
{
|
||||||
|
client = cl_array[i];
|
||||||
|
pPlayer = playerhelpers->GetGamePlayer(client);
|
||||||
|
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||||
|
} else if (!pPlayer->IsInGame()) {
|
||||||
|
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crf.Initialize(cl_array, numClients);
|
||||||
|
|
||||||
char *sample;
|
char *sample;
|
||||||
pContext->LocalToString(params[3], &sample);
|
pContext->LocalToString(params[3], &sample);
|
||||||
@ -512,10 +531,10 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
if (entity == -2 && engine->IsDedicatedServer())
|
if (entity == -2 && engine->IsDedicatedServer())
|
||||||
{
|
{
|
||||||
for (cell_t i=0; i<params[2]; i++)
|
for (unsigned int i = 0; i < numClients; i++)
|
||||||
{
|
{
|
||||||
cell_t player[1];
|
cell_t player[1];
|
||||||
player[0] = pl_addr[i];
|
player[0] = cl_array[i];
|
||||||
crf.Reset();
|
crf.Reset();
|
||||||
crf.Initialize(player, 1);
|
crf.Initialize(player, 1);
|
||||||
if (g_InSoundHook)
|
if (g_InSoundHook)
|
||||||
@ -604,10 +623,29 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
|
|||||||
static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
|
static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
cell_t *addr;
|
cell_t *addr;
|
||||||
|
|
||||||
CellRecipientFilter crf;
|
CellRecipientFilter crf;
|
||||||
|
unsigned int numClients;
|
||||||
|
int client;
|
||||||
|
IGamePlayer *pPlayer = NULL;
|
||||||
|
|
||||||
pContext->LocalToPhysAddr(params[1], &addr);
|
pContext->LocalToPhysAddr(params[1], &addr);
|
||||||
crf.Initialize(addr, params[2]);
|
numClients = params[2];
|
||||||
|
|
||||||
|
/* Client validation */
|
||||||
|
for (unsigned int i = 0; i < numClients; i++)
|
||||||
|
{
|
||||||
|
client = addr[i];
|
||||||
|
pPlayer = playerhelpers->GetGamePlayer(client);
|
||||||
|
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||||
|
} else if (!pPlayer->IsInGame()) {
|
||||||
|
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crf.Initialize(addr, numClients);
|
||||||
|
|
||||||
int sentence = params[3];
|
int sentence = params[3];
|
||||||
int entity = params[4];
|
int entity = params[4];
|
||||||
|
@ -83,7 +83,8 @@ native bool:GetUserMessageName(UserMsg:msg_id, String:msg[], maxlength);
|
|||||||
* @param flags Optional flags to set.
|
* @param flags Optional flags to set.
|
||||||
* @return A handle to a bf_write bit packing structure, or
|
* @return A handle to a bf_write bit packing structure, or
|
||||||
* INVALID_HANDLE on failure.
|
* INVALID_HANDLE on failure.
|
||||||
* @error Invalid message name or unable to start a message.
|
* @error Invalid message name, unable to start a message, invalid client,
|
||||||
|
* or client not connected.
|
||||||
*/
|
*/
|
||||||
native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0);
|
native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0);
|
||||||
|
|
||||||
@ -98,7 +99,8 @@ native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0);
|
|||||||
* @param flags Optional flags to set.
|
* @param flags Optional flags to set.
|
||||||
* @return A handle to a bf_write bit packing structure, or
|
* @return A handle to a bf_write bit packing structure, or
|
||||||
* INVALID_HANDLE on failure.
|
* INVALID_HANDLE on failure.
|
||||||
* @error Invalid message name or unable to start a message.
|
* @error Invalid message name, unable to start a message, invalid client,
|
||||||
|
* or client not connected.
|
||||||
*/
|
*/
|
||||||
native Handle:StartMessageEx(UserMsg:msg, clients[], numClients, flags=0);
|
native Handle:StartMessageEx(UserMsg:msg, clients[], numClients, flags=0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user