From 4dff5bd09b73c0a02cf8a95f9e4f528e74a5ef50 Mon Sep 17 00:00:00 2001 From: Giacomo Pozzoni Date: Fri, 4 Sep 2020 21:25:58 +0200 Subject: Core/SAI: Reduce the chance of infinite loops/stack overflows (#25398) Fixes #24092 (cherry picked from commit a58aeb41f466fd916cdc12e805f7a8130c8ccdf5) --- src/server/game/AI/SmartScripts/SmartScript.cpp | 27 ++++++++++++++++++------- src/server/game/AI/SmartScripts/SmartScript.h | 4 ++++ 2 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src') 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; -- cgit v1.2.3