プロジェクトで UBSAN を使用しようとしたところ、修正が不可能と思われる問題が発生しました。このプロジェクトでは、共有ライブラリを介して実装されたプラグイン システムが使用されています。つまり、各プラグインは、プラグイン固有の派生クラスを持つ抽象クラスのインスタンスを返すファクトリ メソッドを提供します。次に、プロジェクトはフォルダー内のすべての共有ライブラリを反復処理し、それらを で開き、dlopen
経由でファクトリ メソッドを取得し、dlsym
使用されるプラグイン インスタンスを作成します。
ただし、UBSAN がスローするインターフェイス メソッドを使用すると、member call on address 0x... which does not point to an object of type '...'
MWE:
foo.h
struct Foo{
virtual int g() = 0;
};
extern "C" Foo* create();
foo.cpp
#include "foo.h"
struct Bar: Foo{
int g(){ return 42; }
};
Foo* create(){
return new Bar();
}
main.cpp
#include "foo.h"
#include <dlfcn.h>
#include <cassert>
int main(){
void* h = dlopen("libfoo.so", RTLD_GLOBAL | RTLD_NOW);
assert(h);
void* c = dlsym(h, "create");
assert(c);
using create_t = Foo*();
Foo* f = reinterpret_cast<create_t*>(c)();
return f->g() != 42;
}
コンパイル:
g++ -shared -fPIC -o libfoo.so foo.cpp
g++ -fsanitize=vptr main.cpp -ldl
./a.out
https://whatofhow.wordpress.com/2015/03/17/odr-rtti-dsoは、これは共有ライブラリの RTTI 情報とバイナリが異なるためであると説明しています。
共有ライブラリで関数をエクスポートし、それをインポートしdlsym
て呼び出しようとすると、非常によく似た問題が発生します。結果は for clang になりcall to function <...> through pointer to incorrect function type '<...>'
ます-fsanitize=function
。
これを解決する方法はありますか?私はClangを使用していないか、遊んで-fvisibility
いないので、ここで何をすべきかわかりません。