Addr & 7,将得知此次内存访问是从memory region的第几个byte开始的。

AccessSize是此次内存访问需要访问的字节长度。

(Addr&7)+AccessSize 》 k,则说明此次内存访问将会访问到不可寻址的字节。(具体可分为k大于0和小于0两种情况来分析)

当此次内存访问可能会访问到不可寻址的字节时,ASAN会报错并结合shadow memory中具体的值明确错误类型。

1.3 典型错误

1.3.1 Use-After-Free

想要检测UseAfterFree的错误,需要有两点保证:

已经free掉的内存区域需要被标记成特殊的状态。在ASAN的实现里,free掉的normal memory对应的shadow memory值为0xfd(猜测有freed的意思)。

已经free掉的内存区域需要放入隔离区一段时间,防止发生错误时该区域已经通过malloc重新分配给其他人使用。一旦分配给其他人使用,则可能漏掉UseAfterFree的错误。

测试代码:

// RUN: clang -O -g -fsanitize=address %t && 。/a.outint main(int argc, char **argv) { int *array = new int[100]; delete [] array; return array[argc]; // BOOM}

ASAN输出的错误信息:

===================================================================6254== ERROR: AddressSanitizer: heap-use-after-free on address 0x603e0001fc64 at pc 0x417f6a bp 0x7fff626b3250 sp 0x7fff626b3248READ of size 4 at 0x603e0001fc64 thread T0 #0 0x417f69 in main example_UseAfterFree.cc:5 #1 0x7fae62b5076c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c) #2 0x417e54 (a.out+0x417e54)0x603e0001fc64 is located 4 bytes inside of 400-byte region [0x603e0001fc60,0x603e0001fdf0)freed by thread T0 here: #0 0x40d4d2 in operator delete[](void*) /home/kcc/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:61 #1 0x417f2e in main example_UseAfterFree.cc:4previously allocated by thread T0 here: #0 0x40d312 in operator new[](unsigned long) /home/kcc/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:46 #1 0x417f1e in main example_UseAfterFree.cc:3Shadow bytes around the buggy address: 0x1c07c0003f30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c07c0003f40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c07c0003f50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c07c0003f60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c07c0003f70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa=》0x1c07c0003f80: fa fa fa fa fa fa fa fa fa fa fa fa[fd]fd fd fd 0x1c07c0003f90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x1c07c0003fa0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x1c07c0003fb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa 0x1c07c0003fc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c07c0003fd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

可以看到,=》指向的那行有一个byte数值用中括号给圈出来了:[fd]。它表示的是此次出错的内存地址对应的shadow memory的值。而其之前的fa表示Heap left redzone,它是之前该区域有效时的遗留产物。连续的fd总共有50个,每一个shadow memory的byte和8个normal memory byte对应,所以可以知道此次free的内存总共是50×8=400bytes。这一点在上面的log中也得到了验证,截取出来展示如下: