gpt4 book ai didi

C++ UBSAN 使用派生对象产生误报

转载 作者:行者123 更新时间:2023-12-01 14:20:28 26 4
gpt4 key购买 nike

我想使用 UBSAN(未定义行为 sanitizer ),但发现它完全没有值(value),因为它会报告许多误报。
例如。一个简单的std::make_shared<int>(42);足以触发警告,如

member access within address 0x00000236de70 which does not point to an object of type '_Sp_counted_base'


将此示例简化为 MWE 表明该问题在基类和继承中更为普遍:
例子:
struct Foo{
int f(){ return g(); }
virtual int g() = 0;
};

struct Bar: Foo{
int g(){ return 42; }
};

int main(){
auto f = new Bar();
return f->g();
}
编译 -fsanitize=undefined并观看

example.cpp:15:16: runtime error: member call on address 0x000000726e70 which does not point to an object of type 'Bar'

0x000000726e70: note: object has invalid vptr


https://godbolt.org/z/0UiVtu .
连这些简单的案件都没有妥善处理?我错过了什么吗?我应该如何正确使用 UBSAN 来检查我的代码? (这需要[几乎]没有误报)
编辑:由于 MWE 似乎只适用于 Godbolt,原始代码如下所示:
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/iostreams/stream.hpp>
using MMStream = boost::iostreams::stream<boost::iostreams::mapped_file_source>;

int main(){
MMStream stream;
stream.open("a.out");
return !stream;
}
编译 clang++-8 -fsanitize=undefined -fvisibility=hidden -I /opt/boost_1_64_0/include/ test.cpp /opt/boost_1_64_0/lib/libboost_iostreams.so并运行这会导致错误,例如

runtime error: member call on address 0x00000126ef30 which does not point to an object of type 'boost::detail::sp_counted_base'

最佳答案

在评论后尝试自己回答这个问题并创建另一个 MWE。

TLDR:确保在使用 -fvisibility=hidden 编译时导出所有包含虚函数的类

考虑一个共享库 Foo

foo.h

#define EXPORT __attribute__((visibility("default")))

struct Foo{
virtual int g() = 0;
};

struct Bar: Foo{
int g(){ return 42; }
};

EXPORT Foo* create();

文件
#include "foo.h"
Foo* create(){
return new Bar();
}

编译 clang++-8 foo.cpp -shared -fPIC -o foo.so
和一个使用虚函数链接的可执行文件,但使用 -fvisibility :

主.cpp:
#include "foo.h"

int main(){
Foo* f = create();
return f->g() != 42;
}

编译 clang++-8 -fsanitize=undefined -fvisibility=hidden main.cpp foo.so
这将报告

runtime error: member call on address 0x00000290cea0 which does not point to an object of type 'Foo'



这与 https://bugs.llvm.org/show_bug.cgi?id=39191 中描述的错误相同(感谢@Nikita Petrenko)

摘要:与 fvisibility=hidden未导出的符号(未使用属性 __attribute__((visibility("default"))) 修饰的函数、类在不同的 DSO(例如可执行和共享库)中使用时不被认为是相同的。因此共享库和可执行文件中的基类 Foo 是不同的(它们有不同的 vtables) UBSAN 检测到: 可执行文件“期望”一个对象 witg vtable 为 Exe::Foo 而是得到 Library::Foo
在升压情况下,类 sp_counted_base是罪魁祸首,因为它直到 Boost 1.69 才被导出,它增加了 BOOST_SYMBOL_EXPORT ,所以切换到 Boost 1.69+ 可以解决这个问题。

关于C++ UBSAN 使用派生对象产生误报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57294792/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com