aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-01-15 13:30:17 +0100
committerShauren <shauren.trinity@gmail.com>2023-01-15 13:30:17 +0100
commitbadb55bfd97c16fecfb8cd73ba99e39ecb6b622d (patch)
tree63c169c36a9db899cb7c9a58d0235ee518112d9b /src
parent7587cff0dcb319f92cba4e3f2c1227b1b1276b64 (diff)
Core/Spells: Added additional validation to loading spell_linked_spell to prevent infinite loops
Closes #28753
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp8
-rw-r--r--src/server/game/Spells/Spell.cpp4
-rw-r--r--src/server/game/Spells/SpellMgr.cpp37
-rw-r--r--src/server/game/Spells/SpellMgr.h12
4 files changed, 39 insertions, 22 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 4343cc239c8..8fd19d2804a 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1357,7 +1357,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
// apply linked auras
if (apply)
{
- if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA))
+ if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
{
for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
{
@@ -1371,7 +1371,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
else
{
// remove linked auras
- if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(-(int32)GetId()))
+ if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_REMOVE, GetId()))
{
for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
{
@@ -1383,7 +1383,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
.SetOriginalCastId(GetCastId()));
}
}
- if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA))
+ if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
{
for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
{
@@ -1398,7 +1398,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
else if (apply)
{
// modify stack amount of linked auras
- if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA))
+ if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
{
for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
if (*itr > 0)
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index d463e785f55..a894a3037e9 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3205,7 +3205,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit)
// trigger linked auras remove/apply
/// @todo remove/cleanup this, as this table is not documented and people are doing stupid things with it
- if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id + SPELL_LINK_HIT))
+ if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_HIT, m_spellInfo->Id))
{
for (std::vector<int32>::const_iterator i = spellTriggered->begin(); i != spellTriggered->end(); ++i)
{
@@ -3746,7 +3746,7 @@ void Spell::_cast(bool skipCheck)
CallScriptAfterCastHandlers();
- if (std::vector<int32> const* spell_triggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id))
+ if (std::vector<int32> const* spell_triggered = sSpellMgr->GetSpellLinked(SPELL_LINK_CAST, m_spellInfo->Id))
{
for (int32 id : *spell_triggered)
{
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 3ead1a0196a..0b837a966f1 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -625,9 +625,9 @@ bool SpellMgr::IsArenaAllowedEnchancment(uint32 ench_id) const
return false;
}
-std::vector<int32> const* SpellMgr::GetSpellLinked(int32 spell_id) const
+std::vector<int32> const* SpellMgr::GetSpellLinked(SpellLinkedType type, uint32 spell_id) const
{
- return Trinity::Containers::MapGetValuePtr(mSpellLinkedMap, spell_id);
+ return Trinity::Containers::MapGetValuePtr(mSpellLinkedMap, { type, spell_id });
}
PetLevelupSpellSet const* SpellMgr::GetPetLevelupSpellList(uint32 petFamily) const
@@ -2047,7 +2047,7 @@ void SpellMgr::LoadSpellLinked()
int32 trigger = fields[0].GetInt32();
int32 effect = fields[1].GetInt32();
- int32 type = fields[2].GetUInt8();
+ SpellLinkedType type = SpellLinkedType(fields[2].GetUInt8());
SpellInfo const* spellInfo = GetSpellInfo(abs(trigger), DIFFICULTY_NONE);
if (!spellInfo)
@@ -2057,11 +2057,13 @@ void SpellMgr::LoadSpellLinked()
}
if (effect >= 0)
+ {
for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
{
if (spellEffectInfo.CalcValue() == abs(effect))
TC_LOG_ERROR("sql.sql", "The spell {} Effect: {} listed in `spell_linked_spell` has same bp{} like effect (possible hack).", abs(trigger), abs(effect), uint32(spellEffectInfo.EffectIndex));
}
+ }
spellInfo = GetSpellInfo(abs(effect), DIFFICULTY_NONE);
if (!spellInfo)
@@ -2070,14 +2072,31 @@ void SpellMgr::LoadSpellLinked()
continue;
}
- if (type) //we will find a better way when more types are needed
+ if (type < SPELL_LINK_CAST || type > SPELL_LINK_REMOVE)
{
- if (trigger > 0)
- trigger += SPELL_LINKED_MAX_SPELLS * type;
- else
- trigger -= SPELL_LINKED_MAX_SPELLS * type;
+ TC_LOG_ERROR("sql.sql", "The spell trigger {}, effect {} listed in `spell_linked_spell` has invalid link type {}, skipped.", trigger, effect, type);
+ continue;
+ }
+
+ if (trigger < 0)
+ {
+ if (type != SPELL_LINK_CAST)
+ TC_LOG_ERROR("sql.sql", "The spell trigger {} listed in `spell_linked_spell` has invalid link type {}, changed to 0.", trigger, type);
+
+ trigger = -trigger;
+ type = SPELL_LINK_REMOVE;
}
- mSpellLinkedMap[trigger].push_back(effect);
+
+ if (type != SPELL_LINK_AURA)
+ {
+ if (trigger == effect)
+ {
+ TC_LOG_ERROR("sql.sql", "The spell trigger {}, effect {} listed in `spell_linked_spell` triggers itself (infinite loop), skipped.", trigger, effect);
+ continue;
+ }
+ }
+
+ mSpellLinkedMap[{ type, trigger }].push_back(effect);
++count;
} while (result->NextRow());
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 7be029d92f3..314436d4a44 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -118,14 +118,12 @@ enum SpellFamilyFlag
SPELLFAMILYFLAG_SHAMAN_TOTEM_EFFECTS = 0x04000000 // Seems to be linked to most totems and some totem effects
};
-#define SPELL_LINKED_MAX_SPELLS 200000
-
enum SpellLinkedType
{
SPELL_LINK_CAST = 0, // +: cast; -: remove
- SPELL_LINK_HIT = 1 * 200000,
- SPELL_LINK_AURA = 2 * 200000, // +: aura; -: immune
- SPELL_LINK_REMOVE = 0
+ SPELL_LINK_HIT = 1,
+ SPELL_LINK_AURA = 2, // +: aura; -: immune
+ SPELL_LINK_REMOVE = 3
};
// Spell proc event related declarations (accessed using SpellMgr functions)
@@ -617,7 +615,7 @@ struct PetDefaultSpellsEntry
// < 0 for petspelldata id, > 0 for creature_id
typedef std::map<int32, PetDefaultSpellsEntry> PetDefaultSpellsMap;
-typedef std::unordered_map<int32, std::vector<int32>> SpellLinkedMap;
+typedef std::unordered_map<std::pair<SpellLinkedType, uint32>, std::vector<int32>> SpellLinkedMap;
bool IsPrimaryProfessionSkill(uint32 skill);
@@ -733,7 +731,7 @@ class TC_GAME_API SpellMgr
SpellEnchantProcEntry const* GetSpellEnchantProcEvent(uint32 enchId) const;
bool IsArenaAllowedEnchancment(uint32 ench_id) const;
- std::vector<int32> const* GetSpellLinked(int32 spell_id) const;
+ std::vector<int32> const* GetSpellLinked(SpellLinkedType type, uint32 spell_id) const;
PetLevelupSpellSet const* GetPetLevelupSpellList(uint32 petFamily) const;
PetDefaultSpellsEntry const* GetPetDefaultSpellsEntry(int32 id) const;