From ac68a441eefe5d01fda7450dc1c5aefe0984a0f1 Mon Sep 17 00:00:00 2001 From: Scott Ehlert Date: Wed, 11 Jun 2008 08:07:17 +0000 Subject: [PATCH] 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 --- core/sm_stringutil.cpp | 2 +- core/smn_usermsgs.cpp | 43 ++++++++++++++++++++++-- extensions/sdktools/tenatives.cpp | 21 +++++++++++- extensions/sdktools/vsound.cpp | 54 ++++++++++++++++++++++++++----- plugins/include/usermessages.inc | 6 ++-- 5 files changed, 112 insertions(+), 14 deletions(-) diff --git a/core/sm_stringutil.cpp b/core/sm_stringutil.cpp index 020a87eb..96a3831c 100644 --- a/core/sm_stringutil.cpp +++ b/core/sm_stringutil.cpp @@ -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 * read the test cases and understand the code behind each one. * 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. * * There are explicitly more cases than the AMX Mod X version because diff --git a/core/smn_usermsgs.cpp b/core/smn_usermsgs.cpp index b1206e53..3ea96ada 100644 --- a/core/smn_usermsgs.cpp +++ b/core/smn_usermsgs.cpp @@ -32,6 +32,7 @@ #include "HandleSys.h" #include "PluginSys.h" #include "UserMessages.h" +#include "PlayerManager.h" #include "smn_usermsgs.h" HandleType_t g_WrBitBufType; @@ -349,8 +350,11 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params) { char *msgname; cell_t *cl_array; + unsigned int numClients; int msgid; bf_write *pBitBuf; + int client; + CPlayer *pPlayer = NULL; if (g_IsMsgInExec) { @@ -366,7 +370,23 @@ static cell_t smn_StartMessage(IPluginContext *pCtx, const cell_t *params) 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) { 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) { cell_t *cl_array; + unsigned int numClients; bf_write *pBitBuf; + int client; + CPlayer *pPlayer = NULL; int msgid = params[1]; if (g_IsMsgInExec) @@ -396,7 +419,23 @@ static cell_t smn_StartMessageEx(IPluginContext *pCtx, const cell_t *params) 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) { return pCtx->ThrowNativeError("Unable to execute a new message while in hook"); diff --git a/extensions/sdktools/tenatives.cpp b/extensions/sdktools/tenatives.cpp index 4d0b69f3..0f4e20ed 100644 --- a/extensions/sdktools/tenatives.cpp +++ b/extensions/sdktools/tenatives.cpp @@ -445,10 +445,29 @@ static cell_t smn_TESend(IPluginContext *pContext, const cell_t *params) } cell_t *cl_array; + unsigned int numClients; + 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); + } + } 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 = NULL; diff --git a/extensions/sdktools/vsound.cpp b/extensions/sdktools/vsound.cpp index 078f39fb..224d5c50 100644 --- a/extensions/sdktools/vsound.cpp +++ b/extensions/sdktools/vsound.cpp @@ -449,11 +449,30 @@ static cell_t StopSound(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; - pContext->LocalToPhysAddr(params[1], &pl_addr); - crf.Initialize(pl_addr, params[2]); + unsigned int numClients; + 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; pContext->LocalToString(params[3], &sample); @@ -512,10 +531,10 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) if (entity == -2 && engine->IsDedicatedServer()) { - for (cell_t i=0; iLocalToPhysAddr(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 entity = params[4]; diff --git a/plugins/include/usermessages.inc b/plugins/include/usermessages.inc index e90fa81f..7fc57731 100644 --- a/plugins/include/usermessages.inc +++ b/plugins/include/usermessages.inc @@ -83,7 +83,8 @@ native bool:GetUserMessageName(UserMsg:msg_id, String:msg[], maxlength); * @param flags Optional flags to set. * @return A handle to a bf_write bit packing structure, or * 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); @@ -98,7 +99,8 @@ native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0); * @param flags Optional flags to set. * @return A handle to a bf_write bit packing structure, or * 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);