diff options
author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-09-04 21:25:58 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-02-05 11:51:54 +0100 |
commit | 4dff5bd09b73c0a02cf8a95f9e4f528e74a5ef50 (patch) | |
tree | 5063ff27137b6687f7a42f0724484be3cd36939d | |
parent | 1a86bab4d870996334400b31b207c122c35bcc32 (diff) |
Core/SAI: Reduce the chance of infinite loops/stack overflows (#25398)
Fixes #24092
(cherry picked from commit a58aeb41f466fd916cdc12e805f7a8130c8ccdf5)
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 27 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 4 |
2 files changed, 24 insertions, 7 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 37b5a737cd4..b17a06cab2b 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -63,6 +63,7 @@ SmartScript::SmartScript() isProcessingTimedActionList = false; mCurrentPriority = 0; mEventSortingRequired = false; + mNestedEventsCounter = 0; } SmartScript::~SmartScript() @@ -233,16 +234,28 @@ void SmartScript::ResetBaseObject() void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob, std::string const& varString) { - for (SmartScriptHolder& event : mEvents) + mNestedEventsCounter++; + + // Allow only a fixed number of nested ProcessEventsFor calls + if (mNestedEventsCounter > MAX_NESTED_EVENTS) { - SMART_EVENT eventType = SMART_EVENT(event.GetEventType()); - if (eventType == SMART_EVENT_LINK)//special handling - continue; + TC_LOG_WARN("scripts.ai", "SmartScript::ProcessEventsFor: reached the limit of max allowed nested ProcessEventsFor() calls with event %u, skipping!\n%s", e, GetBaseObject()->GetDebugInfo().c_str()); + } + else + { + for (SmartScriptHolder& event : mEvents) + { + SMART_EVENT eventType = SMART_EVENT(event.GetEventType()); + if (eventType == SMART_EVENT_LINK)//special handling + continue; - if (eventType == e) - if (sConditionMgr->IsObjectMeetingSmartEventConditions(event.entryOrGuid, event.event_id, event.source_type, unit, GetBaseObject())) - ProcessEvent(event, unit, var0, var1, bvar, spell, gob, varString); + if (eventType == e) + if (sConditionMgr->IsObjectMeetingSmartEventConditions(event.entryOrGuid, event.event_id, event.source_type, unit, GetBaseObject())) + ProcessEvent(event, unit, var0, var1, bvar, spell, gob, varString); + } } + + --mNestedEventsCounter; } void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob, std::string const& varString) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 5376e251d6a..c3167ac65d1 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -136,6 +136,10 @@ class TC_GAME_API SmartScript bool mUseTextTimer; uint32 mCurrentPriority; bool mEventSortingRequired; + uint32 mNestedEventsCounter; + + // Max number of nested ProcessEventsFor() calls to avoid infinite loops + static constexpr uint32 MAX_NESTED_EVENTS = 10; ObjectVectorMap _storedTargets; |