From 71b840e70a16705519db48949036a5de793fae0e Mon Sep 17 00:00:00 2001 From: Dr!fter Date: Tue, 30 Aug 2016 10:58:04 -0400 Subject: [PATCH] Fix overriding functions with objects crashing. --- sourcemod/scripting/include/dhooks.inc | 7 ++- vfunc_call.h | 71 ++++++++++++++++++-------- vhook.cpp | 2 +- vhook.h | 2 +- 4 files changed, 57 insertions(+), 25 deletions(-) diff --git a/sourcemod/scripting/include/dhooks.inc b/sourcemod/scripting/include/dhooks.inc index 571a0aa..6bf8211 100644 --- a/sourcemod/scripting/include/dhooks.inc +++ b/sourcemod/scripting/include/dhooks.inc @@ -84,8 +84,11 @@ enum MRESReturn enum DHookPassFlag { - DHookPass_ByVal = (1<<0), - DHookPass_ByRef = (1<<1) + DHookPass_ByVal = (1<<0), /**< Passing by value */ + DHookPass_ByRef = (1<<1), /**< Passing by reference */ + DHookPass_ODTOR = (1<<2), /**< Object has a destructor */ + DHookPass_OCTOR = (1<<3), /**< Object has a constructor */ + DHookPass_OASSIGNOP = (1<<4), /**< Object has an assignment operator */ }; typeset ListenCB diff --git a/vfunc_call.h b/vfunc_call.h index 39943e3..f436b68 100644 --- a/vfunc_call.h +++ b/vfunc_call.h @@ -3,35 +3,30 @@ #include "vhook.h" #include "extension.h" +#include "natives.h" #define PARAMINFO_SWITCH(passType) \ - paramInfo[i].flags = dg->params.at(i).flag; \ + paramInfo[i].flags = dg->params.at(i).flags; \ paramInfo[i].size = dg->params.at(i).size; \ paramInfo[i].type = passType; #define VSTK_PARAM_SWITCH(paramType) \ if(paramStruct->isChanged[i]) \ { \ - *(paramType *)vptr = (paramType)(paramStruct->newParams[i]); \ + *(paramType *)vptr = *(paramType *)newAddr; \ } \ else \ { \ - *(paramType *)vptr = (paramType)(paramStruct->orgParams[i]); \ + *(paramType *)vptr = *(paramType *)orgAddr; \ } \ if(i + 1 != dg->params.size()) \ { \ vptr += dg->params.at(i).size; \ } \ break; -#define VSTK_PARAM_SWITCH_FLOAT() \ - if(paramStruct->isChanged[i]) \ - { \ - *(float *)vptr = *(float *)(paramStruct->newParams[i]); \ - } \ - else \ - { \ - *(float *)vptr = *(float *)(paramStruct->orgParams[i]); \ - } \ + +#define VSTK_PARAM_SWITCH_OBJECT() \ + memcpy(vptr, objAddr, dg->params.at(i).size); \ if(i + 1 != dg->params.size()) \ { \ vptr += dg->params.at(i).size; \ @@ -71,8 +66,14 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) { vptr += sizeof(void *); paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size()); + for(int i = 0; i < (int)dg->params.size(); i++) { + size_t offset = GetParamOffset(paramStruct, i); + + void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset); + void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset); + switch(dg->params.at(i).type) { case HookParamType_Int: @@ -83,10 +84,10 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) VSTK_PARAM_SWITCH(cell_t); case HookParamType_Float: PARAMINFO_SWITCH(PassType_Float); - VSTK_PARAM_SWITCH_FLOAT(); + VSTK_PARAM_SWITCH(float); case HookParamType_String: PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH(int); + VSTK_PARAM_SWITCH(string_t); case HookParamType_StringPtr: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(string_t *); @@ -102,6 +103,12 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) case HookParamType_Edict: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(edict_t *); + case HookParamType_Object: + { + void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset); + PARAMINFO_SWITCH(PassType_Object); + VSTK_PARAM_SWITCH_OBJECT(); + } default: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(void *); @@ -110,7 +117,7 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) } T ret = 0; - + if(dg->returnType == ReturnType_Void) { pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.size()); @@ -160,7 +167,12 @@ SDKVector CallVFunction(DHooksCallback *dg, HookParamsStruct *paramSt paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size()); for(int i = 0; i < (int)dg->params.size(); i++) { - switch(dg->params.at(i).type) + size_t offset = GetParamOffset(paramStruct, i); + + void *orgAddr = *(void **)((intptr_t)paramStruct->orgParams + offset); + void *newAddr = *(void **)((intptr_t)paramStruct->newParams + offset); + + switch (dg->params.at(i).type) { case HookParamType_Int: PARAMINFO_SWITCH(PassType_Basic); @@ -170,10 +182,10 @@ SDKVector CallVFunction(DHooksCallback *dg, HookParamsStruct *paramSt VSTK_PARAM_SWITCH(cell_t); case HookParamType_Float: PARAMINFO_SWITCH(PassType_Float); - VSTK_PARAM_SWITCH_FLOAT(); + VSTK_PARAM_SWITCH(float); case HookParamType_String: PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH(int); + VSTK_PARAM_SWITCH(string_t); case HookParamType_StringPtr: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(string_t *); @@ -189,6 +201,12 @@ SDKVector CallVFunction(DHooksCallback *dg, HookParamsStruct *paramSt case HookParamType_Edict: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(edict_t *); + case HookParamType_Object: + { + void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset); + PARAMINFO_SWITCH(PassType_Object); + VSTK_PARAM_SWITCH_OBJECT(); + } default: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(void *); @@ -240,7 +258,12 @@ string_t CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStru paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size()); for(int i = 0; i < dg->params.size(); i++) { - switch(dg->params.at(i).type) + size_t offset = GetParamOffset(paramStruct, i); + + void *orgAddr = *(void **)((intptr_t)paramStruct->orgParams + offset); + void *newAddr = *(void **)((intptr_t)paramStruct->newParams + offset); + + switch (dg->params.at(i).type) { case HookParamType_Int: PARAMINFO_SWITCH(PassType_Basic); @@ -250,10 +273,10 @@ string_t CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStru VSTK_PARAM_SWITCH(cell_t); case HookParamType_Float: PARAMINFO_SWITCH(PassType_Float); - VSTK_PARAM_SWITCH_FLOAT(); + VSTK_PARAM_SWITCH(float); case HookParamType_String: PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH(int); + VSTK_PARAM_SWITCH(string_t); case HookParamType_StringPtr: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(string_t *); @@ -269,6 +292,12 @@ string_t CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStru case HookParamType_Edict: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(edict_t *); + case HookParamType_Object: + { + void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset); + PARAMINFO_SWITCH(PassType_Object); + VSTK_PARAM_SWITCH_OBJECT(); + } default: PARAMINFO_SWITCH(PassType_Basic); VSTK_PARAM_SWITCH(void *); diff --git a/vhook.cpp b/vhook.cpp index 9443e83..2265aea 100644 --- a/vhook.cpp +++ b/vhook.cpp @@ -44,7 +44,7 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem for(int i = this->callback->params.size() -1; i >= 0; i--) { - protoInfo.AddParam(this->callback->params.at(i).size, this->callback->params.at(i).pass_type, this->callback->params.at(i).flag, NULL, NULL, NULL, NULL); + protoInfo.AddParam(this->callback->params.at(i).size, this->callback->params.at(i).pass_type, PASSFLAG_BYVAL, NULL, NULL, NULL, NULL);//This seems like we need to do something about it at some point... } if(this->callback->returnType == ReturnType_Void) diff --git a/vhook.h b/vhook.h index 050be4c..415031e 100644 --- a/vhook.h +++ b/vhook.h @@ -82,7 +82,7 @@ struct ParamInfo { HookParamType type; size_t size; - unsigned int flag; + unsigned int flags; SourceHook::PassInfo::PassType pass_type; };