1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-30 08:07:46 +00:00

fix eobj out of bounds allocation client crash

This commit is contained in:
Adam 2018-02-28 23:53:20 +11:00
parent 521c62013c
commit d024f0a396
6 changed files with 46 additions and 5 deletions

View file

@ -16,6 +16,7 @@ namespace Common {
// 99 is the last spawn id that seems to spawn any actor // 99 is the last spawn id that seems to spawn any actor
const uint8_t MAX_DISPLAYED_ACTORS = 99; const uint8_t MAX_DISPLAYED_ACTORS = 99;
const uint8_t MAX_DISPLAYED_EOBJS = 40;
const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000; const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000;

View file

@ -1316,7 +1316,7 @@ struct FFXIVIpcMSQTrackerComplete : FFXIVIpcBasePacket<MSQTrackerComplete>
struct FFXIVIpcObjectSpawn : FFXIVIpcBasePacket<ObjectSpawn> struct FFXIVIpcObjectSpawn : FFXIVIpcBasePacket<ObjectSpawn>
{ {
uint8_t count; uint8_t spawnIndex;
uint8_t objKind; uint8_t objKind;
uint8_t state; uint8_t state;
uint8_t unknown3; uint8_t unknown3;

View file

@ -100,7 +100,7 @@ void Core::Entity::EventObject::spawn( Core::Entity::PlayerPtr pTarget )
{ {
g_log.debug( "Spawning EObj: id:" + std::to_string( getId() ) + " name:" + getName() ); g_log.debug( "Spawning EObj: id:" + std::to_string( getId() ) + " name:" + getName() );
ZoneChannelPacket< FFXIVIpcObjectSpawn > eobjStatePacket( getId(), pTarget->getId() ); ZoneChannelPacket< FFXIVIpcObjectSpawn > eobjStatePacket( getId(), pTarget->getId() );
eobjStatePacket.data().count = pTarget->getNextObjCount(); eobjStatePacket.data().spawnIndex = pTarget->getNextObjSpawnIndexForActorId( getId( ));
eobjStatePacket.data().objKind = getObjKind(); eobjStatePacket.data().objKind = getObjKind();
eobjStatePacket.data().state = getState(); eobjStatePacket.data().state = getState();
eobjStatePacket.data().objId = getObjectId(); eobjStatePacket.data().objId = getObjectId();
@ -115,6 +115,8 @@ void Core::Entity::EventObject::spawn( Core::Entity::PlayerPtr pTarget )
void Core::Entity::EventObject::despawn( Core::Entity::PlayerPtr pTarget ) void Core::Entity::EventObject::despawn( Core::Entity::PlayerPtr pTarget )
{ {
g_log.debug( "despawn eobj: " + std::to_string( getId() ) ); g_log.debug( "despawn eobj: " + std::to_string( getId() ) );
pTarget->freeObjSpawnIndexForActorId( getId( ));
} }
const std::string& Core::Entity::EventObject::getName() const const std::string& Core::Entity::EventObject::getName() const

View file

@ -1659,9 +1659,37 @@ void Core::Entity::Player::teleportQuery( uint16_t aetheryteId )
} }
} }
uint8_t Core::Entity::Player::getNextObjCount() uint8_t Core::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actorId )
{ {
return m_objCount++; auto nextCount = m_freeObjCounts.front();
m_freeObjCounts.pop();
m_actorIdToObjCountMap[actorId] = nextCount;
return nextCount;
}
void Core::Entity::Player::resetObjSpawnIndex()
{
while( m_freeObjCounts.empty() )
m_freeObjCounts.pop();
for( uint32_t i = 0; i < MAX_DISPLAYED_EOBJS; ++i )
m_freeObjCounts.push( i );
m_actorIdToObjCountMap.clear();
}
void Core::Entity::Player::freeObjSpawnIndexForActorId( uint32_t actorId )
{
auto it = m_actorIdToObjCountMap.find( actorId );
if( it == m_actorIdToObjCountMap.end() )
return;
auto freeCount = m_actorIdToObjCountMap[actorId];
m_freeObjCounts.push( freeCount );
m_actorIdToObjCountMap.erase( actorId );
} }
void Core::Entity::Player::setOnEnterEventDone( bool isDone ) void Core::Entity::Player::setOnEnterEventDone( bool isDone )

View file

@ -562,7 +562,12 @@ public:
void setOnEnterEventDone( bool isDone ); void setOnEnterEventDone( bool isDone );
bool isOnEnterEventDone() const; bool isOnEnterEventDone() const;
uint8_t getNextObjCount(); /*! gets the next available obj count */
uint8_t getNextObjSpawnIndexForActorId( uint32_t actorId );
/*! resets the players obj count */
void resetObjSpawnIndex();
/*! frees an obj count to be used by another eobj */
void freeObjSpawnIndexForActorId( uint32_t actorId );
private: private:
uint32_t m_lastWrite; uint32_t m_lastWrite;
@ -679,6 +684,8 @@ private:
// counter used to index objects spawned for the player // counter used to index objects spawned for the player
uint8_t m_objCount; uint8_t m_objCount;
std::queue< uint8_t > m_freeObjCounts;
std::map< uint32_t, uint8_t > m_actorIdToObjCountMap;
}; };
} }

View file

@ -221,6 +221,7 @@ void Core::InstanceContent::setVar( uint8_t index, uint8_t value )
} }
// todo: genericise this?
for( const auto &playerIt : m_playerMap ) for( const auto &playerIt : m_playerMap )
{ {
sendDirectorVars( *playerIt.second ); sendDirectorVars( *playerIt.second );
@ -274,6 +275,8 @@ void Core::InstanceContent::onBeforeEnterTerritory( Core::Entity::Player &player
player.setRot( PI ); player.setRot( PI );
player.setPos( { 0.f, 0.f, 0.f } ); player.setPos( { 0.f, 0.f, 0.f } );
} }
player.resetObjSpawnIndex( );
} }
Core::Entity::EventObjectPtr Core::InstanceContent::getEObjByName( const std::string &name ) Core::Entity::EventObjectPtr Core::InstanceContent::getEObjByName( const std::string &name )