Help us help you
Environment
- Operating System version: Ubuntu 20.04.3 LTS
- Game/AppID (with version if applicable): Half-Life 2: Deathmatch / 320
- Current SourceMod version: 1.11
- Current SourceMod snapshot: 6842
- Current Metamod: Source snapshot: 1.11.0-dev+1145
Description
DHooks2 showcases a possible DHooksCallback::plugin_callback NULL pointer de-reference crash sequence when plugins that use it (properly setting hook at OnPluginStart and having double-checked gamedata) get reloaded. Concretely I repeatedly recompile one of them and have it reloaded by restarting map (doing both steps once each new map session), rather than via sm plugins reload (which I didn't test yet). The crash has enough chance to happen each map reload.
Reference plugin.
Recompiled DHooks info
I recompiled DHooks with some debug logging stataments (targetting error logs, for my own convenience) showing relevant related data (callback addresses, offsets, etc.), manually preventing the crash as well, and resulting logs are attached below. Here are the exact testing changes:
+++ b/extensions/dhooks/dynhooks_sourcepawn.cpp
@@ -472,6 +472,8 @@ ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour)
CDynamicHooksSourcePawn::CDynamicHooksSourcePawn(HookSetup *setup, CHook *pDetour, IPluginFunction *pCallback, bool post)
{
+ g_pSM->LogError(myself, "CDynamicHooksSourcePawn called for this = %p with pCallback = %p (plugin callback)",
+ this, pCallback);
this->params = setup->params;
+++ b/extensions/dhooks/listeners.cpp
@@ -75,6 +75,9 @@ void DHooksEntityListener::CleanupListeners(IPluginContext *pContext)
IPluginFunction *cb = manager->callback->plugin_callback;
if (pContext == NULL || (cb && pContext == cb->GetParentRuntime()->GetDefaultContext()))
{
+ g_pSM->LogError(myself, "DHooksEntityListener::CleanupListeners cleaning DHooksCallback at %p"
+ " (plugin_callback = %p; offset = %i)", manager->callback, manager->callback->plugin_callback,
+ manager->callback->offset);
manager->callback->plugin_callback = nullptr;
+++ b/extensions/dhooks/vhook.cpp
@@ -148,7 +148,8 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem
this->callback->post = post;
this->callback->hookType = setup->hookType;
this->callback->params = setup->params;
+ g_pSM->LogError(myself, "DHooksManager constructor of instance %p called! (callback = %p; plugincb = %p; offset = %i)",
+ this, this->callback, plugincb, setup->offset);
@@ -411,6 +412,12 @@ void *Callback(DHooksCallback *dg, void **argStack)
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
+ if (dg->plugin_callback == NULL)
+ {
+ g_pSM->LogError(myself, "dg->plugin_callback was NULL!!! (dg = %p; offset = %i)", dg, dg->offset);
+ return NULL;
+ }
+
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
}
if(dg->returnType != ReturnType_Void)
Important: notice how the logs show several map reloads and after one happens, the dg->plugin_callback was NULL!!! log arises, and its dg object has been cleared early at DHooksEntityListener::CleanupListeners.
It seems to me that the calling stack that triggers this is the following:
DHooksManager::DHooksManager -> MakeHandler(ReturnType type) -> GenerateThunk(ReturnType type) -> Callback(DHooksCallback *dg, void **argStack)

Notice that at DHooksManager, the plugin_callback is only assigned after the MakeHandler call.
Logs
errors_20220107.log
crash_j6efozxcjard.zip
Help us help you
Environment
Description
DHooks2 showcases a possible
DHooksCallback::plugin_callbackNULLpointer de-reference crash sequence when plugins that use it (properly setting hook atOnPluginStartand having double-checked gamedata) get reloaded. Concretely I repeatedly recompile one of them and have it reloaded by restarting map (doing both steps once each new map session), rather than viasm plugins reload(which I didn't test yet). The crash has enough chance to happen each map reload.Reference plugin.
Recompiled DHooks info
I recompiled DHooks with some debug logging stataments (targetting error logs, for my own convenience) showing relevant related data (callback addresses, offsets, etc.), manually preventing the crash as well, and resulting logs are attached below. Here are the exact testing changes:
Important: notice how the logs show several map reloads and after one happens, the
dg->plugin_callback was NULL!!!log arises, and itsdgobject has been cleared early atDHooksEntityListener::CleanupListeners.It seems to me that the calling stack that triggers this is the following:
DHooksManager::DHooksManager -> MakeHandler(ReturnType type) -> GenerateThunk(ReturnType type) -> Callback(DHooksCallback *dg, void **argStack)Notice that at
DHooksManager, theplugin_callbackis only assigned after theMakeHandlercall.Logs
errors_20220107.log
crash_j6efozxcjard.zip