From 147916ce2e94ea8a04927213c2f25ae33d41675b Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 19 Jul 2020 02:34:59 -0400 Subject: [PATCH] Set group info to null in various places When the group is disbanded, set the leader to null. When setting a new raid leader, make sure we have a new raid leader. If we don't, avoid a crash and disband the raid. It's better than zones falling apart, and will resolve itself on the next VerifyRaid call. If a member zones, set the leader pointer to nullptr. This fixes an issue where the leader pointer is freed later (MemberZoned normally cleans up the Client object), but referenced by other entities, allowing the leader to be used in the same server process tick, post-cleanup - as the leader won't exist. --- zone/groups.cpp | 4 ++++ zone/raids.cpp | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/zone/groups.cpp b/zone/groups.cpp index 5734d4672..60a58b99c 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -498,6 +498,9 @@ void Group::SendEndurancePacketFrom(Mob* member) //if the group was in the zone already bool Group::UpdatePlayer(Mob* update){ + if (!update) + return false; + bool updateSuccess = false; VerifyGroup(); @@ -1009,6 +1012,7 @@ void Group::DisbandGroup(bool joinraid) { Leader->UpdateLFP(); } + SetLeader(nullptr); safe_delete(outapp); } diff --git a/zone/raids.cpp b/zone/raids.cpp index 2dc892a9a..51c52d8d4 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -279,6 +279,8 @@ void Raid::SetRaidLeader(const char *wasLead, const char *name) Client *c = entity_list.GetClientByName(name); if(c) SetLeader(c); + else + SetLeader(nullptr); //sanity check, should never get hit but we want to prefer to NOT crash if we do VerifyRaid and leader never gets set there (raid without a leader?) LearnMembers(); VerifyRaid(); @@ -1549,6 +1551,11 @@ void Raid::VerifyRaid() SetLeader(members[x].member); strn0cpy(leadername, members[x].membername, 64); } + else + { + //should never happen, but maybe it is? + SetLeader(nullptr); + } } } } @@ -1558,6 +1565,11 @@ void Raid::MemberZoned(Client *c) if(!c) return; + if (leader == c) + { + leader = nullptr; + } + // Raid::GetGroup() goes over the members as well, this way we go over once uint32 gid = RAID_GROUPLESS; for(int x = 0; x < MAX_RAID_MEMBERS; x++)