GCC的ASAN可以提供与Rust相同的内存安全性吗?

Hes*_*nov 6 gcc rust address-sanitizer

Rust被称为内存安全语言,但GCC中有一个名为AddressSanitizer(ASAN)的安全功能:

./configure CFLAGS="-fsanitize=address -g" CXXFLAGS="-fsanitize=address -g" LDFLAGS="-fsanitize=address"
make
make check
Run Code Online (Sandbox Code Playgroud)

ASAN能提供与Rust相同的内存安全性,还是Rust有更多技巧?甚至可以比较两者吗?

免责声明:我不是程序员.

Mat*_* M. 14

消毒剂

GCC和Clang都有一套消毒剂; 到目前为止,它们是在Clang开发的,然后移植到GCC,因此Clang拥有最先进的版本:

  • 地址Sanitizer(ASan):检测越界访问,释放后使用,使用后范围,双重自由/无效,并添加对内存泄漏的支持(预期内存开销3倍),
  • Memory Sanitizer(MemSan):检测未初始化的读取(预期减速3x),
  • Thread Sanitizer(TSan):检测数据竞争(预期减速5x-15x,内存开销5x-10x),
  • 未定义的行为清理程序(UBSan):各种本地未定义的行为,如未对齐的指针,整数/浮点溢出等...(最小减速,轻微的代码大小增加).

Type Sanitizer还有一些工作正在进行中.


消毒杀菌剂vs Rust

不幸的是,使用消毒剂使C++达到Rust的安全水平是不可能的; 即使将所有现有的消毒杀菌剂结合起来仍然会留下空白,众所周知它们是不完整的.

您可以在2017年 CppCon上看到John Regher关于未定义行为的演示文稿,幻灯片可以在github上找到,我们从中获得当前的报道:

在此输入图像描述

这并不能说明消毒剂彼此不相容这一事实.也就是说,即使你愿意接受组合的减速(15x-45x?)和内存开销(15x-30x?),你仍然无法管理C++程序和Rust一样安全.


强化与调试

消毒剂之所以如此占用CPU /内存是因为它们是调试工具; 他们试图尽可能精确地为开发人员提供诊断,以便对调试最有用.

为了在生产中运行代码,您正在寻找的是强化.强化是指以尽可能低的开销消除未定义的行为.例如,Clang支持多种强化二进制的方法:

这些工具可以组合在一起,对性能影响最小(<1%).遗憾的是,它们比清洁剂的覆盖范围要小得多,而且最明显的是,它们并不试图涵盖经常使用的后使用/使用后范围或数据争夺,这些都是攻击的常见目标.


结论

我没有看到任何方法将C++提升到Rust结合的安全级别,没有:

  • 对语言的严格限制:参见MISRA/JSF指南,
  • 非常严重的性能损失:消毒剂,禁用​​优化,......
  • 对标准库和编码实践进行彻底检查,其中核心指南是一个开始.

另一方面,值得注意的是Rust本身使用unsafe代码; 并且其unsafe代码也需要经过审查(参见Rust Belt项目),并将受益于所有上述消毒剂/硬化仪器通过.