简介
Sanitizers是谷歌发起的开源工具集,包括了AddressSanitizer, MemorySanitizer, ThreadSanitizer, LeakSanitizer,Sanitizers项目本是LLVM项目的一部分,但GNU也将该系列工具加入到了自家的GCC编译器中。GCC从4.8版本开始支持Address和Thread Sanitizer,4.9版本开始支持Leak Sanitizer和UB Sanitizer,这些都是查找隐藏Bug的利器。
valgrind特点:
这个工具相对简单,对于一些复杂的内存泄露可能无法解析出来而且有一个问题就是只有检测的进程退出后才会输出内存泄露信息。
sanitizer特点:
Sanitizer可以在检测到内存泄露第一时间立刻终止进程,并且它可以深入检测(随应用进程一起编译)。
Github 地址:https://github.com/google/sanitizers
Wiki 地址:https://github.com/google/sanitizers/wiki/AddressSanitizer
参考:
基本使用:https://blog.youkuaiyun.com/c_lazy/article/details/80009627
输出信息的详细解释:https://www.jianshu.com/p/3a2df9b7c353
ASAN(AddressSanitizer的缩写)是一款面向C/C++语言的内存错误问题检查工具,可以检测如下内存问题:
- 使用已释放内存(野指针)
- 堆内存越界(读写)
- 栈内存越界(读写)
- 全局变量越界(读写)
- 函数返回局部变量
- 内存泄漏
ASAN工具比 Valgrind 更高效,主要由两部分组成:
- 编译器插桩模块(编译器instrumentation 模块)
- 运行时库(提供malloc()/free()替代项的运行时库)
gcc 4.8 开始,AddressSanitizer 成为 gcc 的一部分,但不支持符号信息,无法显示出问题的函数和行数。从 4.9 开始,gcc 支持 AddressSanitizer 的所有功能。
https://blog.youkuaiyun.com/weixin_39094034/article/details/108796315
安装
Ubuntu 一般不用安装,CentOS 一般需要安装。
如果使用 AddressSanitizer 时报错:
/usr/bin/ld: cannot find /usr/lib64/libasan.so.0.0.0
则需要先安装。Ubuntu 安装命令:
sudo apt-get install libasan0
CentOS 安装命令:
sudo yum install libasan
使用方法
内存越界检测
1,内存访问错误是模糊测试通常能够发现的一类错误,其主要是由于程序对不该进行读写操作的内存进行了操作,从而导致了应用程序的崩溃。
2,实际上并不是所有的内存访问错误都能发生崩溃。
test.c来作为一个例子:
#include <stdio.h>
int main()
{
int a[2] = {1, 0};
int b = a[2];
return 0;
}
3,我们可以看出这是一个经典的 off-by-one-error错误((英语:Off-by-one error,缩写OBOE)是在计数时由于边界条件判断失误导致结果多了一或少了一的错误):
定义一个有两个元素的数组,访问该数组的元素时需从0开始,因此该数组的两个元素分别为a[0]、a[1]。然后将a[2]赋值给b,但实际上a[2]不是数组的一部分,是个无效的数值。所以b最终就成了一个任意的数值,它只是从堆栈和内存中未被定义的部分中读取了“一些”内存。
4,然而和其他的内存访问错误所不同的是,它并不会造成崩溃,即使是强大的 valgrind 也无法告诉我们具体问题在哪里。而在最新版本的 llvm和gcc中有一款工具却可以发现这种错误,它就是Address Sanitizer (ASan) ,它可以直接在编译的时候进行使用。
不过要注意的是,在使用前我们需要在编译器标志中增加一个参数-fsanitize=address。另外,为了使调试更为轻松,我们还需要增加 -ggdb.
zhangsan@PC:~$ gcc -fsanitize=address -ggdb -o test test.c
现在,我们再去运行之前的那个例子,我们会得到一个彩色的错误信息:
==7402==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff2971ab88 at pc 0x400904 bp 0x7fff2971ab40 sp 0x7fff2971ab30READ of size 4 at 0x7fff2971ab88 thread T0
#0 0x400903 in main /tmp/test.c:5
#1 0x7fd7e26