AddressSanitizer
AddressSanitizer可以在运行时,检测内存是否发生了内存错误。
例如可以检测以下问题:
- Use after free
- Head/Stack/Global buffer overflow
- Use after return
- Use after scope
- Memory leaks
用法如下:
clang++ -O1 -fsanitize=address a.cc ; ./a.out
原理
内存8 bytes对齐
san-8-bytes- 所有8字节都是 unpoisoned ,则为0
- 所有字节都是 poisoned,则为-1
- 前k个字节为 unpoisoned,则为k
这些值记录在shadow内存中
通过用内存的1/8的内存记录其他字节的内存状态
shadow使用1 byte的内存来标记8 bytes内存的状态
记录shadow使用以下的代码转换
shadow内存填充
原始代码:
void foo()
{
char a[8];
...
return;
}
编译后的代码:
void foo()
{
char redzone1[32]; // 32-byte aligned
char a[8]; // 32-byte aligned
char redzone2[24];
char redzone3[32]; // 32-byte aligned
int *shadow_base = MemToShadow(redzone1);
shadow_base[0] = 0xffffffff; // poison redzone1
shadow_base[1] = 0xffffff00; // poison redzone2, unpoison 'a'
shadow_base[2] = 0xffffffff; // poison redzone3
...
shadow_base[0] = shadow_base[1] = shadow_base[2] = 0; // unpoison all
return;
}
地址访问
每次访问之前做内存检查
原始代码:
*address = ...;
编译后代码:
if (IsPoisoned(address))
{
ReportError(address, kAccessSize, kIsWrite);
}
*address = ...;
malloc/free处理
使用自定义的函数替换malloc和free
malloc的buffer前后填充posion,buffer填充unposion
free的buffer填充posion
ThreadSanitizer
ThreadSanitizer 是用来检测死锁和data race的
原理
代码填充
原始代码:
void foo(int* p) {
*p = 42;
}
编译后的代码:
void foo(int *p) {
__tsan_func_entry(__builtin_return_address(0));
__tsan_write4(p);
*p = 42;
__tsan_func_exit()
}
shadow内容
8 bytes的内存
- 16 bits:线程id
- 42 bits:Epoch
- 5 bits: access buffer size
- 1 bit: IsWrite
通过在内存中动态维持这个shadow,来比较内存是否存在发生data race
MemorySanitizer
MemorySanitizer是用来检测是否使用未初始化内存
用法:
clang -fsanitize=memory a.c -g; ./a.out
原理
shadow
使用bit-2-bit来做shadow,1 代码 poisoned
每次访问内存时,通过获取shadow的状态,来判断是否发生了使用未初始化内粗
UndefinedBehaviorSanitizer
UndefinedBehaviorSanitizer可以用来检测程序是否发生了未定义行为
例如整数溢出
用法:
clang -fsanitize=undefined a.cc -g; ./a.out
提供的选项:
-fsanitize=alignment
-fsanitize=bool
-fsanitize=bounds
-fsanitize=enum
-fsanitize=float-cast-overflow
-fsanitize=float-divide-by-zero
-fsanitize=function
-fsanitize=integer-divide-by-zero
-fsanitize=null
-fsanitize=returns-nonnull-attribute
-fsanitize=shift
-fsanitize=signed-integer-overflow
-fsanitize=unreachable
-fsanitize=unsigned-integer-overflow
-fsanitize=vla-bound
-fsanitize=vptr
-fsanitize=object-size
-fsanitize=return
网友评论