mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
Fix re-entrancy issue when a [generated] message is sent during register_event forward (bug 3664, r=joropito)
This commit is contained in:
parent
efe3bda51b
commit
163098892c
@ -55,16 +55,16 @@ EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
|
|||||||
m_FlagDead = (flags & 8) ? true : false; // flag d
|
m_FlagDead = (flags & 8) ? true : false; // flag d
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_FlagClient)
|
if (m_FlagClient)
|
||||||
{
|
{
|
||||||
m_FlagPlayer = true;
|
m_FlagPlayer = true;
|
||||||
m_FlagBot = true;
|
m_FlagBot = true;
|
||||||
|
|
||||||
if (flags & 96)
|
if (flags & 96)
|
||||||
{
|
{
|
||||||
m_FlagPlayer = (flags & 32) ? true : false; // flag f
|
m_FlagPlayer = (flags & 32) ? true : false; // flag f
|
||||||
m_FlagBot = (flags & 64) ? true : false; // flag g
|
m_FlagBot = (flags & 64) ? true : false; // flag g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Stamp = 0.0f;
|
m_Stamp = 0.0f;
|
||||||
@ -138,7 +138,11 @@ EventsMngr::EventsMngr()
|
|||||||
{
|
{
|
||||||
m_ParseVault = NULL;
|
m_ParseVault = NULL;
|
||||||
m_ParseVaultSize = 0;
|
m_ParseVaultSize = 0;
|
||||||
m_CurrentMsgType = -1;
|
m_ParseMsgType = -1;
|
||||||
|
m_ReadVault = NULL;
|
||||||
|
m_ReadVaultSize = 0;
|
||||||
|
m_ReadPos = -1;
|
||||||
|
m_ReadMsgType = -1;
|
||||||
clearEvents();
|
clearEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,15 +231,15 @@ void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int in
|
|||||||
if (msg_type < 0 || msg_type > MAX_AMX_REG_MSG)
|
if (msg_type < 0 || msg_type > MAX_AMX_REG_MSG)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_CurrentMsgType = msg_type;
|
|
||||||
|
|
||||||
m_ParseNotDone = false;
|
m_ParseNotDone = false;
|
||||||
m_Timer = timer;
|
|
||||||
|
|
||||||
// don't parse if nothing to do
|
// don't parse if nothing to do
|
||||||
if (!m_Events[msg_type].size())
|
if (!m_Events[msg_type].size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_ParseMsgType = msg_type;
|
||||||
|
m_Timer = timer;
|
||||||
|
|
||||||
for (ClEventVecIter iter = m_Events[msg_type].begin(); iter; ++iter)
|
for (ClEventVecIter iter = m_Events[msg_type].begin(); iter; ++iter)
|
||||||
{
|
{
|
||||||
if ((*iter).m_Done)
|
if ((*iter).m_Done)
|
||||||
@ -423,12 +427,46 @@ void EventsMngr::parseValue(const char *sz)
|
|||||||
|
|
||||||
void EventsMngr::executeEvents()
|
void EventsMngr::executeEvents()
|
||||||
{
|
{
|
||||||
|
static unsigned int reentrant = 0;
|
||||||
if (!m_ParseFun)
|
if (!m_ParseFun)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
|
// Store old read data, which are either default values or previous event data
|
||||||
|
int oldMsgType = m_ReadMsgType, oldReadPos = m_ReadPos;
|
||||||
|
MsgDataEntry *oldReadVault = m_ReadVault, *readVault = NULL;
|
||||||
|
|
||||||
|
// We have a re-entrant call
|
||||||
|
if (reentrant++)
|
||||||
|
{
|
||||||
|
// Create temporary read vault
|
||||||
|
readVault = new MsgDataEntry[m_ParsePos + 1];
|
||||||
|
m_ReadVault = readVault;
|
||||||
|
} else if (m_ReadVaultSize != m_ParseVaultSize) {
|
||||||
|
// Extend read vault size if necessary
|
||||||
|
delete [] m_ReadVault;
|
||||||
|
m_ReadVault = new MsgDataEntry[m_ParseVaultSize];
|
||||||
|
m_ReadVaultSize = m_ParseVaultSize;
|
||||||
|
|
||||||
|
// Update old read vault so we don't restore to a wrong pointer
|
||||||
|
oldReadVault = m_ReadVault;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data over to readvault
|
||||||
|
m_ReadPos = m_ParsePos;
|
||||||
|
m_ReadMsgType = m_ParseMsgType;
|
||||||
|
|
||||||
|
if (m_ParseVault)
|
||||||
|
{
|
||||||
|
memcpy(m_ReadVault, m_ParseVault, (m_ParsePos + 1) * sizeof(MsgDataEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset this here so we don't trigger re-entrancy for unregistered messages
|
||||||
|
ClEventVec *parseFun = m_ParseFun;
|
||||||
|
m_ParseFun = NULL;
|
||||||
|
|
||||||
|
for (ClEventVecIter iter = parseFun->begin(); iter; ++iter)
|
||||||
{
|
{
|
||||||
if ((*iter).m_Done)
|
if ((*iter).m_Done)
|
||||||
{
|
{
|
||||||
@ -437,67 +475,74 @@ void EventsMngr::executeEvents()
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*iter).m_Stamp = (float)*m_Timer;
|
(*iter).m_Stamp = (float)*m_Timer;
|
||||||
executeForwards((*iter).m_Func, static_cast<cell>(m_ParseVault ? m_ParseVault[0].iValue : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_CurrentMsgType = -1;
|
executeForwards((*iter).m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
|
||||||
m_ParseFun = NULL;
|
}
|
||||||
|
|
||||||
|
// Restore old read data, either resetting to default or to previous event data
|
||||||
|
m_ReadMsgType = oldMsgType;
|
||||||
|
m_ReadPos = oldReadPos;
|
||||||
|
m_ReadVault = oldReadVault;
|
||||||
|
|
||||||
|
delete [] readVault;
|
||||||
|
|
||||||
|
--reentrant;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EventsMngr::getArgNum() const
|
int EventsMngr::getArgNum() const
|
||||||
{
|
{
|
||||||
return m_ParsePos + 1;
|
return m_ReadPos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* EventsMngr::getArgString(int a) const
|
const char* EventsMngr::getArgString(int a) const
|
||||||
{
|
{
|
||||||
if (a < 0 || a > m_ParsePos)
|
if (a < 0 || a > m_ReadPos)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
static char var[32];
|
static char var[32];
|
||||||
|
|
||||||
switch (m_ParseVault[a].type)
|
switch (m_ReadVault[a].type)
|
||||||
{
|
{
|
||||||
case MSG_INTEGER:
|
case MSG_INTEGER:
|
||||||
sprintf(var, "%d", m_ParseVault[a].iValue);
|
sprintf(var, "%d", m_ReadVault[a].iValue);
|
||||||
return var;
|
return var;
|
||||||
case MSG_STRING:
|
case MSG_STRING:
|
||||||
return m_ParseVault[a].sValue;
|
return m_ReadVault[a].sValue;
|
||||||
default:
|
default:
|
||||||
sprintf(var, "%g", m_ParseVault[a].fValue);
|
sprintf(var, "%g", m_ReadVault[a].fValue);
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EventsMngr::getArgInteger(int a) const
|
int EventsMngr::getArgInteger(int a) const
|
||||||
{
|
{
|
||||||
if (a < 0 || a > m_ParsePos)
|
if (a < 0 || a > m_ReadPos)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (m_ParseVault[a].type)
|
switch (m_ReadVault[a].type)
|
||||||
{
|
{
|
||||||
case MSG_INTEGER:
|
case MSG_INTEGER:
|
||||||
return m_ParseVault[a].iValue;
|
return m_ReadVault[a].iValue;
|
||||||
case MSG_STRING:
|
case MSG_STRING:
|
||||||
return atoi(m_ParseVault[a].sValue);
|
return atoi(m_ReadVault[a].sValue);
|
||||||
default:
|
default:
|
||||||
return (int)m_ParseVault[a].fValue;
|
return (int)m_ReadVault[a].fValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float EventsMngr::getArgFloat(int a) const
|
float EventsMngr::getArgFloat(int a) const
|
||||||
{
|
{
|
||||||
if (a < 0 || a > m_ParsePos)
|
if (a < 0 || a > m_ReadPos)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
switch (m_ParseVault[a].type)
|
switch (m_ReadVault[a].type)
|
||||||
{
|
{
|
||||||
case MSG_INTEGER:
|
case MSG_INTEGER:
|
||||||
return static_cast<float>(m_ParseVault[a].iValue);
|
return static_cast<float>(m_ReadVault[a].iValue);
|
||||||
case MSG_STRING:
|
case MSG_STRING:
|
||||||
return static_cast<float>(atof(m_ParseVault[a].sValue));
|
return static_cast<float>(atof(m_ReadVault[a].sValue));
|
||||||
default:
|
default:
|
||||||
return m_ParseVault[a].fValue;
|
return m_ReadVault[a].fValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,6 +560,14 @@ void EventsMngr::clearEvents(void)
|
|||||||
m_ParseVault = NULL;
|
m_ParseVault = NULL;
|
||||||
m_ParseVaultSize = 0;
|
m_ParseVaultSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ReadVault)
|
||||||
|
{
|
||||||
|
delete [] m_ReadVault;
|
||||||
|
m_ReadVault = NULL;
|
||||||
|
m_ReadVaultSize = 0;
|
||||||
|
m_ReadPos = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EventsMngr::getEventId(const char* msg)
|
int EventsMngr::getEventId(const char* msg)
|
||||||
@ -550,5 +603,5 @@ int EventsMngr::getEventId(const char* msg)
|
|||||||
|
|
||||||
int EventsMngr::getCurrentMsgType()
|
int EventsMngr::getCurrentMsgType()
|
||||||
{
|
{
|
||||||
return m_CurrentMsgType;
|
return m_ReadMsgType;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
MsgDataEntry *m_ParseVault;
|
MsgDataEntry *m_ParseVault;
|
||||||
|
MsgDataEntry *m_ReadVault;
|
||||||
int m_ParseVaultSize;
|
int m_ParseVaultSize;
|
||||||
|
int m_ReadVaultSize;
|
||||||
void NextParam(); // make sure a new parameter can be added
|
void NextParam(); // make sure a new parameter can be added
|
||||||
|
|
||||||
typedef CList<ClEvent> ClEventVec;
|
typedef CList<ClEvent> ClEventVec;
|
||||||
@ -132,11 +134,13 @@ private:
|
|||||||
|
|
||||||
bool m_ParseNotDone;
|
bool m_ParseNotDone;
|
||||||
int m_ParsePos; // is args. num. - 1
|
int m_ParsePos; // is args. num. - 1
|
||||||
|
int m_ReadPos;
|
||||||
float* m_Timer;
|
float* m_Timer;
|
||||||
|
|
||||||
ClEvent* getValidEvent(ClEvent* a);
|
ClEvent* getValidEvent(ClEvent* a);
|
||||||
|
|
||||||
int m_CurrentMsgType;
|
int m_ParseMsgType;
|
||||||
|
int m_ReadMsgType;
|
||||||
public:
|
public:
|
||||||
EventsMngr();
|
EventsMngr();
|
||||||
~EventsMngr();
|
~EventsMngr();
|
||||||
|
@ -2036,6 +2036,11 @@ static cell AMX_NATIVE_CALL read_data(AMX *amx, cell *params) /* 3 param */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL read_datatype(AMX *amx, cell *params) /* 0 param */
|
||||||
|
{
|
||||||
|
return g_events.getCurrentMsgType();
|
||||||
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_playersnum(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL get_playersnum(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
if (!params[1])
|
if (!params[1])
|
||||||
@ -4622,6 +4627,7 @@ static cell AMX_NATIVE_CALL is_rukia_a_hag(AMX *amx, cell *params)
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
AMX_NATIVE_INFO amxmodx_Natives[] =
|
AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{
|
{
|
||||||
{"abort", amx_abort},
|
{"abort", amx_abort},
|
||||||
@ -4762,6 +4768,7 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||||||
{"read_argv", read_argv},
|
{"read_argv", read_argv},
|
||||||
{"read_data", read_data},
|
{"read_data", read_data},
|
||||||
{"read_datanum", read_datanum},
|
{"read_datanum", read_datanum},
|
||||||
|
{"read_datatype", read_datatype},
|
||||||
{"read_flags", read_flags},
|
{"read_flags", read_flags},
|
||||||
{"read_logargc", read_logargc},
|
{"read_logargc", read_logargc},
|
||||||
{"read_logargv", read_logargv},
|
{"read_logargv", read_logargv},
|
||||||
|
@ -162,6 +162,9 @@ native read_data(value, any:... );
|
|||||||
/* Returns number of values in client message. */
|
/* Returns number of values in client message. */
|
||||||
native read_datanum();
|
native read_datanum();
|
||||||
|
|
||||||
|
/* Returns message id of client message */
|
||||||
|
native read_datatype();
|
||||||
|
|
||||||
/* Gets log message. Can be called only in plugin_log() forward function. */
|
/* Gets log message. Can be called only in plugin_log() forward function. */
|
||||||
native read_logdata(output[],len);
|
native read_logdata(output[],len);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user