Core/SAI: Fix crash in SmartScript

Fix crash in SmartScript storing WorldObject* instead of guid as targets in SmartScript::mTargetStorage , used by SMART_TARGET_STORED target type , SMART_ESCORT_TARGETS and other escort related code.
Fixes #11228 , #10157 .

Valgrind log:
 Invalid read of size 4
  at : Object::GetTypeId() const (Object.h:140)
  by : SmartScript::IsPlayer(WorldObject*) (SmartScript.h:73)
  by : SmartScript::ProcessAction(SmartScriptHolder&, Unit*, unsigned int, unsigned int, bool, SpellInfo const*, GameObject*) (SmartScript.cpp:330)
  by : SmartScript::ProcessEvent(SmartScriptHolder&, Unit*, unsigned int, unsigned int, bool, SpellInfo const*, GameObject*) (SmartScript.cpp:2662)
  by : SmartScript::ProcessAction(SmartScriptHolder&, Unit*, unsigned int, unsigned int, bool, SpellInfo const*, GameObject*) (SmartScript.cpp:2226)
  by : SmartScript::ProcessTimedAction(SmartScriptHolder&, unsigned int const&, unsigned int const&, Unit*, unsigned int, unsigned int, bool, SpellInfo const*, GameObject*) (SmartScript.cpp:2238)
  by : SmartScript::ProcessEvent(SmartScriptHolder&, Unit*, unsigned int, unsigned int, bool, SpellInfo const*, GameObject*) (SmartScript.cpp:2685)
  by : SmartScript::UpdateTimer(SmartScriptHolder&, unsigned int) (SmartScript.cpp:3198)
  by : SmartScript::OnUpdate(unsigned int) (SmartScript.cpp:3244)
  by : SmartAI::UpdateAI(unsigned int) (SmartAI.cpp:331)
  by : Creature::Update(unsigned int) (Creature.cpp:544)
  by : void Trinity::ObjectUpdater::Visit<Creature>(GridRefManager<Creature>&) (GridNotifiers.cpp:340)
This commit is contained in:
jackpoz
2014-01-12 20:23:13 +01:00
parent de1d75af70
commit b8625f41bd
3 changed files with 57 additions and 5 deletions

View File

@@ -2551,7 +2551,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
{
ObjectListMap::iterator itr = mTargetStorage->find(e.target.stored.id);
if (itr != mTargetStorage->end())
l->assign(itr->second->begin(), itr->second->end());
{
ObjectList* objectList = itr->second->GetObjectList();
l->assign(objectList->begin(), objectList->end());
}
return l;
}

View File

@@ -99,13 +99,13 @@ class SmartScript
if (mTargetStorage->find(id) != mTargetStorage->end())
{
// check if already stored
if ((*mTargetStorage)[id] == targets)
if ((*mTargetStorage)[id]->Equals(targets))
return;
delete (*mTargetStorage)[id];
}
(*mTargetStorage)[id] = targets;
(*mTargetStorage)[id] = new ObjectGuidList(targets, GetBaseObject());
}
bool IsSmart(Creature* c = NULL)
@@ -141,7 +141,7 @@ class SmartScript
{
ObjectListMap::iterator itr = mTargetStorage->find(id);
if (itr != mTargetStorage->end())
return (*itr).second;
return (*itr).second->GetObjectList();
return NULL;
}

View File

@@ -1321,7 +1321,56 @@ struct SmartScriptHolder
typedef UNORDERED_MAP<uint32, WayPoint*> WPPath;
typedef std::list<WorldObject*> ObjectList;
typedef UNORDERED_MAP<uint32, ObjectList*> ObjectListMap;
typedef std::list<uint64> GuidList;
class ObjectGuidList
{
ObjectList* m_objectList;
GuidList* m_guidList;
WorldObject* m_baseObject;
public:
ObjectGuidList(ObjectList* objectList, WorldObject* baseObject)
{
ASSERT(objectList != NULL);
ASSERT(baseObject != NULL);
m_objectList = objectList;
m_baseObject = baseObject;
m_guidList = new GuidList();
for (ObjectList::iterator itr = objectList->begin(); itr != objectList->end(); ++itr)
{
m_guidList->push_back((*itr)->GetGUID());
}
}
ObjectList* GetObjectList()
{
//sanitize list using m_guidList
m_objectList->clear();
for (GuidList::iterator itr = m_guidList->begin(); itr != m_guidList->end(); ++itr)
{
if (WorldObject* obj = ObjectAccessor::GetWorldObject(*m_baseObject, *itr))
m_objectList->push_back(obj);
else
TC_LOG_DEBUG("scripts.ai", "SmartScript::mTargetStorage stores a guid to an invalid object: " UI64FMTD, *itr);
}
return m_objectList;
}
bool Equals(ObjectList* objectList)
{
return m_objectList == objectList;
}
~ObjectGuidList()
{
delete m_objectList;
delete m_guidList;
}
};
typedef UNORDERED_MAP<uint32, ObjectGuidList*> ObjectListMap;
class SmartWaypointMgr
{