问题标签 [ubsan]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - UBSan:boost::program_options 与 std::string
我们目前正在调查我们的程序中可能存在的未定义行为,该行为由 clang7 UBSan 结合 boost::program_option 来自 boost 1.69.0 进行标记。我们创建了以下工作示例,我们可以使用它来编译和运行clang++ -std=c++17 -fsanitize=undefined -fno-omit-frame-pointer -lboost_program_options debug.cpp && UBSAN_OPTIONS=print_stacktrace=1 ./a.out
我们得到以下输出:
正如我们所看到的,它运行良好(test_string
之后具有正确的值)。我们研究了 boost::program_options 和 boost::any 并发现了以下内容: 在program_options::typed_value::notify()
(#2) 中,我们得到一个 boost::any 并通过调用 boost::any_cast() 将其转换为应有的类型。
考虑到 clang 的输出 (downcast of address 0x5638e42892e0 which does not point to an object of type 'any::holder<typename remove_cv<basic_string<char, char_traits<char>, allocator<char> > >::type>' (aka 'holder<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >')
和object is of type 'boost::any::holder<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
),我们只能得出结论,这个 boost::any 实例实际上拥有正确的成员......在这种情况下,向下转换应该是合法的。
然而,UBSan 表示不会出现误报。
有趣的是,如果没有 program_options 混合,我们将无法重现此错误:
因此,我们怀疑(预编译的)program_options 可能会以某种方式与 std::string 类型混淆。
顺便说一句,valgrind 不会为这两个程序报告任何错误。
有任何想法吗?
我们已经在 Arch linux(boost 1.69.0-1,clang 7.0.1-1 使用 libstd++)和 CentOS 7.6(clang 7.0.0 使用 libc++ 和 boost 1.69.0 使用相同的 clang 构建)上尝试过这个。
c++ - 带有 MinGW-w64 的 Clang 8:如何使用地址和 UB 消毒剂?
Clang 8 发行说明有这样一条有希望的行:
- 允许在 MinGW 上使用 Address Sanitizer 和 Undefined Behavior Sanitizer。
但是,我无法弄清楚如何正确使用它们。
我将 Clang 8.0.0 与 MSYS2 MinGW GCC 一起使用。确切的细节在问题的底部。
我正在尝试编译以下最少的代码:
1.cpp
以下是结果-fsanitize=address
:
这是-fsanitize=undefined
:
以下是它在Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\
哪里查找库的内容:
这看起来不对,因为 MinGW GCC 通常与.a
库一起使用,而不是.lib
.
我试图从该目录手动链接各种库。
对于 asan,我设法摆脱了编译器错误,但 asan 本身似乎没有发出任何诊断信息:
对于 ubsan,我尝试链接到clang_rt.ubsan_standalone-x86_64.lib
,但得到了更多未定义的引用和几个Warning: corrupt .drectve at end of def file
.
我做了一些研究Warning: corrupt .drectve at end of def file
,这个问题表明这意味着我正在链接不兼容的 MSVC 库。
这里发生了什么?我应该如何使用 asan 和 ubsan?
上面的所有命令都是从 MSYS2 终端运行的,在 Windows 7 x64 上运行。
我的目标是 x86_64 并使用 MSYS2 中可用的最新 GCC:
MSYS2 的 Clang 似乎没有捆绑 asan 和 ubsan 库,所以我使用的是llvm.org的官方版本:
我正在使用-target x86_64-w64-windows-gnu
,因为否则 Clang 会尝试使用我没有的 MSVC 安装。这个特定的三元组是 MSYS2 clang 报告的--version
。
ubsan - UBSan:存储到未对齐的地址;有什么问题,我应该关心吗
我一直在 UBSan 下运行一些代码,发现了一个我以前从未见过的错误:
(g++-7.3.0,Ubuntu 18.04,标志 -fsanitize=address -fsanitize=undefined)
这个错误是什么意思?这真的是一个错误吗(它在标准库中,所以不会太糟糕,对吧?),我应该关心它吗?
c++ - C++ UBSAN 对派生对象产生误报
我想使用 UBSAN(未定义的行为消毒剂),但发现它完全没有价值,因为它会报告许多误报。
例如,一个简单std::make_shared<int>(42);
的就足以触发警告,例如
地址 0x00000236de70 内的成员访问,它不指向“_Sp_counted_base”类型的对象
将此示例简化为 MWE 表明问题在基类和继承方面更为普遍:
例子:
编译-fsanitize=undefined
并观看
example.cpp:15:16:运行时错误:对地址 0x000000726e70 的成员调用,它不指向“Bar”类型的对象
0x000000726e70:注意:对象的 vptr 无效
请参阅https://godbolt.org/z/0UiVtu。
连这些简单的案件都处理不好怎么办?我错过了什么吗?我应该如何正确使用 UBSAN 来检查我的代码?(这需要[几乎]没有误报)
编辑:似乎 MWE 仅适用于 Godbolt,原始代码如下所示:
编译clang++-8 -fsanitize=undefined -fvisibility=hidden -I /opt/boost_1_64_0/include/ test.cpp /opt/boost_1_64_0/lib/libboost_iostreams.so
并运行会导致错误,例如
运行时错误:对地址 0x00000126ef30 的成员调用,它不指向“boost::detail::sp_counted_base”类型的对象
c++ - gcc/clang UBSan 运行时错误——误报?
我有一个小项目(大约 2k 行代码),它可以使用 clang 和 gcc 进行编译。gcc 给出以下错误(-O0 优化级别):
它由一段简单的代码触发:
clang++ 也给出了“成员调用......”,但在不同的代码段上。
我无法在一个简短的示例中重现它。EnableClone
几乎是独立的——我尝试使用 full 创建一个最小示例cloneable.hpp
,但无法以这种方式重现 UBSan 错误。
我怀疑 ODR 是这种情况,所以我添加-Wodr
了编译标志,但它什么也没给我。
我尝试使用 gdb 来检查 vptrs,但我不完全确定,但它们似乎没问题:
EnableClone
实现:https ://github.com/npetrenko/curse_dim/blob/4c80eccf637bf351ef708c04c432a5c18e41dcfd/bellman/include/bellman/cloneable.hpp
如果我向 ICloneable 添加一个具有副作用的析构函数
然后DiscreteQFuncEst
在 gcc 的 UBSan 抱怨的示例中打印预期的破坏结果(-O0,并且 ICloneable 是一个虚拟基础,所以我希望虚拟 ptr 遍历没有被优化)。
我发现了几个报告误报结果的错误报告,例如: https ://bugs.llvm.org/show_bug.cgi?id=39191
不过,与报告不同的是,我不会弄乱可见性,而且我编写的所有库都是静态链接的。
这是假阳性吗?如果没有,我怎么可能调试这个?还是我能以某种方式确保自己确实是 UB?
谢谢!
重现步骤:
并查看 README.md
更新:我设法将它剥离到几乎为零。我不知道为什么我以前没有成功。签出 repo 可能更方便,我只是从那里复制代码。
造成麻烦的类:
UBSan 错误触发代码示例:
编译:
(替换g++
为clang++
让 UBSan 开心)
g++ (GCC) 9.1.0
铿锵声版本 8.0.1
c++ - 将 UBSAN 与动态加载的共享库一起使用
我试图在一个项目中使用 UBSAN,但遇到了一个似乎无法解决的问题:该项目使用了一个通过共享库实现的插件系统。也就是说,每个插件都提供了一个工厂方法,该方法返回一个带有插件特定派生类的抽象类的实例。然后该项目遍历文件夹中的所有共享库,使用 打开它们dlopen
,通过获取工厂方法dlsym
并创建插件实例,然后使用该实例。
然而,在使用任何接口方法 UBSAN 抛出member call on address 0x... which does not point to an object of type '...'
MWE:
foo.h
foo.cpp
主文件
编译:
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
并尝试调用它。结果将是call to function <...> through pointer to incorrect function type '<...>'
for -fsanitize=function
clang。
有没有办法解决这个问题?我没有使用 Clang 或玩,-fvisibility
所以不知道在这里做什么。
nsdate - 未对齐的指针与 std::shared_ptr 一起使用取消引用
我正在一个遗留代码库中工作,其中包含大量使用手动保留/释放编写的 Objective-C++。内存使用大量 C++ 进行管理,并在调用包含对象的std::shared_ptr<NSMyCoolObjectiveCPointer>
构造时传入了一个合适的删除器。release
这似乎很好用;但是,当启用 UBSan 时,它会抱怨指针未对齐,通常是在取消引用 shared_ptrs 以执行某些工作时。
我已经搜索了线索和/或解决方案,但是很难找到有关 Objective-C 对象指针来龙去脉的技术讨论,更难找到有关 Objective-C++ 的任何讨论,所以我在这里。
这是一个完整的 Objective-C++ 程序,它演示了我的问题。当我使用 UBSan 在我的 Macbook 上运行此程序时,我在以下位置遇到了一个未对齐的指针问题shared_ptr::operator*
:
我在电话中得到了这个DateImpl::description
:
我怀疑使用&*
to “cast” shared_ptr<NSDate>
to an 有问题NSDate*
。我想我可以通过使用.get()
shared_ptr 来解决这个问题,但我真的很好奇发生了什么。感谢您的任何反馈或提示!
gcc - 如何摆脱 GCC 提供的自动添加的库?
我正在通过 gcc 编译 main.c 文件,并启用了 sanitizer 选项。
因此,链接器命令在其参数列表中包含“-lubsan”选项。
需要说,我没有明确地为 gcc 提供“-lubsan”选项。
此外,我反对使用它。
所以,问题是:“如何摆脱这种自动添加的选项?
是否可以在不分离编译和链接命令的情况下做到这一点?”。
main.c 文件的内容:
build_gcc_host.sh 文件内容:
PS 如果使用“-nostdlib”选项,则不会添加“-lubsan”,但我确实需要“stdlib”。
我根本不需要自动添加“-lubsan”。
c++ - 使用 boost 序列化时的地址清理程序错误
我最近尝试使用 boost 序列化来序列化一个包含 astd::vector<std::unique_ptr<Base>>>
作为成员的类。根据 boost 文档(https://www.boost.org/doc/libs/1_71_0/libs/serialization/doc/serialization.html#derivedpointersregister_type
),我们必须使用归档的方法注册派生类以进行序列化好好工作。一切确实构建并运行良好,但地址清理程序构建(在我们的 CI 中运行)失败并出现以下错误:
在检查其中的内容后void_cast.hpp
,我发现了以下构造函数中有问题的代码void_caster_primitive
:
从代码和注释来看,这个表达式是在计算Base
类的位移Derived
。但是,它仍然看起来很神奇,尤其是在将(看似)随机数投射到Base
指针时。如果有人能解释为什么这实际上计算了位移,那就太好了。
编辑:这是一个使用上面显示的位移计算方法的简单示例:https : //godbolt.org/z/Bmp7zH 如果关闭消毒剂,它会编译并运行,但打开后,程序会异常终止。
这也是在编译器资源管理器上重现 SEGV 的原始问题的尝试:https ://godbolt.org/z/w8ZNx8但是,链接 boost 序列化似乎不起作用,而且如果我打开 sanitizer 选项,构建有时会超时。
c++ - 如何修复此 C++ UBSAN vptr 运行时错误(运行时错误:成员调用地址)
我在我的项目中启用了 ubsan 测试 (-fsanitize=undefined) 并发现了一些 ubsan 运行时错误。谁能帮我找出这里失败的原因?如何在 GCC 和 Clang 上解决这个问题?
这是包含 lib.h 和 lib.cpp 的 lib.so 模块。
lib.h:
lib.cpp:
这是将调用 lib.so 模块的可执行模块:
主文件
构建模块(lib.so 和 main)并运行 main,存在运行时错误:
build_run_gcc.sh
错误: