mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 05:51:20 +00:00
Uniform way to guard ACS stack and variables
ACS VM stack and map/world/global variables arrays are now checked for out of bounds access
This commit is contained in:
parent
0f62cd67a5
commit
d5bc0a1fa9
2 changed files with 46 additions and 41 deletions
|
@ -835,12 +835,12 @@ inline int uallong(const int &foo)
|
|||
//============================================================================
|
||||
|
||||
// ACS variables with world scope
|
||||
int32_t ACS_WorldVars[NUM_WORLDVARS];
|
||||
FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS];
|
||||
static BoundsCheckingArray<int32_t, NUM_WORLDVARS> ACS_WorldVars;
|
||||
static BoundsCheckingArray<FWorldGlobalArray, NUM_WORLDVARS> ACS_WorldArrays;
|
||||
|
||||
// ACS variables with global scope
|
||||
int32_t ACS_GlobalVars[NUM_GLOBALVARS];
|
||||
FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS];
|
||||
BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
|
||||
BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> ACS_GlobalArrays;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -851,21 +851,7 @@ FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS];
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct FACSStackMemory
|
||||
{
|
||||
int32_t& operator[](const size_t index)
|
||||
{
|
||||
if (index >= STACK_SIZE)
|
||||
{
|
||||
I_Error("Corrupted stack pointer in ACS VM");
|
||||
}
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t buffer[STACK_SIZE];
|
||||
};
|
||||
using FACSStackMemory = BoundsCheckingArray<int32_t, STACK_SIZE>;
|
||||
|
||||
struct FACSStack
|
||||
{
|
||||
|
@ -1470,10 +1456,10 @@ void ACSStringPool::UnlockForLevel(int lnum)
|
|||
|
||||
void P_MarkWorldVarStrings()
|
||||
{
|
||||
GlobalACSStrings.MarkStringArray(ACS_WorldVars, countof(ACS_WorldVars));
|
||||
for (size_t i = 0; i < countof(ACS_WorldArrays); ++i)
|
||||
GlobalACSStrings.MarkStringArray(ACS_WorldVars.Pointer(), ACS_WorldVars.Size());
|
||||
for (size_t i = 0; i < ACS_WorldArrays.Size(); ++i)
|
||||
{
|
||||
GlobalACSStrings.MarkStringMap(ACS_WorldArrays[i]);
|
||||
GlobalACSStrings.MarkStringMap(ACS_WorldArrays.Pointer()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1485,10 +1471,10 @@ void P_MarkWorldVarStrings()
|
|||
|
||||
void P_MarkGlobalVarStrings()
|
||||
{
|
||||
GlobalACSStrings.MarkStringArray(ACS_GlobalVars, countof(ACS_GlobalVars));
|
||||
for (size_t i = 0; i < countof(ACS_GlobalArrays); ++i)
|
||||
GlobalACSStrings.MarkStringArray(ACS_GlobalVars.Pointer(), ACS_GlobalVars.Size());
|
||||
for (size_t i = 0; i < ACS_GlobalArrays.Size(); ++i)
|
||||
{
|
||||
GlobalACSStrings.MarkStringMap(ACS_GlobalArrays[i]);
|
||||
GlobalACSStrings.MarkStringMap(ACS_GlobalArrays.Pointer()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1571,14 +1557,14 @@ void P_ClearACSVars(bool alsoglobal)
|
|||
{
|
||||
int i;
|
||||
|
||||
memset (ACS_WorldVars, 0, sizeof(ACS_WorldVars));
|
||||
ACS_WorldVars.Fill(0);
|
||||
for (i = 0; i < NUM_WORLDVARS; ++i)
|
||||
{
|
||||
ACS_WorldArrays[i].Clear ();
|
||||
}
|
||||
if (alsoglobal)
|
||||
{
|
||||
memset (ACS_GlobalVars, 0, sizeof(ACS_GlobalVars));
|
||||
ACS_GlobalVars.Fill(0);
|
||||
for (i = 0; i < NUM_GLOBALVARS; ++i)
|
||||
{
|
||||
ACS_GlobalArrays[i].Clear ();
|
||||
|
@ -1726,10 +1712,10 @@ static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t co
|
|||
|
||||
void P_ReadACSVars(FSerializer &arc)
|
||||
{
|
||||
ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars");
|
||||
ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars");
|
||||
ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays");
|
||||
ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays");
|
||||
ReadVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars");
|
||||
ReadVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars");
|
||||
ReadArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays");
|
||||
ReadArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays");
|
||||
GlobalACSStrings.ReadStrings(arc, "acsglobalstrings");
|
||||
}
|
||||
|
||||
|
@ -1741,10 +1727,10 @@ void P_ReadACSVars(FSerializer &arc)
|
|||
|
||||
void P_WriteACSVars(FSerializer &arc)
|
||||
{
|
||||
WriteVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars");
|
||||
WriteVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars");
|
||||
WriteArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays");
|
||||
WriteArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays");
|
||||
WriteVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars");
|
||||
WriteVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars");
|
||||
WriteArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays");
|
||||
WriteArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays");
|
||||
GlobalACSStrings.WriteStrings(arc, "acsglobalstrings");
|
||||
}
|
||||
|
||||
|
|
31
src/p_acs.h
31
src/p_acs.h
|
@ -60,13 +60,32 @@ struct InitIntToZero
|
|||
};
|
||||
typedef TMap<int32_t, int32_t, THashTraits<int32_t>, InitIntToZero> FWorldGlobalArray;
|
||||
|
||||
// ACS variables with world scope
|
||||
extern int32_t ACS_WorldVars[NUM_WORLDVARS];
|
||||
extern FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS];
|
||||
// Type of elements count is unsigned int instead of size_t to match ACSStringPool interface
|
||||
template <typename T, unsigned int N>
|
||||
struct BoundsCheckingArray
|
||||
{
|
||||
T &operator[](const unsigned int index)
|
||||
{
|
||||
if (index >= N)
|
||||
{
|
||||
I_Error("Out of bounds memory access in ACS VM");
|
||||
}
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
T *Pointer() { return buffer; }
|
||||
unsigned int Size() const { return N; }
|
||||
|
||||
void Fill(const T &value) { std::fill(std::begin(buffer), std::end(buffer), value); }
|
||||
|
||||
private:
|
||||
T buffer[N];
|
||||
};
|
||||
|
||||
// ACS variables with global scope
|
||||
extern int32_t ACS_GlobalVars[NUM_GLOBALVARS];
|
||||
extern FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS];
|
||||
extern BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
|
||||
extern BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> ACS_GlobalArrays;
|
||||
|
||||
#define LIBRARYID_MASK 0xFFF00000
|
||||
#define LIBRARYID_SHIFT 20
|
||||
|
@ -359,7 +378,7 @@ public:
|
|||
ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); }
|
||||
const char *LookupString (uint32_t index) const;
|
||||
|
||||
int32_t *MapVars[NUM_MAPVARS];
|
||||
BoundsCheckingArray<int32_t *, NUM_MAPVARS> MapVars;
|
||||
|
||||
static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0);
|
||||
static void StaticLoadDefaultModules ();
|
||||
|
|
Loading…
Reference in a new issue