Core/Spells: Added additional validation to loading spell_linked_spell to prevent infinite loops

Port From (https://github.com/TrinityCore/TrinityCore/commit/badb55bfd97c16fecfb8cd73ba99e39ecb6b622d)
This commit is contained in:
hondacrx
2023-01-23 00:24:27 -05:00
parent 4b86a00d6e
commit 8921432333
4 changed files with 38 additions and 20 deletions
@@ -39,10 +39,10 @@ namespace Framework.Constants
public enum SpellLinkedType
{
Cast = 0, // +: cast; -: remove
Hit = 1 * 200000,
Aura = 2 * 200000, // +: aura; -: immune
Remove = 0
Cast = 0, // +: cast; -: remove
Hit = 1,
Aura = 2, // +: aura; -: immune
Remove = 3
}
//Spell targets used by SelectSpell
+4 -4
View File
@@ -1238,7 +1238,7 @@ namespace Game.Spells
// apply linked auras
if (apply)
{
var spellTriggered = Global.SpellMgr.GetSpellLinked((int)GetId() + (int)SpellLinkedType.Aura);
var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Aura, GetId());
if (spellTriggered != null)
{
foreach (var spell in spellTriggered)
@@ -1253,7 +1253,7 @@ namespace Game.Spells
else
{
// remove linked auras
var spellTriggered = Global.SpellMgr.GetSpellLinked(-(int)GetId());
var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Remove, GetId());
if (spellTriggered != null)
{
foreach (var spell in spellTriggered)
@@ -1266,7 +1266,7 @@ namespace Game.Spells
.SetOriginalCastId(GetCastId()));
}
}
spellTriggered = Global.SpellMgr.GetSpellLinked((int)GetId() + (int)SpellLinkedType.Aura);
spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Aura, GetId());
if (spellTriggered != null)
{
foreach (var id in spellTriggered)
@@ -1282,7 +1282,7 @@ namespace Game.Spells
else if (apply)
{
// modify stack amount of linked auras
var spellTriggered = Global.SpellMgr.GetSpellLinked((int)GetId() + (int)SpellLinkedType.Aura);
var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Aura, GetId());
if (spellTriggered != null)
{
foreach (var id in spellTriggered)
+2 -2
View File
@@ -2312,7 +2312,7 @@ namespace Game.Spells
// trigger linked auras remove/apply
// @todo remove/cleanup this, as this table is not documented and people are doing stupid things with it
var spellTriggered = Global.SpellMgr.GetSpellLinked((int)m_spellInfo.Id + (int)SpellLinkedType.Hit);
var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Hit, m_spellInfo.Id);
if (spellTriggered != null)
{
foreach (var id in spellTriggered)
@@ -2894,7 +2894,7 @@ namespace Game.Spells
CallScriptAfterCastHandlers();
var spell_triggered = Global.SpellMgr.GetSpellLinked((int)m_spellInfo.Id);
var spell_triggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Cast, m_spellInfo.Id);
if (spell_triggered != null)
{
foreach (var spellId in spell_triggered)
+28 -10
View File
@@ -562,9 +562,9 @@ namespace Game.Entities
return false;
}
public List<int> GetSpellLinked(int spell_id)
public List<int> GetSpellLinked(SpellLinkedType type, uint spellId)
{
return mSpellLinkedMap.LookupByKey(spell_id);
return mSpellLinkedMap.LookupByKey((type, spellId));
}
public MultiMap<uint, uint> GetPetLevelupSpellList(CreatureFamily petFamily)
@@ -1730,7 +1730,7 @@ namespace Game.Entities
{
int trigger = result.Read<int>(0);
int effect = result.Read<int>(1);
int type = result.Read<int>(2);
SpellLinkedType type = (SpellLinkedType)result.Read<byte>(2);
SpellInfo spellInfo = GetSpellInfo((uint)Math.Abs(trigger), Difficulty.None);
if (spellInfo == null)
@@ -1754,14 +1754,32 @@ namespace Game.Entities
continue;
}
if (type != 0) //we will find a better way when more types are needed
if (type < SpellLinkedType.Cast || type > SpellLinkedType.Remove)
{
if (trigger > 0)
trigger += 200000 * type;
else
trigger -= 200000 * type;
Log.outError(LogFilter.Sql, $"The spell trigger {trigger}, effect {effect} listed in `spell_linked_spell` has invalid link type {type}, skipped.");
continue;
}
mSpellLinkedMap.Add(trigger, effect);
if (trigger < 0)
{
if (type != SpellLinkedType.Cast)
Log.outError(LogFilter.Sql, $"The spell trigger {trigger} listed in `spell_linked_spell` has invalid link type {type}, changed to 0.");
trigger = -trigger;
type = SpellLinkedType.Remove;
}
if (type != SpellLinkedType.Aura)
{
if (trigger == effect)
{
Log.outError(LogFilter.Sql, $"The spell trigger {trigger}, effect {effect} listed in `spell_linked_spell` triggers itself (infinite loop), skipped.");
continue;
}
}
mSpellLinkedMap.Add((type, (uint)trigger), effect);
++count;
} while (result.NextRow());
@@ -4729,7 +4747,7 @@ namespace Game.Entities
Dictionary<(uint id, Difficulty difficulty), SpellProcEntry> mSpellProcMap = new();
Dictionary<uint, SpellThreatEntry> mSpellThreatMap = new();
Dictionary<uint, PetAura> mSpellPetAuraMap = new();
MultiMap<int, int> mSpellLinkedMap = new();
MultiMap<(SpellLinkedType, uint), int> mSpellLinkedMap = new();
Dictionary<uint, SpellEnchantProcEntry> mSpellEnchantProcEventMap = new();
MultiMap<uint, SpellArea> mSpellAreaMap = new();
MultiMap<uint, SpellArea> mSpellAreaForQuestMap = new();