diff options
author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-09-04 21:25:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-04 21:25:58 +0200 |
commit | a58aeb41f466fd916cdc12e805f7a8130c8ccdf5 (patch) | |
tree | 55fbf50e8a793aa5f0e1c52d28a0cb5bd28fb3dc | |
parent | a02d36f18c5846fc4306cb602851744cb352fc57 (diff) |
Core/SAI: Reduce the chance of infinite loops/stack overflows (#25398)
Fixes #24092
-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 ef84c706c64..014e388c191 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -59,6 +59,7 @@ SmartScript::SmartScript() isProcessingTimedActionList = false; mCurrentPriority = 0; mEventSortingRequired = false; + mNestedEventsCounter = 0; } SmartScript::~SmartScript() @@ -219,16 +220,28 @@ void SmartScript::ResetBaseObject() void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) { - 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); + if (eventType == e) + if (sConditionMgr->IsObjectMeetingSmartEventConditions(event.entryOrGuid, event.event_id, event.source_type, unit, GetBaseObject())) + ProcessEvent(event, unit, var0, var1, bvar, spell, gob); + } } + + --mNestedEventsCounter; } void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index caa86f3ef0b..e028acbec1b 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -128,6 +128,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; |