美文网首页
C++内存安全检测工具 Sanitize

C++内存安全检测工具 Sanitize

作者: 谭英智 | 来源:发表于2023-01-31 18:28 被阅读0次

    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
    san-thread-shadow

    通过在内存中动态维持这个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
    

    相关文章

      网友评论

          本文标题:C++内存安全检测工具 Sanitize

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