Allowed CVARs to be set in unsafe context

CVAR values set in unsafe context are not written to user configuration file
This does not affect mod's CVARs

https://forum.zdoom.org/viewtopic.php?t=59484
This commit is contained in:
alexey.lysiuk 2018-02-23 12:56:00 +02:00 committed by Christoph Oelckers
parent 2541bd93fc
commit 4053e18835
2 changed files with 29 additions and 29 deletions

View file

@ -60,6 +60,7 @@ struct FLatchedValue
FBaseCVar *Variable; FBaseCVar *Variable;
UCVarValue Value; UCVarValue Value;
ECVarType Type; ECVarType Type;
bool UnsafeContext;
}; };
static TArray<FLatchedValue> LatchedValues; static TArray<FLatchedValue> LatchedValues;
@ -71,11 +72,6 @@ FBaseCVar *CVars = NULL;
int cvar_defflags; int cvar_defflags;
FBaseCVar::FBaseCVar (const FBaseCVar &var)
{
I_FatalError ("Use of cvar copy constructor");
}
FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &)) FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &))
{ {
FBaseCVar *var; FBaseCVar *var;
@ -148,7 +144,12 @@ void FBaseCVar::ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend)
if (m_UseCallback) if (m_UseCallback)
Callback (); Callback ();
Flags &= ~CVAR_ISDEFAULT; if ((Flags & CVAR_ARCHIVE) && !(Flags & CVAR_UNSAFECONTEXT))
{
SafeValue = GetGenericRep(CVAR_String).String;
}
Flags &= ~(CVAR_ISDEFAULT | CVAR_UNSAFECONTEXT);
} }
void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type)
@ -167,13 +168,17 @@ void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type)
latch.Value = value; latch.Value = value;
else else
latch.Value.String = copystring(value.String); latch.Value.String = copystring(value.String);
latch.UnsafeContext = !!(Flags & CVAR_UNSAFECONTEXT);
LatchedValues.Push (latch); LatchedValues.Push (latch);
Flags &= ~CVAR_UNSAFECONTEXT;
} }
else if ((Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) else if ((Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback)
{ {
if (netgame && !players[consoleplayer].settings_controller) if (netgame && !players[consoleplayer].settings_controller)
{ {
Printf ("Only setting controllers can change %s\n", Name); Printf ("Only setting controllers can change %s\n", Name);
Flags &= ~CVAR_UNSAFECONTEXT;
return; return;
} }
D_SendServerInfoChange (this, value, type); D_SendServerInfoChange (this, value, type);
@ -1134,6 +1139,14 @@ DEFINE_ACTION_FUNCTION(_CVar, ResetToDefault)
return 0; return 0;
} }
void FBaseCVar::MarkUnsafe()
{
if (!(Flags & CVAR_MOD) && UnsafeExecutionContext)
{
Flags |= CVAR_UNSAFECONTEXT;
}
}
// //
// Flag cvar implementation // Flag cvar implementation
// //
@ -1644,6 +1657,8 @@ void UnlatchCVars (void)
{ {
uint32_t oldflags = var.Variable->Flags; uint32_t oldflags = var.Variable->Flags;
var.Variable->Flags &= ~(CVAR_LATCH | CVAR_SERVERINFO); var.Variable->Flags &= ~(CVAR_LATCH | CVAR_SERVERINFO);
if (var.UnsafeContext)
var.Variable->Flags |= CVAR_UNSAFECONTEXT;
var.Variable->SetGenericRep (var.Value, var.Type); var.Variable->SetGenericRep (var.Value, var.Type);
if (var.Type == CVAR_String) if (var.Type == CVAR_String)
delete[] var.Value.String; delete[] var.Value.String;
@ -1697,9 +1712,7 @@ void C_ArchiveCVars (FConfigFile *f, uint32_t filter)
(CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_MOD|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE)) (CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_MOD|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE))
== filter) == filter)
{ {
UCVarValue val; f->SetValueForKey(cvar->GetName(), cvar->SafeValue);
val = cvar->GetGenericRep (CVAR_String);
f->SetValueForKey (cvar->GetName (), val.String);
} }
cvar = cvar->m_Next; cvar = cvar->m_Next;
} }
@ -1707,16 +1720,6 @@ void C_ArchiveCVars (FConfigFile *f, uint32_t filter)
EXTERN_CVAR(Bool, sv_cheats); EXTERN_CVAR(Bool, sv_cheats);
static bool IsUnsafe(const FBaseCVar *const var)
{
const bool unsafe = UnsafeExecutionContext && !(var->GetFlags() & CVAR_MOD);
if (unsafe)
{
Printf(TEXTCOLOR_RED "Cannot set console variable" TEXTCOLOR_GOLD " %s " TEXTCOLOR_RED "from unsafe command\n", var->GetName());
}
return unsafe;
}
void FBaseCVar::CmdSet (const char *newval) void FBaseCVar::CmdSet (const char *newval)
{ {
if ((GetFlags() & CVAR_CHEAT) && !sv_cheats) if ((GetFlags() & CVAR_CHEAT) && !sv_cheats)
@ -1724,10 +1727,8 @@ void FBaseCVar::CmdSet (const char *newval)
Printf("sv_cheats must be true to set this console variable.\n"); Printf("sv_cheats must be true to set this console variable.\n");
return; return;
} }
else if (IsUnsafe(this))
{ MarkUnsafe();
return;
}
UCVarValue val; UCVarValue val;
@ -1814,10 +1815,7 @@ CCMD (toggle)
{ {
if ( (var = FindCVar (argv[1], &prev)) ) if ( (var = FindCVar (argv[1], &prev)) )
{ {
if (IsUnsafe(var)) var->MarkUnsafe();
{
return;
}
val = var->GetGenericRep (CVAR_Bool); val = var->GetGenericRep (CVAR_Bool);
val.Bool = !val.Bool; val.Bool = !val.Bool;

View file

@ -64,6 +64,7 @@ enum
CVAR_MOD = 8192, // cvar was defined by a mod CVAR_MOD = 8192, // cvar was defined by a mod
CVAR_IGNORE = 16384,// do not send cvar across the network/inaccesible from ACS (dummy mod cvar) CVAR_IGNORE = 16384,// do not send cvar across the network/inaccesible from ACS (dummy mod cvar)
CVAR_CHEAT = 32768,// can be set only when sv_cheats is enabled CVAR_CHEAT = 32768,// can be set only when sv_cheats is enabled
CVAR_UNSAFECONTEXT = 65536,// cvar value came from unsafe context
}; };
union UCVarValue union UCVarValue
@ -110,6 +111,7 @@ public:
void SetGenericRep (UCVarValue value, ECVarType type); void SetGenericRep (UCVarValue value, ECVarType type);
void ResetToDefault (); void ResetToDefault ();
void SetArchiveBit () { Flags |= CVAR_ARCHIVE; } void SetArchiveBit () { Flags |= CVAR_ARCHIVE; }
void MarkUnsafe();
virtual ECVarType GetRealType () const = 0; virtual ECVarType GetRealType () const = 0;
@ -132,7 +134,6 @@ public:
static void ListVars (const char *filter, bool plain); static void ListVars (const char *filter, bool plain);
protected: protected:
FBaseCVar () {}
virtual void DoSet (UCVarValue value, ECVarType type) = 0; virtual void DoSet (UCVarValue value, ECVarType type) = 0;
static bool ToBool (UCVarValue value, ECVarType type); static bool ToBool (UCVarValue value, ECVarType type);
@ -147,10 +148,11 @@ protected:
static UCVarValue FromGUID (const GUID &value, ECVarType type); static UCVarValue FromGUID (const GUID &value, ECVarType type);
char *Name; char *Name;
FString SafeValue;
uint32_t Flags; uint32_t Flags;
private: private:
FBaseCVar (const FBaseCVar &var); FBaseCVar (const FBaseCVar &var) = delete;
FBaseCVar (const char *name, uint32_t flags); FBaseCVar (const char *name, uint32_t flags);
void (*m_Callback)(FBaseCVar &); void (*m_Callback)(FBaseCVar &);