检查通过函数指针调用的函数是否具有return语句

时间:2017-12-28 02:11:27

标签: dll function-pointers loadlibrary cdecl extern-c

我们有一个插件系统通过dllning / LoadLibrarying dll / so / dylib调用dll(用户生成的插件)中的函数,然后dlsyming / GetProcAddressing函数,然后将该结果存储在函数指针中。

不幸的是,由于一些错误的示例代码被复制粘贴,所以这些dll中的一些dig没有正确的函数签名,并且不包含return语句。

dll可能包含这个:

extern "C" void Foo() { stuffWithNoReturn(); } // copy-paste from bad code

或者它可能包含:

extern "C" int Foo() { doStuff(); return 1; } // good code

加载dll的应用程序依赖于返回值,但是有一些非常重要的dll没有返回语句。我试图检测这种情况,并警告用户他的插件问题。

这个天真的代码应该解释我尝试做的事情:

typedef int (*Foo_f)(void);
Foo_f func = (Foo_f)getFromDll(); // does dlsym or GetProcAddress depending on platform
int canary = 0x42424242;
canary = (*func)();
if (canary == 0x42424242)
   printf("You idiot, this is the wrong signature!!!\n");
else
   real_return_value = canary;

遗憾的是,在调用具有已知缺陷的dll后,canary包含一个随机值。我天真地假设调用一个没有返回语句的函数会让金丝雀完好无损,但它并没有。

我的下一个想法是编写一些内联汇编程序来调用函数,并在返回时检查eax寄存器,但Visual Studio 2015不再允许x64代码中的__asm()。

我知道没有符合标准的解决方案,因为将函数指针强制转换为错误的类型当然是未定义的行为。但是,如果某人的解决方案至少在使用Visual C ++的64位Windows上运行,或者在MacOS上使用clang的解决方案,我会非常高兴。

1 个答案:

答案 0 :(得分:0)

@Lorinczy Zsigmond是正确的,如果函数执行某些操作但未返回任何内容,则寄存器的内容是未定义的。 然而,我们发现在实践中,什么都不返回的插件也几乎总是空函数,编译为retn 0x0并保持返回寄存器不变。我们可以通过用已知值(0xdeadbeef)喷射rax寄存器并检查它来检测这种情况。