From 0b1b0eaeccdbf1fee18311ce3389eb6cfc6be595 Mon Sep 17 00:00:00 2001 From: Alex Dcnh <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:18:14 +0100 Subject: [PATCH] Core - Fix RTSC SeeSpellAction crash on malformed WorldPacket (#1841) ## Summary This PR fixes the Crash 1 Source from Issue [#1840](https://github.com/mod-playerbots/mod-playerbots/issues/1840) posted in a @Regrad posted logs, in `SeeSpellAction::Execute` when an RTSC "see spell" event arrives with an empty or malformed `WorldPacket`. In that case the code used to read from the packet without any validation, causing a `ByteBufferException` and a crash in the map thread. ## Fix - Reset the packet read position and check that the RTSC header (castCount + spellId + castFlags) fits into the packet before reading. - Wrap `SpellCastTargets::Read` in a `try { } catch (ByteBufferException const&) { }` block so truncated RTSC payloads are handled gracefully. - Check that `targets.GetDst()` is not `nullptr` before accessing its position. For valid RTSC packets the behavior is unchanged; malformed packets are now safely ignored instead of crashing the server. ## Testing - Sent bots to multiple locations using RTSC and verified they still move as before. - Reproduced the previous crash scenario with malformed RTSC packets: the worldserver no longer crashes and the event is simply ignored. --------- Co-authored-by: bash Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com> --- src/strategy/actions/SeeSpellAction.cpp | 44 ++++++++++++++++++++----- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/strategy/actions/SeeSpellAction.cpp b/src/strategy/actions/SeeSpellAction.cpp index 8b90adec..f42dcade 100644 --- a/src/strategy/actions/SeeSpellAction.cpp +++ b/src/strategy/actions/SeeSpellAction.cpp @@ -12,6 +12,7 @@ #include "RTSCValues.h" #include "RtscAction.h" #include "PositionValue.h" +#include "ByteBuffer.h" Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, float o, uint32 entry, Creature* lastWp, bool important) @@ -31,27 +32,52 @@ Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, bool SeeSpellAction::Execute(Event event) { - WorldPacket p(event.getPacket()); // + // RTSC packet data + WorldPacket p(event.getPacket()); + uint8 castCount; uint32 spellId; - uint8 castCount, castFlags; + uint8 castFlags; + + // check RTSC header size = castCount (uint8) + spellId (uint32) + castFlags (uint8) + uint32 const rtscHeaderSize = sizeof(uint8) + sizeof(uint32) + sizeof(uint8); + if (p.size() < rtscHeaderSize) + { + LOG_WARN("playerbots", "SeeSpellAction: Corrupt RTSC packet size={}, expected>={}", p.size(), rtscHeaderSize); + return false; + } + Player* master = botAI->GetMaster(); - - p.rpos(0); - p >> castCount >> spellId >> castFlags; - if (!master) return false; + // read RTSC packet data + p.rpos(0); // set read position to start + p >> castCount >> spellId >> castFlags; + // if (!botAI->HasStrategy("RTSC", botAI->GetState())) // return false; if (spellId != RTSC_MOVE_SPELL) return false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - + // should not throw exception,just defensive measure to prevent any crashes when core function breaks. SpellCastTargets targets; - targets.Read(p, botAI->GetMaster()); + try + { + targets.Read(p, master); + if (!targets.GetDst()) + { + // do not dereference a null destination; ignore malformed RTSC packets instead of crashing + LOG_WARN("playerbots", "SeeSpellAction: (malformed) RTSC payload does not contain full targets data"); + return false; + } + } + catch (ByteBufferException const&) + { + // ignore malformed RTSC packets instead of crashing + LOG_WARN("playerbots", "SeeSpellAction: Failed deserialization (malformed) RTSC payload"); + return false; + } WorldPosition spellPosition(master->GetMapId(), targets.GetDst()->_position); SET_AI_VALUE(WorldPosition, "see spell location", spellPosition);