mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Fix crash cases when setting ConVar string using SetValue
Added IsMaterialThreadSetAllowed and QueueMaterialThreadSetValue checks.
This commit is contained in:
parent
9ba5e63ada
commit
0fe554b3d1
@ -483,12 +483,15 @@ void CRConServer::ProcessMessage(const cl_rcon::request& cl_request)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CRConServer::Execute(const cl_rcon::request& cl_request, bool bConVar) const
|
void CRConServer::Execute(const cl_rcon::request& cl_request, bool bConVar) const
|
||||||
{
|
{
|
||||||
ConVar* pConVar = g_pCVar->FindVar(cl_request.requestbuf().c_str());
|
if (bConVar)
|
||||||
if (pConVar) // Set value without running the callback.
|
|
||||||
{
|
{
|
||||||
pConVar->SetValue(cl_request.requestval().c_str());
|
ConVar* pConVar = g_pCVar->FindVar(cl_request.requestbuf().c_str());
|
||||||
|
if (pConVar) // Set value without running the callback.
|
||||||
|
{
|
||||||
|
pConVar->SetValue(cl_request.requestval().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!bConVar) // Execute command with "<val>".
|
else // Execute command with "<val>".
|
||||||
{
|
{
|
||||||
Cbuf_AddText(Cbuf_GetCurrentPlayer(), cl_request.requestbuf().c_str(), cmd_source_t::kCommandSrcCode);
|
Cbuf_AddText(Cbuf_GetCurrentPlayer(), cl_request.requestbuf().c_str(), cmd_source_t::kCommandSrcCode);
|
||||||
Cbuf_Execute();
|
Cbuf_Execute();
|
||||||
|
@ -56,6 +56,7 @@ class CCommand;
|
|||||||
#define FCVAR_SERVER_CANNOT_QUERY (1<<29) // If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
|
#define FCVAR_SERVER_CANNOT_QUERY (1<<29) // If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
|
||||||
#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command.
|
#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command.
|
||||||
|
|
||||||
|
#define FCVAR_MATERIAL_THREAD_MASK ( FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD )
|
||||||
/*
|
/*
|
||||||
class ConVar : ConCommandBase, IConVar; [MI] (#classinformer)
|
class ConVar : ConCommandBase, IConVar; [MI] (#classinformer)
|
||||||
dq offset ? ? _R4ConVar@@6B@; const ConVar::`RTTI Complete Object Locator'
|
dq offset ? ? _R4ConVar@@6B@; const ConVar::`RTTI Complete Object Locator'
|
||||||
|
@ -279,7 +279,7 @@ void ConVar::PurgeHostNames(void) const
|
|||||||
{
|
{
|
||||||
if (ConVar* pCVar = g_pCVar->FindVar(pszHostNames[i]))
|
if (ConVar* pCVar = g_pCVar->FindVar(pszHostNames[i]))
|
||||||
{
|
{
|
||||||
pCVar->ChangeStringValue("0.0.0.0");
|
pCVar->SetValue("0.0.0.0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,14 +512,17 @@ void ConVar::SetValue(Color value)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ConVar::InternalSetValue(const char* pszValue)
|
void ConVar::InternalSetValue(const char* pszValue)
|
||||||
{
|
{
|
||||||
if (strcmp(this->m_pParent->m_Value.m_pszString, pszValue) == 0)
|
if (IsFlagSet(this, FCVAR_MATERIAL_THREAD_MASK))
|
||||||
{
|
{
|
||||||
return;
|
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
|
||||||
|
{
|
||||||
|
g_pCVar->QueueMaterialThreadSetValue(this, pszValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->m_pParent->m_Value.m_pszString = pszValue;
|
|
||||||
|
|
||||||
char szTempValue[32]{};
|
char szTempValue[32];
|
||||||
const char* pszNewValue{};
|
const char* pszNewValue;
|
||||||
|
|
||||||
// Only valid for root convars.
|
// Only valid for root convars.
|
||||||
assert(m_pParent == this);
|
assert(m_pParent == this);
|
||||||
@ -533,7 +536,9 @@ void ConVar::InternalSetValue(const char* pszValue)
|
|||||||
if (!SetColorFromString(pszValue))
|
if (!SetColorFromString(pszValue))
|
||||||
{
|
{
|
||||||
// Not a color, do the standard thing
|
// Not a color, do the standard thing
|
||||||
float flNewValue = static_cast<float>(atof(pszValue));
|
double dblValue = atof(pszValue); // Use double to avoid 24-bit restriction on integers and allow storing timestamps or dates in convars
|
||||||
|
float flNewValue = static_cast<float>(dblValue);
|
||||||
|
|
||||||
if (!IsFinite(flNewValue))
|
if (!IsFinite(flNewValue))
|
||||||
{
|
{
|
||||||
Warning(eDLL_T::ENGINE, "Warning: ConVar '%s' = '%s' is infinite, clamping value.\n", GetBaseName(), pszValue);
|
Warning(eDLL_T::ENGINE, "Warning: ConVar '%s' = '%s' is infinite, clamping value.\n", GetBaseName(), pszValue);
|
||||||
@ -566,6 +571,15 @@ void ConVar::InternalSetIntValue(int nValue)
|
|||||||
if (nValue == m_Value.m_nValue)
|
if (nValue == m_Value.m_nValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (IsFlagSet(this, FCVAR_MATERIAL_THREAD_MASK))
|
||||||
|
{
|
||||||
|
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
|
||||||
|
{
|
||||||
|
g_pCVar->QueueMaterialThreadSetValue(this, nValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(m_pParent == this); // Only valid for root convars.
|
assert(m_pParent == this); // Only valid for root convars.
|
||||||
|
|
||||||
float fValue = static_cast<float>(nValue);
|
float fValue = static_cast<float>(nValue);
|
||||||
@ -595,6 +609,15 @@ void ConVar::InternalSetFloatValue(float flValue)
|
|||||||
if (flValue == m_Value.m_fValue)
|
if (flValue == m_Value.m_fValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (IsFlagSet(this, FCVAR_MATERIAL_THREAD_MASK))
|
||||||
|
{
|
||||||
|
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
|
||||||
|
{
|
||||||
|
g_pCVar->QueueMaterialThreadSetValue(this, flValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(m_pParent == this); // Only valid for root convars.
|
assert(m_pParent == this); // Only valid for root convars.
|
||||||
|
|
||||||
// Check bounds
|
// Check bounds
|
||||||
@ -742,52 +765,57 @@ bool ConVar::SetColorFromString(const char* pszValue)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ConVar::ChangeStringValue(const char* pszTempVal)
|
void ConVar::ChangeStringValue(const char* pszTempVal)
|
||||||
{
|
{
|
||||||
ConVar_ChangeStringValue(this, pszTempVal);
|
assert(!(m_nFlags & FCVAR_NEVER_AS_STRING));
|
||||||
|
|
||||||
//assert(!(m_nFlags & FCVAR_NEVER_AS_STRING));
|
char* pszOldValue = reinterpret_cast<char*>(_malloca(m_Value.m_iStringLength));
|
||||||
|
if (pszOldValue != nullptr)
|
||||||
|
{
|
||||||
|
memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_iStringLength);
|
||||||
|
}
|
||||||
|
|
||||||
//char* pszOldValue = reinterpret_cast<char*>(_malloca(m_Value.m_iStringLength));
|
if (pszTempVal)
|
||||||
//if (pszOldValue != nullptr)
|
{
|
||||||
//{
|
size_t len = strlen(pszTempVal) + 1;
|
||||||
// memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_iStringLength);
|
if (len > m_Value.m_iStringLength)
|
||||||
//}
|
{
|
||||||
|
if (m_Value.m_pszString)
|
||||||
|
{
|
||||||
|
MemAllocSingleton()->Free(m_Value.m_pszString);
|
||||||
|
}
|
||||||
|
|
||||||
//if (pszTempVal)
|
m_Value.m_pszString = MemAllocSingleton()->Alloc<char>(len);
|
||||||
//{
|
m_Value.m_iStringLength = len;
|
||||||
// size_t len = strlen(pszTempVal) + 1;
|
}
|
||||||
|
else if (!m_Value.m_pszString)
|
||||||
|
{
|
||||||
|
m_Value.m_pszString = MemAllocSingleton()->Alloc<char>(len);
|
||||||
|
m_Value.m_iStringLength = len;
|
||||||
|
}
|
||||||
|
memmove(m_Value.m_pszString, pszTempVal, len);
|
||||||
|
|
||||||
// if (len > m_Value.m_iStringLength)
|
/*****
|
||||||
// {
|
!FIXME:
|
||||||
// if (m_Value.m_pszString)
|
Respawn put additional code here which
|
||||||
// {
|
seems to itterate over a 64bit integer
|
||||||
// MemAllocSingleton()->Free(m_Value.m_pszString);
|
to call the callback several times (as many times as m_iCallbackCount?).
|
||||||
// }
|
******/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Value.m_pszString = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// m_Value.m_pszString = MemAllocSingleton()->Alloc<const char>(len);
|
pszOldValue = nullptr;
|
||||||
// m_Value.m_iStringLength = len;
|
|
||||||
// }
|
|
||||||
// else if (!m_Value.m_pszString)
|
|
||||||
// {
|
|
||||||
// m_Value.m_pszString = MemAllocSingleton()->Alloc<const char>(len);
|
|
||||||
// m_Value.m_iStringLength = len;
|
|
||||||
// }
|
|
||||||
// memmove(const_cast<char*>(m_Value.m_pszString), pszTempVal, len);
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// m_Value.m_pszString = nullptr;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//pszOldValue = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: changes the ConVar string value (only use if the new string is equal or lower than this->m_iStringLength).
|
// Purpose: changes the ConVar string value (this is faster than ChangeStringValue,
|
||||||
|
// only use if the new string is equal or lower than this->m_iStringLength).
|
||||||
// Input : *pszTempVal - flOldValue
|
// Input : *pszTempVal - flOldValue
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ConVar::ChangeStringValueUnsafe(const char* pszNewValue)
|
void ConVar::ChangeStringValueUnsafe(const char* pszNewValue)
|
||||||
{
|
{
|
||||||
m_Value.m_pszString = pszNewValue;
|
m_Value.m_pszString = const_cast<char*>(pszNewValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -70,17 +70,17 @@ public:
|
|||||||
|
|
||||||
struct CVValue_t
|
struct CVValue_t
|
||||||
{
|
{
|
||||||
const char* m_pszString;
|
char* m_pszString;
|
||||||
size_t m_iStringLength;
|
size_t m_iStringLength;
|
||||||
float m_fValue;
|
float m_fValue;
|
||||||
int m_nValue;
|
int m_nValue;
|
||||||
};
|
};
|
||||||
struct CVCallback_t
|
struct CVCallback_t
|
||||||
{
|
{
|
||||||
void** m_ppCallback;
|
void** m_ppCallback;
|
||||||
int64_t m_iFlags;
|
int64_t m_iFlags;
|
||||||
char m_Pad[8];
|
char m_Pad[8];
|
||||||
int64_t m_iTimesChanged;
|
int64_t m_iCallbackCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
IConVar* m_pIConVarVFTable{}; //0x0040
|
IConVar* m_pIConVarVFTable{}; //0x0040
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
float m_fMinVal {}; //0x0074
|
float m_fMinVal {}; //0x0074
|
||||||
bool m_bHasMax {}; //0x0078
|
bool m_bHasMax {}; //0x0078
|
||||||
float m_fMaxVal {}; //0x007C
|
float m_fMaxVal {}; //0x007C
|
||||||
CVCallback_t m_Callback {}; //0x0080
|
CVCallback_t m_Callback {}; //0x0080 // <-- !FIXME: 'CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks;'
|
||||||
}; //Size: 0x00A0
|
}; //Size: 0x00A0
|
||||||
|
|
||||||
/* ==== ICONVAR ========================================================================================================================================================= */
|
/* ==== ICONVAR ========================================================================================================================================================= */
|
||||||
|
@ -243,5 +243,29 @@ unordered_map<string, ConCommandBase*> CCVar::DumpToMap(void)
|
|||||||
return allConVars;
|
return allConVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: deal with queued material system ConVars
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CCVar::IsMaterialThreadSetAllowed(void)
|
||||||
|
{
|
||||||
|
const int index = 280;
|
||||||
|
return CallVFunc<bool>(index, this);
|
||||||
|
}
|
||||||
|
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, float flValue)
|
||||||
|
{
|
||||||
|
const int index = 288;
|
||||||
|
CallVFunc<void>(index, this, pConVar, flValue);
|
||||||
|
}
|
||||||
|
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, int nValue)
|
||||||
|
{
|
||||||
|
const int index = 296;
|
||||||
|
CallVFunc<void>(index, this, pConVar, nValue);
|
||||||
|
}
|
||||||
|
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, const char* pValue)
|
||||||
|
{
|
||||||
|
const int index = 304;
|
||||||
|
CallVFunc<void>(index, this, pConVar, pValue);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
CCVar* g_pCVar = nullptr;
|
CCVar* g_pCVar = nullptr;
|
||||||
|
@ -182,6 +182,11 @@ public:
|
|||||||
ConCommand* FindCommand(const char* pszCommandName);
|
ConCommand* FindCommand(const char* pszCommandName);
|
||||||
CCVarIteratorInternal* FactoryInternalIterator(void);
|
CCVarIteratorInternal* FactoryInternalIterator(void);
|
||||||
unordered_map<string, ConCommandBase*> DumpToMap(void);
|
unordered_map<string, ConCommandBase*> DumpToMap(void);
|
||||||
|
|
||||||
|
bool IsMaterialThreadSetAllowed(void);
|
||||||
|
void QueueMaterialThreadSetValue(ConVar* pConVar, float flValue);
|
||||||
|
void QueueMaterialThreadSetValue(ConVar* pConVar, int nValue);
|
||||||
|
void QueueMaterialThreadSetValue(ConVar* pConVar, const char* pValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user