From d5bc0a1fa9bc178d20be8411a1c3b54155486367 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 3 Feb 2018 14:39:01 +0200 Subject: [PATCH] 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 --- src/p_acs.cpp | 56 +++++++++++++++++++-------------------------------- src/p_acs.h | 31 ++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 3e5358a3ce..e36cecde78 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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 ACS_WorldVars; +static BoundsCheckingArray ACS_WorldArrays; // ACS variables with global scope -int32_t ACS_GlobalVars[NUM_GLOBALVARS]; -FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; +BoundsCheckingArray ACS_GlobalVars; +BoundsCheckingArray 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; 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"); } diff --git a/src/p_acs.h b/src/p_acs.h index 4f53ce1a37..7b0d18bd82 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -60,13 +60,32 @@ struct InitIntToZero }; typedef TMap, 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 +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 ACS_GlobalVars; +extern BoundsCheckingArray 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 MapVars; static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0); static void StaticLoadDefaultModules ();