问题标签 [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.

0 投票
0 回答
241 浏览

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 构建)上尝试过这个。

0 投票
2 回答
2625 浏览

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

0 投票
1 回答
1655 浏览

ubsan - UBSan:存储到未对齐的地址;有什么问题,我应该关心吗

我一直在 UBSan 下运行一些代码,发现了一个我以前从未见过的错误:

(g++-7.3.0,Ubuntu 18.04,标志 -fsanitize=address -fsanitize=undefined)

这个错误是什么意思?这真的是一个错误吗(它在标准库中,所以不会糟糕,对吧?),我应该关心它吗?

0 投票
1 回答
2554 浏览

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”类型的对象

0 投票
0 回答
309 浏览

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

0 投票
1 回答
324 浏览

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=functionclang。

有没有办法解决这个问题?我没有使用 Clang 或玩,-fvisibility所以不知道在这里做什么。

0 投票
2 回答
230 浏览

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 来解决这个问题,但我真的很好奇发生了什么。感谢您的任何反馈或提示!

0 投票
0 回答
53 浏览

gcc - 如何摆脱 GCC 提供的自动添加的库?

我正在通过 gcc 编译 main.c 文件,并启用了 sanitizer 选项。

因此,链接器命令在其参数列表中包含“-lubsan”选项。

需要说,我没有明确地为 gcc 提供“-lubsan”选项。

此外,我反对使用它。

所以,问题是:“如何摆脱这种自动添加的选项?

是否可以在不分离编译和链接命令的情况下做到这一点?”。

main.c 文件的内容:

build_gcc_host.sh 文件内容:

PS 如果使用“-nostdlib”选项,则不会添加“-lubsan”,但我确实需要“stdlib”。

我根本不需要自动添加“-lubsan”。

0 投票
1 回答
529 浏览

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 选项,构建有时会超时。

0 投票
0 回答
653 浏览

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

错误: