From 4e6834a7a4b65f52169ba8073d5d85fd7542bfca Mon Sep 17 00:00:00 2001 From: Scott Ehlert Date: Thu, 12 Apr 2007 07:51:05 +0000 Subject: [PATCH] Fixed amb190 - Crash with Mani's spawn protection and GetEvent (which exposed re-entrancy problems in EventManager) --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40690 --- core/EventManager.cpp | 32 ++++++++++++++++++++++---------- core/EventManager.h | 5 +++-- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/core/EventManager.cpp b/core/EventManager.cpp index 082fe522..eba1a86a 100644 --- a/core/EventManager.cpp +++ b/core/EventManager.cpp @@ -25,7 +25,7 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell}; typedef List EventHookList; -EventManager::EventManager() : m_EventType(0), m_NotifyPlugins(true), m_EventCopy(NULL) +EventManager::EventManager() : m_EventType(0), m_NotifyPlugins(true) { /* Create an event lookup trie */ m_EventHooks = sm_trie_create(); @@ -322,6 +322,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) { EventHook *pHook; IChangeableForward *pForward; + const char *name; cell_t res = Pl_Continue; if (!m_NotifyPlugins) @@ -330,9 +331,11 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) } /* Get the event name, we're going to need this for passing to post hooks */ - m_EventName = pEvent->GetName(); + name = pEvent->GetName(); - if (sm_trie_retrieve(m_EventHooks, m_EventName, reinterpret_cast(&pHook))) + m_EventNames.push(name); + + if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast(&pHook))) { pForward = pHook->pPreHook; @@ -342,7 +345,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); pForward->PushCell(hndl); - pForward->PushString(m_EventName); + pForward->PushString(name); pForward->PushCell(bDontBroadcast); pForward->Execute(&res, NULL); @@ -352,7 +355,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) if (pHook->postCopy) { - m_EventCopy = gameevents->DuplicateEvent(pEvent); + pHook->pEventCopy = gameevents->DuplicateEvent(pEvent); } if (res) @@ -368,8 +371,10 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) /* IGameEventManager2::FireEvent post hook */ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) { + IGameEvent *pEventCopy; EventHook *pHook; IChangeableForward *pForward; + const char *name; Handle_t hndl = 0; if (!m_NotifyPlugins) @@ -380,7 +385,9 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) RETURN_META_VALUE(MRES_IGNORED, true); } - if (sm_trie_retrieve(m_EventHooks, m_EventName, reinterpret_cast(&pHook))) + name = m_EventNames.front(); + + if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast(&pHook))) { pForward = pHook->pPostHook; @@ -388,14 +395,17 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) { if (pHook->postCopy) { - EventInfo info = {m_EventCopy, false}; + pEventCopy = pHook->pEventCopy; + + EventInfo info = {pEventCopy, false}; hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); + pForward->PushCell(hndl); } else { pForward->PushCell(BAD_HANDLE); } - pForward->PushString(m_EventName); + pForward->PushString(name); pForward->PushCell(bDontBroadcast); pForward->Execute(NULL); @@ -406,11 +416,13 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) g_HandleSys.FreeHandle(hndl, &sec); /* Free event structure */ - gameevents->FreeEvent(m_EventCopy); - m_EventCopy = NULL; + gameevents->FreeEvent(pEventCopy); + pHook->pEventCopy = NULL; } } } + m_EventNames.pop(); + RETURN_META_VALUE(MRES_IGNORED, true); } diff --git a/core/EventManager.h b/core/EventManager.h index 588b87ed..deb8c5ec 100644 --- a/core/EventManager.h +++ b/core/EventManager.h @@ -42,11 +42,13 @@ struct EventHook pPreHook = NULL; pPostHook = NULL; postCopy = false; + pEventCopy = NULL; refCount = 0; } IChangeableForward *pPreHook; IChangeableForward *pPostHook; bool postCopy; + IGameEvent *pEventCopy; unsigned int refCount; }; @@ -102,10 +104,9 @@ private: // IGameEventManager2 hooks private: HandleType_t m_EventType; bool m_NotifyPlugins; - const char *m_EventName; - IGameEvent *m_EventCopy; Trie *m_EventHooks; CStack m_FreeEvents; + CStack m_EventNames; }; extern EventManager g_EventManager;