Added a run time check for calling a state action from the wrong actor type.

This can happen if a state that's retrieved with FindState gets used with a different actor type and can lead to hard to trace problems if not checked.
This commit is contained in:
Christoph Oelckers 2018-11-15 09:03:54 +01:00
parent 9f6091519f
commit 0a21d19723

View file

@ -118,6 +118,7 @@ void FState::SetAction(const char *name)
ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name);
}
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret)
{
if (ActionFunc != nullptr)
@ -140,6 +141,34 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
}
try
{
auto CheckType = [=](AActor *check, PType *requiredType)
{
// This should really never happen. Any valid action function must have actor pointers here.
if (!requiredType->isObjectPointer())
{
ThrowAbortException(X_OTHER, "Bad function prototype in function call to %s", ActionFunc->PrintableName.GetChars());
}
auto cls = static_cast<PObjectPointer*>(requiredType)->PointedClass();
if (!check->IsKindOf(cls))
{
ThrowAbortException(X_OTHER, "Invalid class %s in function call to %s. %s expected", check->GetClass()->TypeName.GetChars(), ActionFunc->PrintableName.GetChars(), cls->TypeName.GetChars());
}
};
if (ActionFunc->ImplicitArgs >= 1)
{
auto argtypes = ActionFunc->Proto->ArgumentTypes;
CheckType(self, argtypes[0]);
if (ActionFunc->ImplicitArgs >= 2)
{
CheckType(stateowner, argtypes[1]);
}
}
if (stateret == nullptr)
{
VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0);