From ac388f2a1a1d50790d5432f77c2c6121403e759f Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 28 Apr 2022 10:11:23 -0400 Subject: [PATCH] Core/SAI: Reduce the chance of infinite loops/stack overflows Port From (https://github.com/TrinityCore/TrinityCore/commit/4dff5bd09b73c0a02cf8a95f9e4f528e74a5ef50) --- Source/Game/AI/SmartScripts/SmartScript.cs | 32 ++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/Source/Game/AI/SmartScripts/SmartScript.cs b/Source/Game/AI/SmartScripts/SmartScript.cs index 1073b1628..0ee81ddd7 100644 --- a/Source/Game/AI/SmartScripts/SmartScript.cs +++ b/Source/Game/AI/SmartScripts/SmartScript.cs @@ -32,6 +32,9 @@ namespace Game.AI { public class SmartScript { + // Max number of nested ProcessEventsFor() calls to avoid infinite loops + const uint MaxNestedEvents = 10; + public ObjectGuid LastInvoker; Dictionary _counterList = new(); @@ -63,6 +66,7 @@ namespace Game.AI bool _useTextTimer; uint _currentPriority; bool _eventSortingRequired; + uint _nestedEventsCounter; Dictionary _storedTargets = new(); @@ -111,16 +115,28 @@ namespace Game.AI public void ProcessEventsFor(SmartEvents e, Unit unit = null, uint var0 = 0, uint var1 = 0, bool bvar = false, SpellInfo spell = null, GameObject gob = null, string varString = "") { - foreach (var Event in _events) - { - SmartEvents eventType = Event.GetEventType(); - if (eventType == SmartEvents.Link)//special handling - continue; + _nestedEventsCounter++; - if (eventType == e) - if (Global.ConditionMgr.IsObjectMeetingSmartEventConditions(Event.EntryOrGuid, Event.EventId, Event.SourceType, unit, GetBaseObject())) - ProcessEvent(Event, unit, var0, var1, bvar, spell, gob, varString); + // Allow only a fixed number of nested ProcessEventsFor calls + if (_nestedEventsCounter > MaxNestedEvents) + { + Log.outWarn(LogFilter.ScriptsAi, $"SmartScript::ProcessEventsFor: reached the limit of max allowed nested ProcessEventsFor() calls with event {e}, skipping!\n{GetBaseObject().GetDebugInfo()}"); } + else + { + foreach (var Event in _events) + { + SmartEvents eventType = Event.GetEventType(); + if (eventType == SmartEvents.Link)//special handling + continue; + + if (eventType == e) + if (Global.ConditionMgr.IsObjectMeetingSmartEventConditions(Event.EntryOrGuid, Event.EventId, Event.SourceType, unit, GetBaseObject())) + ProcessEvent(Event, unit, var0, var1, bvar, spell, gob, varString); + } + } + + --mNestedEventsCounter; } void ProcessAction(SmartScriptHolder e, Unit unit = null, uint var0 = 0, uint var1 = 0, bool bvar = false, SpellInfo spell = null, GameObject gob = null, string varString = "")