mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Fix heap-use-after-free in CGameWorld::RemoveEntity
Entities have a pointer to their parent entity. If the parent entity is freed first, then freeing the child will cause access to the already freed parent. This is fixed by adding a child pointer and clearing the child and parent pointers when either child or parent is freed.
This commit is contained in:
parent
1e31db257f
commit
2df4c4c668
|
@ -24,7 +24,8 @@ CEntity::CEntity(CGameWorld *pGameWorld, int ObjType, vec2 Pos, int ProximityRad
|
|||
m_SnapTicks = -1;
|
||||
|
||||
// DDRace
|
||||
m_pParent = 0;
|
||||
m_pParent = nullptr;
|
||||
m_pChild = nullptr;
|
||||
m_DestroyTick = -1;
|
||||
m_LastRenderTick = -1;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
int m_DestroyTick;
|
||||
int m_LastRenderTick;
|
||||
CEntity *m_pParent;
|
||||
CEntity *m_pChild;
|
||||
CEntity *NextEntity() { return m_pNextTypeEntity; }
|
||||
int ID() { return m_ID; }
|
||||
void Keep()
|
||||
|
|
|
@ -30,10 +30,7 @@ CGameWorld::CGameWorld()
|
|||
|
||||
CGameWorld::~CGameWorld()
|
||||
{
|
||||
// delete all entities
|
||||
for(auto &pFirstEntityType : m_apFirstEntityTypes)
|
||||
while(pFirstEntityType)
|
||||
delete pFirstEntityType;
|
||||
Clear();
|
||||
if(m_pChild && m_pChild->m_pParent == this)
|
||||
{
|
||||
OnModified();
|
||||
|
@ -143,9 +140,18 @@ void CGameWorld::RemoveEntity(CEntity *pEnt)
|
|||
pEnt->m_pNextTypeEntity = 0;
|
||||
pEnt->m_pPrevTypeEntity = 0;
|
||||
|
||||
if(m_IsValidCopy && m_pParent && m_pParent->m_pChild == this && pEnt->m_pParent)
|
||||
pEnt->m_pParent->m_DestroyTick = GameTick();
|
||||
pEnt->m_pParent = 0;
|
||||
if(pEnt->m_pParent)
|
||||
{
|
||||
if(m_IsValidCopy && m_pParent && m_pParent->m_pChild == this)
|
||||
pEnt->m_pParent->m_DestroyTick = GameTick();
|
||||
pEnt->m_pParent->m_pChild = nullptr;
|
||||
pEnt->m_pParent = nullptr;
|
||||
}
|
||||
if(pEnt->m_pChild)
|
||||
{
|
||||
pEnt->m_pChild->m_pParent = nullptr;
|
||||
pEnt->m_pChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CGameWorld::RemoveCharacter(CCharacter *pChar)
|
||||
|
@ -578,6 +584,7 @@ void CGameWorld::CopyWorld(CGameWorld *pFrom)
|
|||
if(pCopy)
|
||||
{
|
||||
pCopy->m_pParent = pEnt;
|
||||
pEnt->m_pChild = pCopy;
|
||||
this->InsertEntity(pCopy);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue