From af93d819c62a930cf3ed2061355b422c5ce4e7c3 Mon Sep 17 00:00:00 2001 From: Adrian-Stefan Mares <36161392+adriansmares@users.noreply.github.com> Date: Sat, 20 Apr 2024 03:56:48 +0200 Subject: [PATCH] Handle `INVALID_FUNCTION` mismatches at plugin boundaries, redux (#2136) --- core/logic/smn_datapacks.cpp | 21 +++++++++++++++++++-- core/logic/smn_fakenatives.cpp | 29 ++++++++++++++++++++++++++++- core/logic/smn_functions.cpp | 30 +++++++++++++++++++++--------- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/core/logic/smn_datapacks.cpp b/core/logic/smn_datapacks.cpp index 3276c30086..9cf2a4a323 100644 --- a/core/logic/smn_datapacks.cpp +++ b/core/logic/smn_datapacks.cpp @@ -244,7 +244,19 @@ static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *para pDataPack->RemoveItem(); } - pDataPack->PackFunction(params[2]); + cell_t funcid = params[2]; + if (pContext->IsNullFunctionId(funcid)) + { + pDataPack->PackFunction(0); + } + else if (funcid <= 0) + { + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); + } + else + { + pDataPack->PackFunction(funcid); + } return 1; } @@ -365,7 +377,12 @@ static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *param return pContext->ThrowNativeError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::Function); } - return pDataPack->ReadFunction(); + cell_t funcid = pDataPack->ReadFunction(); + if (!funcid) + { + return pContext->GetNullFunctionValue(); + } + return funcid; } static cell_t smn_ReadPackCellArray(IPluginContext *pContext, const cell_t *params) diff --git a/core/logic/smn_fakenatives.cpp b/core/logic/smn_fakenatives.cpp index cbbca65e86..e68e527a6d 100644 --- a/core/logic/smn_fakenatives.cpp +++ b/core/logic/smn_fakenatives.cpp @@ -366,6 +366,33 @@ static cell_t SetNativeArray(IPluginContext *pContext, const cell_t *params) return SP_ERROR_NONE; } +static cell_t GetNativeFunction(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); + } + + cell_t funcid = s_curparams[param]; + if (s_curcaller->IsNullFunctionId(funcid)) + { + // see alliedmodders/sourcepawn#912, alliedmodders/sourcemod#2068 + // convert null function to receiver's expected value so equality checks against INVALID_FUNCTION pass + return pContext->GetNullFunctionValue(); + } + else if (funcid <= 0) + { + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); + } + return funcid; +} + static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params) { if (!s_curnative || (s_curnative->ctx != pContext)) @@ -483,7 +510,7 @@ REGISTER_NATIVES(nativeNatives) {"GetNativeArray", GetNativeArray}, {"GetNativeCell", GetNativeCell}, {"GetNativeCellRef", GetNativeCellRef}, - {"GetNativeFunction", GetNativeCell}, + {"GetNativeFunction", GetNativeFunction}, {"GetNativeString", GetNativeString}, {"GetNativeStringLength", GetNativeStringLength}, {"FormatNativeString", FormatNativeString}, diff --git a/core/logic/smn_functions.cpp b/core/logic/smn_functions.cpp index ea1acaba78..41349f96ee 100644 --- a/core/logic/smn_functions.cpp +++ b/core/logic/smn_functions.cpp @@ -228,11 +228,15 @@ static cell_t sm_AddToForward(IPluginContext *pContext, const cell_t *params) } } - IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]); - + cell_t funcid = params[3]; + if (funcid <= 0) + { + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); + } + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(funcid); if (!pFunction) { - return pContext->ThrowNativeError("Invalid function id (%X)", params[3]); + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); } return pForward->AddFunction(pFunction); @@ -265,11 +269,15 @@ static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *param } } - IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]); - + cell_t funcid = params[3]; + if (funcid <= 0) + { + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); + } + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(funcid); if (!pFunction) { - return pContext->ThrowNativeError("Invalid function id (%X)", params[3]); + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); } return pForward->RemoveFunction(pFunction); @@ -327,11 +335,15 @@ static cell_t sm_CallStartFunction(IPluginContext *pContext, const cell_t *param } } - s_pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[2]); - + cell_t funcid = params[2]; + if (funcid <= 0) + { + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); + } + s_pFunction = pPlugin->GetBaseContext()->GetFunctionById(funcid); if (!s_pFunction) { - return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); + return pContext->ThrowNativeError("Invalid function id (%X)", funcid); } s_pCallable = static_cast(s_pFunction);