提问人:Marc Mutz - mmutz 提问时间:12/16/2021 最后编辑:user3840170Marc Mutz - mmutz 更新时间:12/27/2021 访问量:542
如何在让瑞银开心的同时抓住“abi::__forced_unwind”?
How to catch `abi::__forced_unwind` while keeping UBSan happy?
问:
像 libstdc++ 一样,我们正在检查某些地方的 ,然后重新抛出它,而不是采取其他一些操作。像 libstdc++ 一样,我们通过引用来捕获它:abi::__forced_unwind
try {
/* ... */
} catch (abi::__forced_unwind&) {
throw;
} catch (...) {
/* ... */
}
但是,如果我们真的pthread_cancel执行代码,ubsan 抱怨道:
运行时错误:引用绑定到类型为“struct __forced_unwind”的 null 指针
在这里,我们是通过 const-ref 还是可变 ref 捕获并不重要。
我们(和 libstdc++)是否真的在这里遇到了 UB,或者它是 GCC 的 UBSan 实现中的误报?
答:
4赞
user3840170
12/21/2021
#1
这是强制展开实现中的一个错误,该错误已作为票证 #100415 提交到 GCC Bugzilla 中。(可以说,它应该在 GCC 本身中修复,因为您没有创建实际的引用绑定,而只是在异常类型上匹配。
在修复时,您可以使用属性修饰包含子句的函数,这将禁止对引用进行 null 检查,而不是其他任何内容:catch
[[gnu::no_sanitize("null")]]
#include <pthread.h>
#include <cxxabi.h>
#include <iostream>
int main() {
pthread_t thrd;
pthread_create(
&thrd, nullptr,
[] [[gnu::no_sanitize("null")]] (void *) -> void * {
try {
pthread_exit(nullptr);
} catch (abi::__forced_unwind const &fu) {
std::cerr << "forced unwind with " << &fu << std::endl;
// does not trigger UBSan
int &x = *static_cast<int *>(nullptr);
// triggers UBSan
1 / 0;
throw;
}
}, nullptr);
pthread_join(thrd, nullptr);
// triggers UBSan
int &x = *static_cast<int *>(nullptr);
return 0;
}
评论
0赞
Jeff Garrett
12/29/2021
由于该属性仅适用于该特定函数,因此如果您调用分配 null 引用的函数,UBSan 仍然可以捕获该函数。换句话说,您可以非常狭隘地定制它。
评论
libstdc++
__forced_unwind
<iomanip>
__forced_unwind