mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 15:22:08 +00:00
Added bounds check for local variables in ACS VM
This commit is contained in:
parent
df0cddb35d
commit
44f01e1dc6
2 changed files with 46 additions and 9 deletions
|
@ -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;
|
||||||
|
|
42
src/p_acs.h
42
src/p_acs.h
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue