Compare commits

..

2 commits

Author SHA1 Message Date
c2f400a60b Merge pull request 'fix: null-session crash on event start/end broadcast' (#3) from fix/null-session-broadcast-crash into main
Reviewed-on: #3
2026-09-04 07:51:01 -06:00
Claude
fc282fda54 fix: null-session crash when broadcasting event start/end messages
StartEvent() and EndEvent() both used ChatHandler(nullptr).SendWorldText()
to announce Gold Rush events server-wide. ChatHandler::SendWorldText()
(core Chat.cpp) unconditionally calls GetSession()->SendPacket() on the
handler's session -- with a null session, that's an immediate null-pointer
dereference. This crashed the live server twice within ~24 hours
(confirmed via a symbolized gdb backtrace against a captured coredump):

  WorldSession::GetPlayer (this=0x0)
  WorldSession::SendPacket (this=0x0, ...)
  ChatHandler::SendWorldText (...)
  GoldRushManager::StartEvent (...) at GoldRush.cpp:880

ChatHandler is meant to wrap a real player/GM session; it was only being
constructed here to reuse SendWorldText's string formatting, with no
actual session behind it.

Fix: use sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, text)
instead -- the core-provided, session-free broadcast path (the same one
the built-in .announce GM command uses in cs_message.cpp). No session
required, so no crash regardless of whether the event is triggered
automatically or by a player.

Fixed all three call sites using this broken pattern: the event-start
announcement (two locations -- StartEvent has what looks like an earlier
duplicate/preview announcement plus the main one) and the event-end
announcement in EndEvent(). The EndEvent() site had not crashed yet but
is the exact same bug and would have crashed the first time any event
completed naturally.
2026-09-04 13:43:49 +00:00

View file

@ -5,6 +5,7 @@
#include "DBCStores.h"
#include "GameObject.h"
#include "Log.h"
#include "WorldSessionMgr.h"
#include "Map.h"
#include "MapMgr.h"
#include "ObjectAccessor.h"
@ -324,7 +325,7 @@ public:
_currentSite.MapId, _currentSite.ZoneId, _currentSite.AreaId, anchor->GetName());
}
ChatHandler(nullptr).SendWorldText(Acore::StringFormat(_config.StartMessage, FormatLocationForAnnouncement(_currentSite, anchor)));
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(_config.StartMessage, FormatLocationForAnnouncement(_currentSite, anchor)));
if (_config.Debug)
{
@ -877,7 +878,7 @@ private:
}
std::string announcementLocation = FormatLocationForAnnouncement(_currentSite, anchor);
ChatHandler(nullptr).SendWorldText(Acore::StringFormat(_config.StartMessage, announcementLocation));
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(_config.StartMessage, announcementLocation));
if (_config.Debug)
{
@ -898,7 +899,7 @@ private:
return;
std::string location = BuildLocationText(_currentSite);
ChatHandler(nullptr).SendWorldText(Acore::StringFormat(_config.EndMessage, location));
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(_config.EndMessage, location));
if (_config.Debug)
LOG_INFO(GoldRushLogFilter, "Gold Rush ended in {}{}.", location, forced ? " (forced)" : "");