diff options
| author | Shauren <shauren.trinity@gmail.com> | 2023-06-29 11:39:02 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2023-06-29 11:39:02 +0200 |
| commit | 29eac37a16df2ec14cba89f4d6e28f54ca1a4e25 (patch) | |
| tree | 0e340300bd3e1e0aaf8ff27324434b59f6a3e2d2 /src/server/game/Entities | |
| parent | bacfbec25180cd0a02fec20e788d74e2fcaf1a0c (diff) | |
Core/Spells: Fully prevent infinite proc loops and add logging to detect most spells that could possibly trigger this behavior at startup
Closes #28865
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 14 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 4 |
2 files changed, 16 insertions, 2 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index cd97d0d4081..46b0f9bc681 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -303,7 +303,7 @@ SpellNonMeleeDamage::SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellIn Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject), m_lastSanctuaryTime(0), LastCharmerGUID(), movespline(new Movement::MoveSpline()), - m_ControlledByPlayer(false), m_procDeep(0), m_transformSpell(0), + m_ControlledByPlayer(false), m_procDeep(0), m_procChainLength(0), m_transformSpell(0), m_removedAurasCount(0), m_interruptMask(SpellAuraInterruptFlags::None), m_interruptMask2(SpellAuraInterruptFlags2::None), m_unitMovedByMe(nullptr), m_playerMovingMe(nullptr), m_charmer(nullptr), m_charmed(nullptr), i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_vehicle(nullptr), @@ -5320,6 +5320,13 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage const* log) ProcFlagsSpellType spellTypeMask, ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo) { + static constexpr int32 ProcChainHardLimit = 10; + if (spell && spell->GetProcChainLength() >= ProcChainHardLimit) + { + TC_LOG_ERROR("spells.aura.effect", "Unit::ProcSkillsAndAuras: Possible infinite proc loop detected, current triggering spell {}", spell->GetDebugInfo().c_str()); + return; + } + WeaponAttackType attType = damageInfo ? damageInfo->GetAttackType() : BASE_ATTACK; if (typeMaskActor && actor) actor->ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType); @@ -10020,6 +10027,9 @@ void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProc { Spell const* triggeringSpell = eventInfo.GetProcSpell(); bool const disableProcs = triggeringSpell && triggeringSpell->IsProcDisabled(); + + int32 oldProcChainLength = std::exchange(m_procChainLength, std::max(m_procChainLength + 1, triggeringSpell ? triggeringSpell->GetProcChainLength() : 0)); + if (disableProcs) SetCantProc(true); @@ -10033,6 +10043,8 @@ void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProc if (disableProcs) SetCantProc(false); + + m_procChainLength = oldProcChainLength; } ///----------Pet responses methods----------------- diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e01d32067e5..0f63cc369a9 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1803,6 +1803,7 @@ class TC_GAME_API Unit : public WorldObject // proc trigger system bool CanProc() const { return !m_procDeep; } void SetCantProc(bool apply); + int32 GetProcChainLength() const { return m_procChainLength; } uint32 GetModelForForm(ShapeshiftForm form, uint32 spellId) const; @@ -1950,7 +1951,8 @@ class TC_GAME_API Unit : public WorldObject DeathState m_deathState; - int32 m_procDeep; + int32 m_procDeep; // tracked for proc system correctness (what spells should proc what) + int32 m_procChainLength; // tracked to protect against infinite proc loops (hard limit, will disallow procs even if they should happen) typedef std::list<DynamicObject*> DynObjectList; DynObjectList m_dynObj; |
