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:
alexey.lysiuk 2018-02-03 14:39:01 +02:00
parent 0f62cd67a5
commit d5bc0a1fa9
2 changed files with 46 additions and 41 deletions

View file

@ -835,12 +835,12 @@ inline int uallong(const int &foo)
//============================================================================ //============================================================================
// ACS variables with world scope // ACS variables with world scope
int32_t ACS_WorldVars[NUM_WORLDVARS]; static BoundsCheckingArray<int32_t, NUM_WORLDVARS> ACS_WorldVars;
FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; static BoundsCheckingArray<FWorldGlobalArray, NUM_WORLDVARS> ACS_WorldArrays;
// ACS variables with global scope // ACS variables with global scope
int32_t ACS_GlobalVars[NUM_GLOBALVARS]; BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> ACS_GlobalArrays;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
@ -851,21 +851,7 @@ FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS];
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct FACSStackMemory using FACSStackMemory = BoundsCheckingArray<int32_t, STACK_SIZE>;
{
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];
};
struct FACSStack struct FACSStack
{ {
@ -1470,10 +1456,10 @@ void ACSStringPool::UnlockForLevel(int lnum)
void P_MarkWorldVarStrings() void P_MarkWorldVarStrings()
{ {
GlobalACSStrings.MarkStringArray(ACS_WorldVars, countof(ACS_WorldVars)); GlobalACSStrings.MarkStringArray(ACS_WorldVars.Pointer(), ACS_WorldVars.Size());
for (size_t i = 0; i < countof(ACS_WorldArrays); ++i) 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() void P_MarkGlobalVarStrings()
{ {
GlobalACSStrings.MarkStringArray(ACS_GlobalVars, countof(ACS_GlobalVars)); GlobalACSStrings.MarkStringArray(ACS_GlobalVars.Pointer(), ACS_GlobalVars.Size());
for (size_t i = 0; i < countof(ACS_GlobalArrays); ++i) 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; int i;
memset (ACS_WorldVars, 0, sizeof(ACS_WorldVars)); ACS_WorldVars.Fill(0);
for (i = 0; i < NUM_WORLDVARS; ++i) for (i = 0; i < NUM_WORLDVARS; ++i)
{ {
ACS_WorldArrays[i].Clear (); ACS_WorldArrays[i].Clear ();
} }
if (alsoglobal) if (alsoglobal)
{ {
memset (ACS_GlobalVars, 0, sizeof(ACS_GlobalVars)); ACS_GlobalVars.Fill(0);
for (i = 0; i < NUM_GLOBALVARS; ++i) for (i = 0; i < NUM_GLOBALVARS; ++i)
{ {
ACS_GlobalArrays[i].Clear (); ACS_GlobalArrays[i].Clear ();
@ -1726,10 +1712,10 @@ static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t co
void P_ReadACSVars(FSerializer &arc) void P_ReadACSVars(FSerializer &arc)
{ {
ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars"); ReadVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars");
ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars"); ReadVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars");
ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays"); ReadArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays");
ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays"); ReadArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.ReadStrings(arc, "acsglobalstrings"); GlobalACSStrings.ReadStrings(arc, "acsglobalstrings");
} }
@ -1741,10 +1727,10 @@ void P_ReadACSVars(FSerializer &arc)
void P_WriteACSVars(FSerializer &arc) void P_WriteACSVars(FSerializer &arc)
{ {
WriteVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars"); WriteVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars");
WriteVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars"); WriteVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars");
WriteArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays"); WriteArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays");
WriteArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays"); WriteArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.WriteStrings(arc, "acsglobalstrings"); GlobalACSStrings.WriteStrings(arc, "acsglobalstrings");
} }

View file

@ -60,13 +60,32 @@ struct InitIntToZero
}; };
typedef TMap<int32_t, int32_t, THashTraits<int32_t>, InitIntToZero> FWorldGlobalArray; typedef TMap<int32_t, int32_t, THashTraits<int32_t>, InitIntToZero> FWorldGlobalArray;
// ACS variables with world scope // Type of elements count is unsigned int instead of size_t to match ACSStringPool interface
extern int32_t ACS_WorldVars[NUM_WORLDVARS]; template <typename T, unsigned int N>
extern FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; 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 // ACS variables with global scope
extern int32_t ACS_GlobalVars[NUM_GLOBALVARS]; extern BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
extern FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; extern BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> ACS_GlobalArrays;
#define LIBRARYID_MASK 0xFFF00000 #define LIBRARYID_MASK 0xFFF00000
#define LIBRARYID_SHIFT 20 #define LIBRARYID_SHIFT 20
@ -359,7 +378,7 @@ public:
ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); } ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); }
const char *LookupString (uint32_t index) const; 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 FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0);
static void StaticLoadDefaultModules (); static void StaticLoadDefaultModules ();