Skip to content

Commit 1faae29

Browse files
committed
fix: backport edict overflow protection
1 parent ddd20da commit 1faae29

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

src/engine/pr_edict.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,39 @@ edict_t *ED_Alloc( int iForceEdictIndex )
205205
// Allocate a new edict.
206206
if ( sv.num_edicts >= sv.max_edicts )
207207
{
208+
if ( sv.max_edicts != 0 )
209+
{
210+
// We don't have any available edicts that are newer than
211+
// EDICT_FREETIME. Rather than crash/restart try to find an edict that
212+
// was deleted less than EDICT_FREETIME ago. This will protect us
213+
// against potential server hacks like those used to crash
214+
// dota2 servers.
215+
iBit = -1;
216+
for ( ;; )
217+
{
218+
iBit = g_FreeEdicts.FindNextSetBit( iBit + 1 );
219+
if ( iBit < 0 )
220+
break;
221+
222+
edict_t *pEdict = &sv.edicts[ iBit ];
223+
224+
// If this assert goes off, someone most likely called pedict->ClearFree() and not ED_ClearFreeFlag()?
225+
Assert( pEdict->IsFree() );
226+
Assert( iBit == pEdict->m_EdictIndex );
227+
// If we have no freetime, we've had AllowImmediateReuse() called. We need
228+
// to explicitly delete this old entity.
229+
if ( pEdict->freetime == 0 && sv_useexplicitdelete.GetBool() )
230+
{
231+
//Warning("ADDING SLOT to snapshot: %d\n", i );
232+
framesnapshotmanager->AddExplicitDelete( iBit );
233+
}
234+
--sv.free_edicts;
235+
g_FreeEdicts.Clear( pEdict->m_EdictIndex );
236+
ED_ClearEdict( pEdict );
237+
return pEdict;
238+
}
239+
}
240+
208241
AssertMsg( 0, "Can't allocate edict" );
209242

210243
SpewEdicts(); // Log the entities we have before we die

0 commit comments

Comments
 (0)