From fcefc8b9deaef20beee07f203cfce036df1c631d Mon Sep 17 00:00:00 2001 From: Alex Lo Date: Tue, 21 Jul 2015 00:08:31 +0100 Subject: [PATCH] Fix crash when deleting a misc_model The following sequence of events and conditions will cause a segfault to occur: 1. Delete a misc_model 2. Undo the delete 3. Delete the same model again 4. Undo the delete A segfault will occur in CEntityMiscModel::Draw when m_model is dereferenced as it has been deleted and cleared. When cloning the misc_model entity, a new CEntityMiscModel is created and the name is set. However, CEntityMiscModel::BuildCacheRequestString relies on all epairs to be present before being able to generate the *correct* request string for the misc_model. Not doing so will cause incorrect behaviour - in this case, the reference count for the CEntityMiscModel is decremented one too many times and causes the object to be deleted. The misc_model object is then used later on after it has been freed. This commit fixes the problem by copying all epairs, before firing the OnKeyValueChanged events. This way, all epairs will be available when BuildCacheRequestString is called. --- plugins/entity/entity.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/entity/entity.cpp b/plugins/entity/entity.cpp index 580d2098..35c836fd 100644 --- a/plugins/entity/entity.cpp +++ b/plugins/entity/entity.cpp @@ -93,8 +93,21 @@ entity_t *Entity_Clone( entity_t *e ){ n = Entity_Alloc(); n->eclass = e->eclass; - for ( ep = e->epairs ; ep ; ep = ep->next ) - SetKeyValue( n, ep->key, ep->value ); + for ( ep = e->epairs ; ep ; ep = ep->next ){ + if ( !ep->key || !ep->key[0] ) { + Sys_FPrintf( SYS_ERR, "ERROR: Entity_Clone: NULL or zero-length key\n" ); + return 0; + } + + SetKeyValue( n->epairs, ep->key, ep->value ); + } + + for ( ep = n->epairs ; ep ; ep = ep->next ){ + /*! + \todo TODO broadcast this through a clean messaging API ;-) + */ + Entity_OnKeyValueChanged( n, ep->key, ep->value ); + } // copy some misc stuff as well VectorCopy( e->origin, n->origin );