From cf590d73e42ee58cc98892c52a6630a265d5cd85 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 15 Nov 2018 09:24:17 +0100 Subject: [PATCH] - extended state caller check to work on CustomInventory items as well Since CallStateChain is a public member in CustomInventory we cannot really be sure that the given state is valid so it needs checking as well. --- .gitignore | 1 + src/info.cpp | 58 +++++++++++++++++++++------------------ src/info.h | 3 ++ src/p_actionfunctions.cpp | 1 + 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 094a390e7a..c725789157 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ /mapfiles_release/*.map .DS_Store /build_vc2017-32 +/build2 diff --git a/src/info.cpp b/src/info.cpp index 5a16060888..87332fd2b2 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -119,6 +119,36 @@ void FState::SetAction(const char *name) } +void FState::CheckCallerType(AActor *self, AActor *stateowner) +{ + 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]); + } + } +} + + bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) { if (ActionFunc != nullptr) @@ -141,33 +171,7 @@ 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]); - } - - } - + CheckCallerType(self, stateowner); if (stateret == nullptr) { diff --git a/src/info.h b/src/info.h index 69912534fa..184313a0eb 100644 --- a/src/info.h +++ b/src/info.h @@ -175,10 +175,13 @@ public: void ClearAction() { ActionFunc = NULL; } void SetAction(const char *name); bool CallAction(AActor *self, AActor *stateowner, FStateParamInfo *stateinfo, FState **stateret); + void CheckCallerType(AActor *self, AActor *stateowner); + static PClassActor *StaticFindStateOwner (const FState *state); static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info); static FString StaticGetStateName(const FState *state); static FRandom pr_statetics; + }; struct FStateLabels; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 60771a469c..6e6e165008 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -169,6 +169,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state) } try { + state->CheckCallerType(actor, this); VMCall(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret); } catch (CVMAbortException &err)