From 0a21d1972363cea3452ce2e7da4653e21155ec2f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 15 Nov 2018 09:03:54 +0100 Subject: [PATCH] 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. --- src/info.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/info.cpp b/src/info.cpp index ffae037f74..5a16060888 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -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(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);