From 036fbda90673c8fd9a5b0d9fde6e7e325ee09be0 Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Sun, 25 Apr 2021 22:47:55 +0200 Subject: [PATCH] Fix strdup() leaks --- sp/src/game/server/ai_speech.cpp | 2 +- sp/src/game/server/effects.cpp | 15 +++---- sp/src/game/server/mapbase/ai_monitor.cpp | 51 +++++++++++++---------- sp/src/game/shared/mapbase/MapEdit.cpp | 7 ++-- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/sp/src/game/server/ai_speech.cpp b/sp/src/game/server/ai_speech.cpp index dafad41e4a..10e7fcfecb 100644 --- a/sp/src/game/server/ai_speech.cpp +++ b/sp/src/game/server/ai_speech.cpp @@ -1240,7 +1240,7 @@ char *CAI_Expresser::ParseApplyContext( const char *szContext ) { // If it's really 0, then this is a waste of time Warning("\"%s\" was detected by applyContext operators as an operable number, but it's not.\n", szValue); - return strdup(szContext); + return szContext; } // This is the existing value; will be operated upon and become the final assignment diff --git a/sp/src/game/server/effects.cpp b/sp/src/game/server/effects.cpp index 7b07e15709..a07ae1bd95 100644 --- a/sp/src/game/server/effects.cpp +++ b/sp/src/game/server/effects.cpp @@ -2511,7 +2511,7 @@ class CBreakableGibShooter : public CBaseEntity DECLARE_DATADESC(); public: - const char *GetRandomTemplateModel( CPointTemplate *pTemplate ); + int GetRandomTemplateModelIndex( CPointTemplate *pTemplate ); void Precache( void ); @@ -2560,19 +2560,20 @@ END_DATADESC() LINK_ENTITY_TO_CLASS( env_break_shooter, CBreakableGibShooter ); -const char *CBreakableGibShooter::GetRandomTemplateModel( CPointTemplate *pTemplate ) +int CBreakableGibShooter::GetRandomTemplateModelIndex( CPointTemplate *pTemplate ) { int iIndex = RandomInt( 0, pTemplate->GetNumTemplates() ); - char *iszTemplate = (char*)(STRING(Templates_FindByIndex(pTemplate->GetTemplateIndexForTemplate(iIndex)))); + char *iszTemplate = strdup(STRING(Templates_FindByIndex(pTemplate->GetTemplateIndexForTemplate(iIndex)))); CEntityMapData entData( iszTemplate ); // This might seem a little messy, but I think it's cheaper than creating the entity. char szModel[MAPKEY_MAXLENGTH]; - if (!entData.ExtractValue("model", szModel)) - return NULL; + bool modelExtracted = entData.ExtractValue("model", szModel); + + free(iszTemplate); - return strdup(szModel); + return modelinfo->GetModelIndex( modelExtracted ? szModel : NULL ); } void CBreakableGibShooter::Precache( void ) @@ -2604,7 +2605,7 @@ void CBreakableGibShooter::Shoot( void ) if (m_iModelType == MODELTYPE_BREAKABLECHUNKS) iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( STRING( GetModelName() ) ) ); else if (m_iModelType == MODELTYPE_TEMPLATE) - iModelIndex = modelinfo->GetModelIndex( GetRandomTemplateModel(pTemplate) ); + iModelIndex = GetRandomTemplateModelIndex( pTemplate ); // All objects except the first one in this run are marked as slaves... int slaveFlag = 0; diff --git a/sp/src/game/server/mapbase/ai_monitor.cpp b/sp/src/game/server/mapbase/ai_monitor.cpp index 754ff56d9b..fa11a20398 100644 --- a/sp/src/game/server/mapbase/ai_monitor.cpp +++ b/sp/src/game/server/mapbase/ai_monitor.cpp @@ -672,6 +672,33 @@ int CAI_Monitor::TranslateScheduleString(const char *schedName) return 0; } +template +static void SetForEachDelimited( CAI_Monitor &monitor, const char *szValue, const char *delimiters, void (CAI_Monitor::*setter)(int), Translator translator) +{ + char *value = strdup(szValue); + char *token = strtok(value, ":"); + while (token) + { + (monitor.*setter)(translator(token)); + + token = strtok(NULL, ":"); + } + free(value); +} + +template +struct CAI_MonitorTranslator +{ + CAI_Monitor &monitor; + + CAI_MonitorTranslator(CAI_Monitor &monitor) : monitor(monitor) {} + + int operator()(const char *value) + { + return (monitor.*translator)(value); + } +}; + //----------------------------------------------------------------------------- // Purpose: Cache user entity field values until spawn is called. // Input : szKeyName - Key to handle. @@ -688,13 +715,7 @@ bool CAI_Monitor::KeyValue( const char *szKeyName, const char *szValue ) } else if (FStrEq(szKeyName, "Conditions")) { - char *token = strtok(strdup(szValue), ":"); - while (token) - { - SetCondition(TranslateConditionString(token)); - - token = strtok(NULL, ":"); - } + SetForEachDelimited(*this, szValue, ":", &CAI_Monitor::SetCondition, CAI_MonitorTranslator<&CAI_Monitor::TranslateConditionString>(*this)); } else if (FStrEq(szKeyName, "SchedulesSimple")) { @@ -703,13 +724,7 @@ bool CAI_Monitor::KeyValue( const char *szKeyName, const char *szValue ) } else if (FStrEq(szKeyName, "Schedules")) { - char *token = strtok(strdup(szValue), ":"); - while (token) - { - SetSchedule(TranslateScheduleString(token)); - - token = strtok(NULL, ":"); - } + SetForEachDelimited(*this, szValue, ":", &CAI_Monitor::SetSchedule, CAI_MonitorTranslator<&CAI_Monitor::TranslateScheduleString>(*this)); } else if (FStrEq(szKeyName, "HintsSimple")) { @@ -718,13 +733,7 @@ bool CAI_Monitor::KeyValue( const char *szKeyName, const char *szValue ) } else if (FStrEq(szKeyName, "Hints")) { - char *token = strtok(strdup(szValue), ":"); - while (token) - { - SetHint(atoi(szValue)); - - token = strtok(NULL, ":"); - } + SetForEachDelimited(*this, szValue, ":", &CAI_Monitor::SetHint, atoi); } else return CBaseEntity::KeyValue( szKeyName, szValue ); diff --git a/sp/src/game/shared/mapbase/MapEdit.cpp b/sp/src/game/shared/mapbase/MapEdit.cpp index 326599648a..9ff1db6045 100644 --- a/sp/src/game/shared/mapbase/MapEdit.cpp +++ b/sp/src/game/shared/mapbase/MapEdit.cpp @@ -464,7 +464,7 @@ class CMapEdit : public CAutoGameSystemPerFrame { pNodeName = pName->GetName(); - const char *pInputName = NULL; + string_t pInputName = NULL_STRING; variant_t varInputParam; float flInputDelay = 0.0f; CBaseEntity *pActivator = NULL; @@ -480,7 +480,7 @@ class CMapEdit : public CAutoGameSystemPerFrame { // Input name case 0: - pInputName = inputparams; break; + pInputName = AllocPooledString(inputparams); break; // Input parameter case 1: varInputParam.SetString(AllocPooledString(inputparams)); break; @@ -500,9 +500,10 @@ class CMapEdit : public CAutoGameSystemPerFrame iter++; inputparams = strtok(NULL, ","); } + free(pszValue); DebugMsg("MapEdit Debug: Firing input %s on %s\n", pInputName, pNodeName); - g_EventQueue.AddEvent(pNodeName, pInputName, varInputParam, flInputDelay, pActivator, pCaller, iOutputID); + g_EventQueue.AddEvent(pNodeName, STRING(pInputName), varInputParam, flInputDelay, pActivator, pCaller, iOutputID); pName = pName->GetNextKey(); }