美文网首页程序员
Clang Sanitizer的几种用法

Clang Sanitizer的几种用法

作者: videoisfun | 来源:发表于2020-11-28 12:23 被阅读0次

Clang已经更新到11版,支持的功能也更多,从代码质量的角度来讲,越多的Sanitizer,可以检测出来的问题也越多。Clang-11支持以下的Sanitizer

  1. Address Sanitizer
  2. Memory Sanitizer
  3. Thread Sanitizer
  4. Undefined Behavior Sanitizer
  5. Leak Sanitizer
    下面分别讲讲这几个Sanitizer如何来使用。

Address Sanitizer

注意Address Sanitizer是没有False Alarm的,也就是没有误报。
可以检测出的错误:

1. Out-of-bounds accesses to heap, stack and globals
2. Use-after-free
3. Use-after-return (runtime flag ASAN_OPTIONS=detect_stack_use_after_return=1)
4. Use-after-scope (clang flag -fsanitize-address-use-after-scope)
5. Double-free, invalid free
6. Memory leaks (experimental)(default on linux, enabled by ASAN_OPTIONS=detect_leaks=1 on MacOs)

如何编译:

% cat example_UseAfterFree.cc
int main(int argc, char **argv) {
  int *array = new int[100];
  delete [] array;
  return array[argc];  // BOOM
}

# Compile and link
% clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls example_UseAfterFree.cc

执行执行编译好的文件,如果AddressSanitizer检测出问题,就会立刻停止,并输出错误信息,不过错误信息里面只有地址,并不好分析。如果需要把地址和源代码对应起来,需要设置ASAN_SYMBOLIZER_PATH的环境变量,让它指向llvm-symbolizer,或者把llvm-symbolizer放在$PATH中。

% ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out
==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
READ of size 4 at 0x7f7ddab8c084 thread T0
    #0 0x403c8c in main example_UseAfterFree.cc:4
    #1 0x7f7ddabcac4d in __libc_start_main ??:0
0x7f7ddab8c084 is located 4 bytes inside of 400-byte region [0x7f7ddab8c080,0x7f7ddab8c210)
freed by thread T0 here:
    #0 0x404704 in operator delete[](void*) ??:0
    #1 0x403c53 in main example_UseAfterFree.cc:4
    #2 0x7f7ddabcac4d in __libc_start_main ??:0
previously allocated by thread T0 here:
    #0 0x404544 in operator new[](unsigned long) ??:0
    #1 0x403c43 in main example_UseAfterFree.cc:2
    #2 0x7f7ddabcac4d in __libc_start_main ??:0
==9442== ABORTING

Memory Sanitizer

可以检测出的错误:

uninitialized reads

如何编译:

% cat umr.cc
#include <stdio.h>

int main(int argc, char** argv) {
  int* a = new int[10];
  a[5] = 0;
  if (a[argc])
    printf("xx\n");
  return 0;
}

% clang -fsanitize=memory -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -O1 umr.cc

另外,可以加上-fsanitize-memory-track-origins去跟踪是未初始化的内存从哪里分配的;
执行:

% ./a.out
WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7f45944b418a in main umr.cc:6
    #1 0x7f45938b676c in __libc_start_main libc-start.c:226

Thread Sanitizer

用来检测data races;
如何编译:

% cat projects/compiler-rt/lib/tsan/lit_tests/tiny_race.c
#include <pthread.h>
int Global;
void *Thread1(void *x) {
  Global = 42;
  return x;
}
int main() {
  pthread_t t;
  pthread_create(&t, NULL, Thread1, NULL);
  Global = 43;
  pthread_join(t, NULL);
  return Global;
}

$ clang -fsanitize=thread -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -O1 tiny_race.c

执行过程中,如果检测到错误,会打印出来,但不会停下来:

WARNING: ThreadSanitizer: data race (pid=19219)
  Write of size 4 at 0x7fcf47b21bc0 by thread T1:
    #0 Thread1 tiny_race.c:4 (exe+0x00000000a360)

  Previous write of size 4 at 0x7fcf47b21bc0 by main thread:
    #0 main tiny_race.c:10 (exe+0x00000000a3b4)

  Thread T1 (running) created at:
    #0 pthread_create tsan_interceptors.cc:705 (exe+0x00000000c790)
    #1 main tiny_race.c:9 (exe+0x00000000a3a4)

UndefinedBehaviorSanitizer

主要用于检测下面的错误;

1. Using misaligned or null pointer
2. Signed integer overflow
3.Conversion to, from, or between floating-point types which would overflow the destination

如何编译:

int main(int argc, char **argv) {
  int k = 0x7fffffff;
  k += argc;
  return 0;
}
% clang++ -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -O1 test.cc
% ./a.out
test.cc:3:5: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'

Leak Sanitizer

可以放在Address Sanitizer里面使用。

相关文章

网友评论

    本文标题:Clang Sanitizer的几种用法

    本文链接:https://www.haomeiwen.com/subject/mgpqwktx.html