Fix heap corruption in CUtlVector destructor (#1165)

This commit is contained in:
peace-maker 2020-02-09 00:36:21 +01:00 committed by GitHub
parent 452338dc11
commit 739c07ca9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 0 deletions

View File

@ -1212,6 +1212,45 @@ bool IsWindowsReservedDeviceName(const char *pMapname)
}
#endif
#if SOURCE_ENGINE >= SE_LEFT4DEAD && defined PLATFORM_WINDOWS
// This frees memory allocated by the game using the game's CRT on Windows,
// avoiding a crash due to heap corruption (issue #910).
template< class T, class I >
class CUtlMemoryGlobalMalloc : public CUtlMemory< T, I >
{
typedef CUtlMemory< T, I > BaseClass;
public:
using BaseClass::BaseClass;
void Purge()
{
if (!IsExternallyAllocated())
{
if (m_pMemory)
{
UTLMEMORY_TRACK_FREE();
g_pMemAlloc->Free((void*)m_pMemory);
m_pMemory = 0;
}
m_nAllocationCount = 0;
}
BaseClass::Purge();
}
};
void CHalfLife2::FreeUtlVectorUtlString(CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> &vec)
{
CUtlMemoryGlobalMalloc<unsigned char> *pMemory;
FOR_EACH_VEC(vec, i)
{
pMemory = (CUtlMemoryGlobalMalloc<unsigned char> *) &vec[i].m_Storage.m_Memory;
pMemory->Purge();
vec[i].m_Storage.SetLength(0);
}
}
#endif
SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_t nMapNameMax)
{
/* We need to ensure user input does not contain reserved device names on windows */
@ -1245,8 +1284,13 @@ SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
#ifdef PLATFORM_WINDOWS
CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> results;
pHelperCmd->AutoCompleteSuggest(pMapName, *(CUtlVector<CUtlString, CUtlMemory<CUtlString>>*)&results);
#else
CUtlVector<CUtlString> results;
pHelperCmd->AutoCompleteSuggest(pMapName, results);
#endif
if (results.Count() == 0)
return SMFindMapResult::NotFound;
@ -1258,11 +1302,17 @@ SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_
bool bExactMatch = Q_strcmp(pMapName, &results[0][helperCmdLen + 1]) == 0;
if (bExactMatch)
{
#ifdef PLATFORM_WINDOWS
FreeUtlVectorUtlString(results);
#endif
return SMFindMapResult::Found;
}
else
{
ke::SafeStrcpy(pFoundMap, nMapNameMax, &results[0][helperCmdLen + 1]);
#ifdef PLATFORM_WINDOWS
FreeUtlVectorUtlString(results);
#endif
return SMFindMapResult::FuzzyMatch;
}

View File

@ -179,6 +179,12 @@ enum class SMFindMapResult : cell_t {
PossiblyAvailable
};
#if SOURCE_ENGINE >= SE_LEFT4DEAD && defined PLATFORM_WINDOWS
template< class T, class I = int >
class CUtlMemoryGlobalMalloc;
class CUtlString;
#endif
class CHalfLife2 :
public SMGlobalClass,
public IGameHelpers
@ -229,6 +235,9 @@ public: //IGameHelpers
bool IsMapValid(const char *map);
SMFindMapResult FindMap(char *pMapName, size_t nMapNameMax);
SMFindMapResult FindMap(const char *pMapName, char *pFoundMap = NULL, size_t nMapNameMax = 0);
#if SOURCE_ENGINE >= SE_LEFT4DEAD && defined PLATFORM_WINDOWS
void FreeUtlVectorUtlString(CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> &vec);
#endif
bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax);
#if SOURCE_ENGINE >= SE_ORANGEBOX
string_t AllocPooledString(const char *pszValue);