From e0a2622138e519c66e375540bd205cd1c4078551 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Fri, 14 Mar 2025 10:41:04 +0100 Subject: [PATCH] fix(Core/Calendar): Fix crash on deletion while iterating through calendar events. (#21667) --- src/server/game/Calendar/CalendarMgr.cpp | 64 ++++++++++++++++-------- src/server/game/Calendar/CalendarMgr.h | 6 +-- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index 12cdf0ae4..014d99056 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -154,25 +154,26 @@ void CalendarMgr::AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite } } -void CalendarMgr::RemoveEvent(uint64 eventId, ObjectGuid remover) +CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, ObjectGuid remover) { - CalendarEvent* calendarEvent = GetEvent(eventId); + CalendarEventStore::iterator current; + CalendarEvent* calendarEvent = GetEvent(eventId, ¤t); if (!calendarEvent) { SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID); - return; + return _events.end(); } - RemoveEvent(calendarEvent, remover); + CalendarEventStore::const_iterator constItr(current); + return RemoveEvent(calendarEvent, remover, &constItr); } -void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover) -{ +CalendarEventStore::iterator CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover, CalendarEventStore::const_iterator* currIt) { if (!calendarEvent) { SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID); - return; + return _events.end(); } SendCalendarEventRemovedAlert(*calendarEvent); @@ -204,9 +205,20 @@ void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover) trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); - _events.erase(calendarEvent); + if (currIt) + { + delete calendarEvent; + return _events.erase(*currIt); + } + + if (auto it = _events.find(calendarEvent); it != _events.end()) + { + delete calendarEvent; + return _events.erase(it); + } + delete calendarEvent; - return; + return _events.end(); } void CalendarMgr::RemoveInvite(uint64 inviteId, uint64 eventId, ObjectGuid /*remover*/) @@ -277,13 +289,12 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(ObjectGuid guid) { for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) { - CalendarEvent* event = *itr; - ++itr; - if (event->GetCreatorGUID() == guid) + if (CalendarEvent* event = *itr; event->GetCreatorGUID() == guid) { - RemoveEvent(event, ObjectGuid::Empty); + itr = RemoveEvent(event, ObjectGuid::Empty, &itr); continue; } + ++itr; } CalendarInviteStore playerInvites = GetPlayerInvites(guid); @@ -293,22 +304,33 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(ObjectGuid guid) void CalendarMgr::RemovePlayerGuildEventsAndSignups(ObjectGuid guid, uint32 guildId) { - for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) + for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) + { if ((*itr)->GetCreatorGUID() == guid && ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement())) - RemoveEvent((*itr)->GetEventId(), guid); + { + itr = RemoveEvent((*itr)->GetEventId(), guid); + continue; + } + ++itr; + } CalendarInviteStore playerInvites = GetPlayerInvites(guid); for (CalendarInviteStore::const_iterator itr = playerInvites.begin(); itr != playerInvites.end(); ++itr) - if (CalendarEvent* calendarEvent = GetEvent((*itr)->GetEventId())) + if (CalendarEvent* calendarEvent = GetEvent((*itr)->GetEventId(), nullptr)) if (calendarEvent->IsGuildEvent() && calendarEvent->GetGuildId() == guildId) RemoveInvite((*itr)->GetInviteId(), (*itr)->GetEventId(), guid); } -CalendarEvent* CalendarMgr::GetEvent(uint64 eventId) +CalendarEvent* CalendarMgr::GetEvent(uint64 eventId, CalendarEventStore::iterator* it) { for (CalendarEventStore::iterator itr = _events.begin(); itr != _events.end(); ++itr) if ((*itr)->GetEventId() == eventId) + { + if (it) + *it = itr; + return *itr; + } return nullptr; } @@ -366,10 +388,12 @@ void CalendarMgr::DeleteOldEvents() for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) { - CalendarEvent* event = *itr; + if (CalendarEvent* event = *itr; event->GetEventTime() < oldEventsTime) + { + itr = RemoveEvent(event, ObjectGuid::Empty, &itr); + continue; + } ++itr; - if (event->GetEventTime() < oldEventsTime) - RemoveEvent(event, ObjectGuid::Empty); } } diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h index c92661be3..79ea79712 100644 --- a/src/server/game/Calendar/CalendarMgr.h +++ b/src/server/game/Calendar/CalendarMgr.h @@ -293,7 +293,7 @@ public: void LoadFromDB(); - CalendarEvent* GetEvent(uint64 eventId); + CalendarEvent* GetEvent(uint64 eventId, CalendarEventStore::iterator* it = nullptr); CalendarEventStore const& GetEvents() const { return _events; } CalendarEventStore GetEventsCreatedBy(ObjectGuid guid, bool includeGuildEvents = false); CalendarEventStore GetPlayerEvents(ObjectGuid guid); @@ -314,8 +314,8 @@ public: uint32 GetPlayerNumPending(ObjectGuid guid); void AddEvent(CalendarEvent* calendarEvent, CalendarSendEventType sendType); - void RemoveEvent(uint64 eventId, ObjectGuid remover); - void RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover); + CalendarEventStore::iterator RemoveEvent(uint64 eventId, ObjectGuid remover); + CalendarEventStore::iterator RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover, CalendarEventStore::const_iterator* currIt = nullptr); void UpdateEvent(CalendarEvent* calendarEvent); void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite, CharacterDatabaseTransaction trans = nullptr);