From 9fa4ed8bac10047050f29d3415099e9ea6cc36bf Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Fri, 3 Mar 2017 11:45:39 -0700 Subject: [PATCH 1/5] Add IsNullVector and IsNullString natives Let plugins check if a string or vector passed to a function is their NULL_VECTOR or NULL_STRING. --- core/logic/smn_core.cpp | 23 +++++++++++++++++++++++ plugins/include/core.inc | 16 ++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/core/logic/smn_core.cpp b/core/logic/smn_core.cpp index 8ba74ad7..d12e0fca 100644 --- a/core/logic/smn_core.cpp +++ b/core/logic/smn_core.cpp @@ -759,6 +759,27 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params) return 0; } +static cell_t IsNullVector(IPluginContext *pContext, const cell_t *params) +{ + cell_t *pNullVec = pContext->GetNullRef(SP_NULL_VECTOR); + if (!pNullVec) + return 0; + + cell_t *addr; + pContext->LocalToPhysAddr(params[1], &addr); + + return addr == pNullVec; +} + +static cell_t IsNullString(IPluginContext *pContext, const cell_t *params) +{ + char *str; + if (pContext->LocalToStringNULL(params[1], &str) != SP_ERROR_NONE) + return 0; + + return str == nullptr; +} + REGISTER_NATIVES(coreNatives) { {"ThrowError", ThrowError}, @@ -787,5 +808,7 @@ REGISTER_NATIVES(coreNatives) {"RequireFeature", RequireFeature}, {"LoadFromAddress", LoadFromAddress}, {"StoreToAddress", StoreToAddress}, + {"IsNullVector", IsNullVector}, + {"IsNullString", IsNullString}, {NULL, NULL}, }; diff --git a/plugins/include/core.inc b/plugins/include/core.inc index 315f79de..47f05e1c 100644 --- a/plugins/include/core.inc +++ b/plugins/include/core.inc @@ -143,6 +143,22 @@ struct SharedPlugin public float NULL_VECTOR[3]; /**< Pass this into certain functions to act as a C++ NULL */ public const char NULL_STRING[1]; /**< pass this into certain functions to act as a C++ NULL */ +/** + * Check if the given vector is the NULL_VECTOR. + * + * @param vec The vector to test. + * @return True if NULL_VECTOR, false otherwise. + */ +native bool IsNullVector(const float vec[3]); + +/** + * Check if the given string is the NULL_STRING. + * + * @param str The string to test. + * @return True if NULL_STRING, false otherwise. + */ +native bool IsNullString(const char[] str); + /** * Horrible compatibility shim. */ From 3de269946c8d73724c3fc11936a1069fcc64e78e Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Fri, 3 Mar 2017 11:47:03 -0700 Subject: [PATCH 2/5] Add IsNativeParamNullVector and IsNativeParamNullString natives Lets plugins check if some other plugin passed NULL_VECTOR or NULL_STRING to a native in the native callback. --- core/logic/smn_fakenatives.cpp | 54 ++++++++++++++++++++++++++++++++++ plugins/include/functions.inc | 16 ++++++++++ 2 files changed, 70 insertions(+) diff --git a/core/logic/smn_fakenatives.cpp b/core/logic/smn_fakenatives.cpp index c4c7cf8a..b446d623 100644 --- a/core/logic/smn_fakenatives.cpp +++ b/core/logic/smn_fakenatives.cpp @@ -424,6 +424,58 @@ static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params) return SP_ERROR_NONE; } +static cell_t IsNativeParamNullVector(IPluginContext *pContext, const cell_t *params) +{ + if (!s_curnative || (s_curnative->ctx != pContext)) + { + return pContext->ThrowNativeError("Not called from inside a native function"); + } + + cell_t param = params[1]; + if (param < 1 || param > s_curparams[0]) + { + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param); + } + + int err; + cell_t *addr; + if ((err = s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE) + { + return err; + } + + cell_t *pNullVec = s_curcaller->GetNullRef(SP_NULL_VECTOR); + if (!pNullVec) + { + return 0; + } + + return addr == pNullVec ? 1 : 0; +} + +static cell_t IsNativeParamNullString(IPluginContext *pContext, const cell_t *params) +{ + if (!s_curnative || (s_curnative->ctx != pContext)) + { + return pContext->ThrowNativeError("Not called from inside a native function"); + } + + cell_t param = params[1]; + if (param < 1 || param > s_curparams[0]) + { + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param); + } + + int err; + char *str; + if ((err = s_curcaller->LocalToStringNULL(s_curparams[param], &str)) != SP_ERROR_NONE) + { + return err; + } + + return str == nullptr ? 1 : 0; +} + //tee hee REGISTER_NATIVES(nativeNatives) { @@ -439,5 +491,7 @@ REGISTER_NATIVES(nativeNatives) {"SetNativeArray", SetNativeArray}, {"SetNativeCellRef", SetNativeCellRef}, {"SetNativeString", SetNativeString}, + {"IsNativeParamNullVector", IsNativeParamNullVector}, + {"IsNativeParamNullString", IsNativeParamNullString}, {NULL, NULL}, }; diff --git a/plugins/include/functions.inc b/plugins/include/functions.inc index 1c479618..c4afff93 100644 --- a/plugins/include/functions.inc +++ b/plugins/include/functions.inc @@ -465,6 +465,22 @@ native int GetNativeArray(int param, any[] local, int size); */ native int SetNativeArray(int param, const any[] local, int size); +/** + * Check if the native parameter is the NULL_VECTOR. + * + * @param param Parameter number, starting from 1. + * @return True if NULL_VECTOR, false otherwise. + */ +native bool IsNativeParamNullVector(int param); + +/** + * Check if the native parameter is the NULL_STRING. + * + * @param param Parameter number, starting from 1. + * @return True if NULL_STRING, false otherwise. + */ +native bool IsNativeParamNullString(int param); + /** * Formats a string using parameters from a native. * From 41a9889cddc745f4d6cab72693dbf37be16f504c Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Thu, 4 May 2017 22:56:31 -0600 Subject: [PATCH 3/5] Add Call_PushNullVector and Call_PushNullString Be able to push NULL_[VECTOR|STRING] to a forward or direct function call. The callee can check the parameter using the IsNullVector/IsNullString natives. --- core/logic/ForwardSys.cpp | 92 ++++++++++++++++++++++++++++++++++- core/logic/ForwardSys.h | 2 + core/logic/smn_functions.cpp | 84 ++++++++++++++++++++++++++++++++ plugins/include/functions.inc | 20 ++++++++ public/IForwardSys.h | 19 +++++++- 5 files changed, 214 insertions(+), 3 deletions(-) diff --git a/core/logic/ForwardSys.cpp b/core/logic/ForwardSys.cpp index f7932621..88b00998 100644 --- a/core/logic/ForwardSys.cpp +++ b/core/logic/ForwardSys.cpp @@ -273,7 +273,26 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) */ if (type == Param_String) { - err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags); + // If NULL_STRING was pushed, push the reference to the pubvar of the callee instead. + if (param->isnull) + { + IPluginRuntime *runtime = func->GetParentRuntime(); + uint32_t null_string_idx; + err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx); + + if (!err) + { + cell_t null_string; + err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr); + + if (!err) + err = func->PushCell(null_string); + } + } + else + { + err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags); + } } else if (type == Param_Float || type == Param_Cell) { @@ -281,7 +300,26 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) } else { - err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags); + // If NULL_VECTOR was pushed, push the reference to the pubvar of the callee instead. + if (param->isnull && type == Param_Array) + { + IPluginRuntime *runtime = func->GetParentRuntime(); + uint32_t null_vector_idx; + err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx); + + if (!err) + { + cell_t null_vector; + err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr); + + if (!err) + err = func->PushCell(null_vector); + } + } + else + { + err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags); + } assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef); } } @@ -400,6 +438,7 @@ int CForward::PushCell(cell_t cell) m_params[m_curparam].pushedas = Param_Cell; } + m_params[m_curparam].isnull = false; m_params[m_curparam++].val = cell; return SP_ERROR_NONE; @@ -423,6 +462,7 @@ int CForward::PushFloat(float number) m_params[m_curparam].pushedas = Param_Float; } + m_params[m_curparam].isnull = false; m_params[m_curparam++].val = *(cell_t *)&number; return SP_ERROR_NONE; @@ -481,6 +521,7 @@ void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags) m_params[m_curparam].byref.cells = cells; m_params[m_curparam].byref.flags = flags; m_params[m_curparam].byref.orig_addr = inarray; + m_params[m_curparam].isnull = false; } int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags) @@ -520,6 +561,7 @@ void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags m_params[m_curparam].byref.flags = cp_flags; m_params[m_curparam].byref.orig_addr = inarray; m_params[m_curparam].byref.sz_flags = sz_flags; + m_params[m_curparam].isnull = false; } int CForward::PushString(const char *string) @@ -570,6 +612,52 @@ int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_fla return SP_ERROR_NONE; } +int CForward::PushNullString() +{ + if (m_curparam < m_numparams) + { + if (m_types[m_curparam] == Param_Any) + { + m_params[m_curparam].pushedas = Param_String; + } else if (m_types[m_curparam] != Param_String) { + return SetError(SP_ERROR_PARAM); + } + } else { + if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS) + { + return SetError(SP_ERROR_PARAMS_MAX); + } + m_params[m_curparam].pushedas = Param_String; + } + + m_params[m_curparam++].isnull = true; + + return SP_ERROR_NONE; +} + +int CForward::PushNullVector() +{ + if (m_curparam < m_numparams) + { + if (m_types[m_curparam] == Param_Any) + { + m_params[m_curparam].pushedas = Param_Array; + } else if (m_types[m_curparam] != Param_Array) { + return SetError(SP_ERROR_PARAM); + } + } else { + if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS) + { + return SetError(SP_ERROR_PARAMS_MAX); + } + m_params[m_curparam].pushedas = Param_Array; + } + + m_params[m_curparam++].isnull = true; + + return SP_ERROR_NONE; +} + void CForward::Cancel() { if (!m_curparam) diff --git a/core/logic/ForwardSys.h b/core/logic/ForwardSys.h index 420335c5..6808fae4 100644 --- a/core/logic/ForwardSys.h +++ b/core/logic/ForwardSys.h @@ -55,6 +55,8 @@ public: //IForward virtual unsigned int GetFunctionCount(); virtual ExecType GetExecType(); virtual int Execute(cell_t *result, IForwardFilter *filter); + virtual int PushNullString(); + virtual int PushNullVector(); public: //IChangeableForward virtual bool RemoveFunction(IPluginFunction *func); virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin); diff --git a/core/logic/smn_functions.cpp b/core/logic/smn_functions.cpp index fc4f763b..ef66c493 100644 --- a/core/logic/smn_functions.cpp +++ b/core/logic/smn_functions.cpp @@ -552,6 +552,88 @@ static cell_t sm_CallPushStringEx(IPluginContext *pContext, const cell_t *params return 1; } +static cell_t sm_CallPushNullVector(IPluginContext *pContext, const cell_t *params) +{ + int err = SP_ERROR_NOT_FOUND; + + if (!s_CallStarted) + { + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress"); + } + + if (s_pFunction) + { + // Find the NULL_VECTOR pubvar in the target plugin and push the local address. + IPluginRuntime *runtime = s_pFunction->GetParentRuntime(); + uint32_t null_vector_idx; + err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx); + if (err) + { + return pContext->ThrowNativeErrorEx(err, "Target plugin has no NULL_VECTOR."); + } + + cell_t null_vector; + err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr); + + if (!err) + err = s_pCallable->PushCell(null_vector); + } + else if (s_pForward) + { + err = s_pForward->PushNullVector(); + } + + if (err) + { + s_pCallable->Cancel(); + ResetCall(); + return pContext->ThrowNativeErrorEx(err, NULL); + } + + return 1; +} + +static cell_t sm_CallPushNullString(IPluginContext *pContext, const cell_t *params) +{ + int err = SP_ERROR_NOT_FOUND; + + if (!s_CallStarted) + { + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress"); + } + + if (s_pFunction) + { + // Find the NULL_STRING pubvar in the target plugin and push the local address. + IPluginRuntime *runtime = s_pFunction->GetParentRuntime(); + uint32_t null_string_idx; + err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx); + if (err) + { + return pContext->ThrowNativeErrorEx(err, "Target plugin has no NULL_STRING."); + } + + cell_t null_string; + err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr); + + if (!err) + err = s_pCallable->PushCell(null_string); + } + else if (s_pForward) + { + err = s_pForward->PushNullString(); + } + + if (err) + { + s_pCallable->Cancel(); + ResetCall(); + return pContext->ThrowNativeErrorEx(err, NULL); + } + + return 1; +} + static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params) { int err = SP_ERROR_NOT_RUNNABLE; @@ -668,6 +750,8 @@ REGISTER_NATIVES(functionNatives) {"Call_PushArrayEx", sm_CallPushArrayEx}, {"Call_PushString", sm_CallPushString}, {"Call_PushStringEx", sm_CallPushStringEx}, + {"Call_PushNullVector", sm_CallPushNullVector}, + {"Call_PushNullString", sm_CallPushNullString}, {"Call_Finish", sm_CallFinish}, {"Call_Cancel", sm_CallCancel}, {"RequestFrame", sm_AddFrameAction}, diff --git a/plugins/include/functions.inc b/plugins/include/functions.inc index c4afff93..b9bd2f9c 100644 --- a/plugins/include/functions.inc +++ b/plugins/include/functions.inc @@ -290,6 +290,16 @@ native void Call_PushArray(const any[] value, int size); */ native void Call_PushArrayEx(any[] value, int size, int cpflags); +/** + * Pushes the NULL_VECTOR onto the current call. + * @see IsNullVector + * + * @note Cannot be used before a call has been started. + * + * @error Called before a call has been started. + */ +native void Call_PushNullVector(); + /** * Pushes a string onto the current call. * @@ -317,6 +327,16 @@ native void Call_PushString(const char[] value); */ native void Call_PushStringEx(char[] value, int length, int szflags, int cpflags); +/** + * Pushes the NULL_STRING onto the current call. + * @see IsNullString + * + * @note Cannot be used before a call has been started. + * + * @error Called before a call has been started. + */ +native void Call_PushNullString(); + /** * Completes a call to a function or forward's call list. * diff --git a/public/IForwardSys.h b/public/IForwardSys.h index 3ea98739..9040d549 100644 --- a/public/IForwardSys.h +++ b/public/IForwardSys.h @@ -50,7 +50,7 @@ using namespace SourcePawn; #define SMINTERFACE_FORWARDMANAGER_NAME "IForwardManager" -#define SMINTERFACE_FORWARDMANAGER_VERSION 3 +#define SMINTERFACE_FORWARDMANAGER_VERSION 4 /* * There is some very important documentation at the bottom of this file. @@ -118,6 +118,7 @@ namespace SourceMod cell_t val; ByrefInfo byref; ParamType pushedas; + bool isnull; }; class IForwardFilter @@ -183,6 +184,22 @@ namespace SourceMod * @return Error code, if any. */ virtual int PushArray(cell_t *inarray, unsigned int cells, int flags=0) =0; + + /** + * @brief Pushes the NULL_STRING onto the current call. This will always push the + * correct reference to each function in the forward. + * + * @return Error code, if any. + */ + virtual int PushNullString() =0; + + /** + * @brief Pushes the NULL_VECTOR onto the current call. This will always push the + * correct reference to each function in the forward. + * + * @return Error code, if any. + */ + virtual int PushNullVector() =0; }; /** From e609a33e6d7836576cb9293bd1c4fb600ad91261 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Sat, 22 Jul 2017 23:08:31 +0200 Subject: [PATCH 4/5] Cleanup CForward::Execute using a helper function Flatten out the nesting a bit. --- core/logic/ForwardSys.cpp | 108 +++++++++++++++++++------------------- core/logic/ForwardSys.h | 1 + 2 files changed, 56 insertions(+), 53 deletions(-) diff --git a/core/logic/ForwardSys.cpp b/core/logic/ForwardSys.cpp index 88b00998..f599cb56 100644 --- a/core/logic/ForwardSys.cpp +++ b/core/logic/ForwardSys.cpp @@ -269,59 +269,9 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF)) { /* If we're byref or we're vararg, we always push everything by ref. - * Even if they're byval, we must push them byref. - */ - if (type == Param_String) - { - // If NULL_STRING was pushed, push the reference to the pubvar of the callee instead. - if (param->isnull) - { - IPluginRuntime *runtime = func->GetParentRuntime(); - uint32_t null_string_idx; - err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx); - - if (!err) - { - cell_t null_string; - err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr); - - if (!err) - err = func->PushCell(null_string); - } - } - else - { - err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags); - } - } - else if (type == Param_Float || type == Param_Cell) - { - err = func->PushCellByRef(¶m->val); - } - else - { - // If NULL_VECTOR was pushed, push the reference to the pubvar of the callee instead. - if (param->isnull && type == Param_Array) - { - IPluginRuntime *runtime = func->GetParentRuntime(); - uint32_t null_vector_idx; - err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx); - - if (!err) - { - cell_t null_vector; - err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr); - - if (!err) - err = func->PushCell(null_vector); - } - } - else - { - err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags); - } - assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef); - } + * Even if they're byval, we must push them byref. + */ + err = _ExecutePushRef(func, type, param); } else { @@ -420,6 +370,58 @@ done: return SP_ERROR_NONE; } +int CForward::_ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param) +{ + /* If we're byref or we're vararg, we always push everything by ref. + * Even if they're byval, we must push them byref. + */ + int err; + IPluginRuntime *runtime = func->GetParentRuntime(); + switch (type) + { + case Param_String: + // Normal string was pushed. + if (!param->isnull) + return func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags); + + // If NULL_STRING was pushed, push the reference to the pubvar of the callee instead. + uint32_t null_string_idx; + err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx); + if (err) + return err; + + cell_t null_string; + err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr); + if (err) + return err; + + return func->PushCell(null_string); + + case Param_Float: + case Param_Cell: + return func->PushCellByRef(¶m->val); + + default: + assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef); + // No NULL_VECTOR was pushed. + if (type != Param_Array || !param->isnull) + return func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags); + + // If NULL_VECTOR was pushed, push the reference to the pubvar of the callee instead. + uint32_t null_vector_idx; + err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx); + if (err) + return err; + + cell_t null_vector; + err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr); + if (err) + return err; + + return func->PushCell(null_vector); + } +} + int CForward::PushCell(cell_t cell) { if (m_curparam < m_numparams) diff --git a/core/logic/ForwardSys.h b/core/logic/ForwardSys.h index 6808fae4..b5037b2d 100644 --- a/core/logic/ForwardSys.h +++ b/core/logic/ForwardSys.h @@ -74,6 +74,7 @@ private: CForward(ExecType et, const char *name, const ParamType *types, unsigned num_params); + int _ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param); void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags); void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags); inline int SetError(int err) From 7eef3948b13c61f4dda8866720c6d3f7d11fe1c4 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Fri, 4 Aug 2017 12:52:19 +0200 Subject: [PATCH 5/5] Don't break backwards compatibility with unmanaged forwards Instead of adding new functions to `IForward`, we just allow NULL to be passed to `PushArray` and `PushString`. --- core/logic/ForwardSys.cpp | 17 +++++++++++++++-- core/logic/ForwardSys.h | 4 ++-- core/logic/smn_functions.cpp | 4 ++-- public/IForwardSys.h | 23 ++++++++--------------- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/core/logic/ForwardSys.cpp b/core/logic/ForwardSys.cpp index f599cb56..bc31f7f7 100644 --- a/core/logic/ForwardSys.cpp +++ b/core/logic/ForwardSys.cpp @@ -528,10 +528,17 @@ void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags) int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags) { - /* We don't allow this here */ + /* Push a reference to the NULL_VECTOR pubvar if NULL was passed. */ if (!inarray) { - return SetError(SP_ERROR_PARAM); + /* Make sure this was intentional. */ + if (cells == 3) + { + return PushNullVector(); + } else { + /* We don't allow this here */ + return SetError(SP_ERROR_PARAM); + } } if (m_curparam < m_numparams) @@ -568,6 +575,12 @@ void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags int CForward::PushString(const char *string) { + /* Push a reference to the NULL_STRING pubvar if NULL was passed. */ + if (!string) + { + return PushNullString(); + } + if (m_curparam < m_numparams) { if (m_types[m_curparam] == Param_Any) diff --git a/core/logic/ForwardSys.h b/core/logic/ForwardSys.h index b5037b2d..cd1b3b82 100644 --- a/core/logic/ForwardSys.h +++ b/core/logic/ForwardSys.h @@ -55,8 +55,6 @@ public: //IForward virtual unsigned int GetFunctionCount(); virtual ExecType GetExecType(); virtual int Execute(cell_t *result, IForwardFilter *filter); - virtual int PushNullString(); - virtual int PushNullVector(); public: //IChangeableForward virtual bool RemoveFunction(IPluginFunction *func); virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin); @@ -74,6 +72,8 @@ private: CForward(ExecType et, const char *name, const ParamType *types, unsigned num_params); + int PushNullString(); + int PushNullVector(); int _ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param); void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags); void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags); diff --git a/core/logic/smn_functions.cpp b/core/logic/smn_functions.cpp index ef66c493..792da977 100644 --- a/core/logic/smn_functions.cpp +++ b/core/logic/smn_functions.cpp @@ -580,7 +580,7 @@ static cell_t sm_CallPushNullVector(IPluginContext *pContext, const cell_t *para } else if (s_pForward) { - err = s_pForward->PushNullVector(); + err = s_pForward->PushArray(NULL, 3); } if (err) @@ -621,7 +621,7 @@ static cell_t sm_CallPushNullString(IPluginContext *pContext, const cell_t *para } else if (s_pForward) { - err = s_pForward->PushNullString(); + err = s_pForward->PushString(NULL); } if (err) diff --git a/public/IForwardSys.h b/public/IForwardSys.h index 9040d549..cbd59abb 100644 --- a/public/IForwardSys.h +++ b/public/IForwardSys.h @@ -178,7 +178,8 @@ namespace SourceMod * @brief Pushes an array of cells onto the current call. Different rules than ICallable. * NOTE: On Execute, the pointer passed will be modified according to the copyback rule. * - * @param inarray Array to copy. Cannot be NULL, unlike ICallable's version. + * @param inarray Array to copy. If NULL and cells is 3 pushes a reference to the NULL_VECTOR pubvar to each callee. + * Pushing other number of cells is not allowed, unlike ICallable's version. * @param cells Number of cells to allocate and optionally read from the input array. * @param flags Whether or not changes should be copied back to the input array. * @return Error code, if any. @@ -186,20 +187,12 @@ namespace SourceMod virtual int PushArray(cell_t *inarray, unsigned int cells, int flags=0) =0; /** - * @brief Pushes the NULL_STRING onto the current call. This will always push the - * correct reference to each function in the forward. - * - * @return Error code, if any. - */ - virtual int PushNullString() =0; - - /** - * @brief Pushes the NULL_VECTOR onto the current call. This will always push the - * correct reference to each function in the forward. - * - * @return Error code, if any. - */ - virtual int PushNullVector() =0; + * @brief Pushes a string onto the current call. + * + * @param string String to push. If NULL pushes a reference to the NULL_STRING pubvar to each callee. + * @return Error code, if any. + */ + virtual int PushString(const char *string) = 0; }; /**