aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiacomo Pozzoni <giacomopoz@gmail.com>2020-09-04 21:25:58 +0200
committerShauren <shauren.trinity@gmail.com>2022-02-05 11:51:54 +0100
commit4dff5bd09b73c0a02cf8a95f9e4f528e74a5ef50 (patch)
tree5063ff27137b6687f7a42f0724484be3cd36939d
parent1a86bab4d870996334400b31b207c122c35bcc32 (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.cpp27
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h4
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;