Added bounds check for local variables in ACS VM

This commit is contained in:
alexey.lysiuk 2018-01-06 12:13:15 +02:00
parent df0cddb35d
commit 44f01e1dc6
2 changed files with 46 additions and 9 deletions

View file

@ -644,7 +644,7 @@ inline int PitchToACS(DAngle ang)
struct CallReturn struct CallReturn
{ {
CallReturn(int pc, ScriptFunction *func, FBehavior *module, int32_t *locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway) CallReturn(int pc, ScriptFunction *func, FBehavior *module, const ACSLocalVariables &locals, ACSLocalArrays *arrays, bool discard, unsigned int runaway)
: ReturnFunction(func), : ReturnFunction(func),
ReturnModule(module), ReturnModule(module),
ReturnLocals(locals), ReturnLocals(locals),
@ -656,7 +656,7 @@ struct CallReturn
ScriptFunction *ReturnFunction; ScriptFunction *ReturnFunction;
FBehavior *ReturnModule; FBehavior *ReturnModule;
int32_t *ReturnLocals; ACSLocalVariables ReturnLocals;
ACSLocalArrays *ReturnArrays; ACSLocalArrays *ReturnArrays;
int ReturnAddress; int ReturnAddress;
int bDiscardResult; int bDiscardResult;
@ -6967,7 +6967,7 @@ static void SetMarineSprite(AActor *marine, PClassActor *source)
int DLevelScript::RunScript () int DLevelScript::RunScript ()
{ {
DACSThinker *controller = DACSThinker::ActiveThinker; DACSThinker *controller = DACSThinker::ActiveThinker;
int32_t *locals = &Localvars[0]; ACSLocalVariables locals(Localvars);
ACSLocalArrays noarrays; ACSLocalArrays noarrays;
ACSLocalArrays *localarrays = &noarrays; ACSLocalArrays *localarrays = &noarrays;
ScriptFunction *activeFunction = NULL; ScriptFunction *activeFunction = NULL;
@ -7335,7 +7335,6 @@ int DLevelScript::RunScript ()
int i; int i;
ScriptFunction *func; ScriptFunction *func;
FBehavior *module; FBehavior *module;
int32_t *mylocals;
if(pcd == PCD_CALLSTACK) if(pcd == PCD_CALLSTACK)
{ {
@ -7364,9 +7363,9 @@ int DLevelScript::RunScript ()
state = SCRIPT_PleaseRemove; state = SCRIPT_PleaseRemove;
break; break;
} }
mylocals = locals; const ACSLocalVariables mylocals = locals;
// The function's first argument is also its first local variable. // The function's first argument is also its first local variable.
locals = &Stack[sp - func->ArgCount]; locals.Reset(&Stack[sp - func->ArgCount], func->ArgCount + func->LocalCount);
// Make space on the stack for any other variables the function uses. // Make space on the stack for any other variables the function uses.
for (i = 0; i < func->LocalCount; ++i) for (i = 0; i < func->LocalCount; ++i)
{ {
@ -7405,7 +7404,7 @@ int DLevelScript::RunScript ()
sp -= sizeof(CallReturn)/sizeof(int); sp -= sizeof(CallReturn)/sizeof(int);
retsp = &Stack[sp]; retsp = &Stack[sp];
activeBehavior->GetFunctionProfileData(activeFunction)->AddRun(runaway - ret->EntryInstrCount); activeBehavior->GetFunctionProfileData(activeFunction)->AddRun(runaway - ret->EntryInstrCount);
sp = int(locals - &Stack[0]); sp = int(locals.GetPointer() - &Stack[0]);
pc = ret->ReturnModule->Ofs2PC(ret->ReturnAddress); pc = ret->ReturnModule->Ofs2PC(ret->ReturnAddress);
activeFunction = ret->ReturnFunction; activeFunction = ret->ReturnFunction;
activeBehavior = ret->ReturnModule; activeBehavior = ret->ReturnModule;

View file

@ -147,6 +147,44 @@ struct ProfileCollector
int Index; int Index;
}; };
class ACSLocalVariables
{
public:
ACSLocalVariables(TArray<int32_t> &variables)
: memory(&variables[0])
, count(variables.Size())
{
}
void Reset(int32_t *const memory, const size_t count)
{
// TODO: pointer sanity check?
// TODO: constraints on count?
this->memory = memory;
this->count = count;
}
int32_t& operator[](const size_t index)
{
if (index >= count)
{
I_Error("Out of bounds access to local variables in ACS VM");
}
return memory[index];
}
const int32_t *GetPointer() const
{
return memory;
}
private:
int32_t *memory;
size_t count;
};
struct ACSLocalArrayInfo struct ACSLocalArrayInfo
{ {
unsigned int Size; unsigned int Size;
@ -173,7 +211,7 @@ struct ACSLocalArrays
} }
// Bounds-checking Set and Get for local arrays // Bounds-checking Set and Get for local arrays
void Set(int *locals, int arraynum, int arrayentry, int value) void Set(ACSLocalVariables &locals, int arraynum, int arrayentry, int value)
{ {
if ((unsigned int)arraynum < Count && if ((unsigned int)arraynum < Count &&
(unsigned int)arrayentry < Info[arraynum].Size) (unsigned int)arrayentry < Info[arraynum].Size)
@ -181,7 +219,7 @@ struct ACSLocalArrays
locals[Info[arraynum].Offset + arrayentry] = value; locals[Info[arraynum].Offset + arrayentry] = value;
} }
} }
int Get(int *locals, int arraynum, int arrayentry) int Get(ACSLocalVariables &locals, int arraynum, int arrayentry)
{ {
if ((unsigned int)arraynum < Count && if ((unsigned int)arraynum < Count &&
(unsigned int)arrayentry < Info[arraynum].Size) (unsigned int)arrayentry < Info[arraynum].Size)