Skip to content

FunctionHook - undefined behaviour on remove #1826

@jhett12321

Description

@jhett12321

The current FunctionHook wrapper does not update trampoline addresses when they are deleted, which causes later function hooks to attempt to call the deleted function hook address.

Here is some simple repro code:

    LOG_WARNING("Hook Init");
    static NWNXLib::Hooks::Hook pHook1 =
        Hooks::HookFunction(&CAppManager::GetDungeonMasterEXERunning,
        +[](CAppManager *pAppManager) -> int32_t
        {
            LOG_WARNING("Hook 1 called");
            return pHook1->CallOriginal<int32_t>(pAppManager);
        });

    static NWNXLib::Hooks::Hook pHook2 =
    Hooks::HookFunction(&CAppManager::GetDungeonMasterEXERunning,
    +[](CAppManager *pAppManager) -> int32_t
    {
        LOG_WARNING("Hook 2 called");
        return pHook2->CallOriginal<int32_t>(pAppManager);
    });

    static NWNXLib::Hooks::Hook pHook3 =
    Hooks::HookFunction(&CAppManager::GetDungeonMasterEXERunning,
    +[](CAppManager *pAppManager) -> int32_t
    {
        LOG_WARNING("Hook 3 called");
        return pHook3->CallOriginal<int32_t>(pAppManager);
    });

    LOG_WARNING("Hook call");
    NWNXLib::API::Globals::AppManager()->GetDungeonMasterEXERunning();

    LOG_WARNING("Hook destroy 1,2");
    pHook1.reset();
    pHook2.reset();

    LOG_WARNING("Hook Call after dispose");
    NWNXLib::API::Globals::AppManager()->GetDungeonMasterEXERunning();

Expected behaviour would be something like the following:

[23:06:16] [NWNX_Test] Hook Init
[23:06:16] [NWNX_Test] Hook call
[23:06:16] [NWNX_Test] Hook 3 called                                                                                                                                                                                                           
[23:06:16] [NWNX_Test] Hook 2 called                                                                                                                                                                                                           
[23:06:16] [NWNX_Test] Hook 1 called                                                                                                                                                                                                           
[23:06:16] [NWNX_Test] Hook destroy 1,2                                                                                                                                                                                                        
[23:06:16] [NWNX_Test] Hook Call after dispose                                                                                                                                                                                                 
[23:06:16] [NWNX_Test] Hook 3 called  

Instead, you get undefined behaviour after the first 2 hooks are disposed due to "Hook 3" still pointing to the deleted hook:

[23:12:57] [NWNX_Test] Hook Init                                                                                                                                                                                                               
[23:12:57] [NWNX_Test] Hook call
[23:12:57] [NWNX_Test] Hook 3 called                                                                                                                                                                                                           
[23:12:57] [NWNX_Test] Hook 2 called                                                                                                                                                                                                           
[23:12:57] [NWNX_Test] Hook 1 called
[23:12:57] [NWNX_Test] Hook destroy 1,2                                                                                                                                                                                                        
[23:12:57] [NWNX_Test] Hook Call after dispose                                                                                                                                                                                                 
NWNX Signal Handler:                                                                                                                                                                                                                                              
==============================================================
NWNX 8193.37-15 (e46d1db822) has crashed. Fatal error: Segmentation fault (11).                                                                                                                                                                                   
Please file a bug at https://github.com/nwnxee/unified/issues                                                                                                                                                                                                     
==============================================================   

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions