Transcription ArgusCore lot 1 : 8 fixes anti-crash + anti-exploit

Anti-crash (adaptes a nos APIs) :
- Spell: assert dur sur cible destination -> log+skip (a00b85b2)
- SpellAuraEffects: DoT weapon-percent, caster nul -> tick a 0 (b456b7f7)
- Battleground: PlayerScores.find sans garde -> continue si absent (e875f9f4)
- VehicleHandler: 4x siege nul deref -> return (392466b1)
- LootHandler: division par zero si liste vide -> return (e8196eed)
Anti-exploit :
- PetHandler: index action bar hors bornes (OOB write) + abandon reserve au proprietaire (fec060ab)
- Guild: onglet de banque reserve au chef (2288f107) ; attribution de rang ne peut viser/donner un rang >= au sien (f94d82dc)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-07-26 16:21:27 +00:00
parent 1f1daf20cd
commit 6ab4abafef
7 changed files with 44 additions and 4 deletions
@@ -860,9 +860,11 @@ void Battleground::EndBattleground(uint32 winner)
if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER);
BattlegroundScoreMap::const_iterator score = PlayerScores.find(player->GetGUID());
if (score == PlayerScores.end()) // pas de score enregistre pour ce joueur (ArgusCore e875f9f4)
continue;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER);
stmt->setUInt32(0, battlegroundId);
stmt->setUInt64(1, player->GetGUID().GetCounter());
stmt->setBool (2, team == winner);
+19
View File
@@ -1573,6 +1573,14 @@ void Guild::HandleSetNewGuildMaster(WorldSession* session, std::string const& na
void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon)
{
// seul le maitre de guilde peut renommer/re-iconer un onglet (comme l achat d onglet) (ArgusCore 2288f107)
if (GetLeaderGUID() != session->GetPlayer()->GetGUID())
{
TC_LOG_ERROR("guild", "Guild::HandleSetBankTabInfo: Joueur %s sans droits de chef a tente de modifier l onglet %u.",
session->GetPlayerInfo().c_str(), tabId);
return;
}
BankTab* tab = GetBankTab(tabId);
if (!tab)
{
@@ -1934,6 +1942,17 @@ void Guild::HandleSetMemberRank(WorldSession* session, ObjectGuid targetGuid, Ob
return;
}
// avoir PROMOTE/DEMOTE ne permet pas d agir sur un membre de rang egal/superieur, ni d attribuer un rang egal/superieur au sien (ArgusCore f94d82dc)
if (Member const* memberMe = GetMember(player->GetGUID()))
{
uint32 myRankId = memberMe->GetRankId();
if (member->GetRankId() <= myRankId || rank <= myRankId)
{
SendCommandResult(session, type, ERR_GUILD_RANK_TOO_HIGH_S);
return;
}
}
// Player cannot promote himself
if (member->IsSamePlayer(player->GetGUID()))
{
+2
View File
@@ -222,6 +222,8 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
playersNear.push_back(member);
}
if (playersNear.empty()) // division par zero si personne a portee (ArgusCore e8196eed)
return;
uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size()));
for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i)
+4 -1
View File
@@ -476,6 +476,9 @@ void WorldSession::HandlePetSetAction(WorldPackets::Pet::PetSetAction& packet)
}
uint32 position = packet.Index;
// position vient du client (CMSG_PET_SET_ACTION) ; PetActionBar est un tableau fixe -> ecriture hors bornes (ArgusCore fec060ab)
if (position >= MAX_UNIT_ACTION_BAR_INDEX)
return;
uint32 actionData = packet.Action;
uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(actionData);
@@ -596,7 +599,7 @@ void WorldSession::HandlePetAbandon(WorldPackets::Pet::PetAbandon& packet)
// pet/charmed
Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, packet.Pet);
if (pet && pet->ToPet() && pet->ToPet()->getPetType() == HUNTER_PET)
if (pet && pet->ToPet() && pet->ToPet()->getPetType() == HUNTER_PET && pet->GetOwnerGUID() == _player->GetGUID()) // proprietaire uniquement (ArgusCore fec060ab)
{
_player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED);
}
@@ -42,6 +42,8 @@ void WorldSession::HandleRequestVehiclePrevSeat(WorldPackets::Vehicle::RequestVe
return;
VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer());
if (!seat) // le joueur peut ne pas avoir de siege resolu (ArgusCore 392466b1)
return;
if (!seat->CanSwitchFromSeat())
{
TC_LOG_ERROR("network", "HandleRequestVehiclePrevSeat: %s tried to switch seats but current seatflags %u don't permit that.",
@@ -59,6 +61,8 @@ void WorldSession::HandleRequestVehicleNextSeat(WorldPackets::Vehicle::RequestVe
return;
VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer());
if (!seat) // le joueur peut ne pas avoir de siege resolu (ArgusCore 392466b1)
return;
if (!seat->CanSwitchFromSeat())
{
TC_LOG_ERROR("network", "HandleRequestVehicleNextSeat: %s tried to switch seats but current seatflags %u don't permit that.",
@@ -76,6 +80,8 @@ void WorldSession::HandleMoveChangeVehicleSeats(WorldPackets::Vehicle::MoveChang
return;
VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer());
if (!seat) // le joueur peut ne pas avoir de siege resolu (ArgusCore 392466b1)
return;
if (!seat->CanSwitchFromSeat())
{
TC_LOG_ERROR("network", "HandleMoveChangeVehicleSeats: %s tried to switch seats but current seatflags %u don't permit that.",
@@ -105,6 +111,8 @@ void WorldSession::HandleRequestVehicleSwitchSeat(WorldPackets::Vehicle::Request
return;
VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer());
if (!seat) // le joueur peut ne pas avoir de siege resolu (ArgusCore 392466b1)
return;
if (!seat->CanSwitchFromSeat())
{
TC_LOG_ERROR("network", "HandleRequestVehicleSwitchSeat: %s tried to switch seats but current seatflags %u don't permit that.",
@@ -5838,7 +5838,8 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
{
WeaponAttackType attackType = GetSpellInfo()->GetAttackType();
int32 weaponDamage = CalculatePct(caster->CalculateDamage(attackType, false, true), GetAmount());
// le degat d arme exige un caster vivant ; s il a quitte la map, ce tick ne fait rien au lieu de crasher (ArgusCore b456b7f7)
int32 weaponDamage = caster ? CalculatePct(caster->CalculateDamage(attackType, false, true), GetAmount()) : 0;
// Add melee damage bonuses (also check for negative)
uint32 damageBonusDone = caster->MeleeDamageBonusDone(target, std::max(weaponDamage, 0), attackType, GetSpellInfo());
+6 -1
View File
@@ -1533,7 +1533,12 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
ASSERT(m_targets.GetObjectTarget() && "Spell::SelectImplicitTargetDestTargets - no explicit object target available!");
// Un ligne spell_effect mal formee ne doit pas crasher le serveur : on log et on saute (ArgusCore a00b85b2)
if (!m_targets.GetObjectTarget())
{
TC_LOG_ERROR("spells", "Spell::SelectImplicitTargetDestTargets: spell %u effect %u sans cible objet explicite; selection de destination ignoree.", m_spellInfo->Id, uint32(effIndex));
return;
}
WorldObject* target = m_targets.GetObjectTarget();
SpellDestination dest(*target);