• C++笔记Asan(addresssanitize)的使用


    参考资料

    https://github.com/google/sanitizers/wiki/AddressSanitizer

    ASAN简介

    AddressSanitizer(又名ASan)是C/C++的内存错误检测器。可以检测以下问题:
    Use after free (dangling pointer dereference) - 释放后使用
    Heap buffer overflow - 堆缓冲区溢出
    Stack buffer overflow - 栈缓冲区溢出
    Global buffer overflow - 全局缓冲区溢出
    Use after return - return后使用
    Use after scope - 作用域后使用
    Initialization order bugs - 初始化顺序bug
    Memory leaks - 内存泄露

    ASAN使用

    检查越界

    测试代码
    test_asan.cpp

    #include <iostream>
    int main() {
      int *arr = new int[10];
      int res = arr[10];  // index out of bounds
      std::cout << res << std::endl;
      delete[] arr;
      return 0;                                                                                                                                                             
    }
    

    编译

    g++ -fsanitize=address test_string_split.cpp -g -o test
    

    报错

    /usr/bin/ld: cannot find /usr/lib64/libasan.so.4.0.0
    collect2: error: ld returned 1 exit status
    

    解决

    sudo yum install /usr/lib64/libasan.so.4.0.0
    

    执行test

    ./test
    

    报错
    7246ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.

    需要将动态库加到LD_PRELOAD 一并执行test

    LD_PRELOAD=/usr/lib64/libasan.so.4 ./test
    

    结果

    =================================================================
    ==12145==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x604000000038 at pc 0x000000400ba8 bp 0x7ffc1899b500 sp 0x7ffc1899b4f0
    READ of size 4 at 0x604000000038 thread T0
        #0 0x400ba7 in main /data/xxx/test_cpp/test_asan.cpp:4
        #1 0x7fa6c5d09554 in __libc_start_main (/lib64/libc.so.6+0x22554)
        #2 0x400aa8  (/data/xxx/test_cpp/test+0x400aa8)
    
    0x604000000038 is located 0 bytes to the right of 40-byte region [0x604000000010,0x604000000038)
    allocated by thread T0 here:
        #0 0x7fa6c6a39968 in operator new[](unsigned long) (/usr/lib64/libasan.so.4+0xe0968)
        #1 0x400b68 in main /data/xxx/test_cpp/test_asan.cpp:3
        #2 0x7fa6c5d09554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    
    SUMMARY: AddressSanitizer: heap-buffer-overflow /datax/xxt/test_cpp/test_asan.cpp:4 in main
    Shadow bytes around the buggy address:
      0x0c087fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x0c087fff8000: fa fa 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa
      0x0c087fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c087fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==12145==ABORTING
    

    可见 heap-buffer-overflow 堆缓冲区溢出, 在main函数的第四行

    检查内存泄露

    test_asan2.cpp

    #include <iostream>
    int main() {
      int *ptr = new int(-1);
      std::cout << *ptr << std::endl;
      // delete ptr;                                                                                                                                                        
      return 0;
    }
    
    g++ -fsanitize=address test_asan2.cpp -g -o test
    LD_PRELOAD=/usr/lib64/libasan.so.4 ./test
    

    结果

    =================================================================
    ==14998==ERROR: LeakSanitizer: detected memory leaks
    
    Direct leak of 4 byte(s) in 1 object(s) allocated from:
        #0 0x7f00df6ee7a8 in operator new(unsigned long) (/usr/lib64/libasan.so.4+0xe07a8)
        #1 0x400b78 in main /xxx/test_cpp/test_asan2.cpp:3
        #2 0x7f00de9be554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    
    SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
    

    可见第三行new了一个int指针,并未释放

    bazel 编译时引入使用asan

    项目结构

    .
    ├── test
    │   ├── BUILD
    │   ├── test_asan2.cpp
    │   └── test_asan.cpp
    └── WORKSPACE
    

    test_asan.cpp
    test_asan2.cpp
    内容与上文相同

    // BUILD
    package(default_visibility = ["//visibility:public"])                                                                                                                   
    cc_binary(
        name = "test_asan",
        srcs = glob([
            "test_asan.cpp",
        ]), 
    )
    cc_binary(
        name = "test_asan2",
        srcs = glob([
            "test_asan2.cpp",
        ]), 
    )
    

    WORKSPACE为空

    编译执行

    bazel build ... -j 16 --compilation_mode=dbg --copt=-fsanitize=address --linkopt=-fsanitize=address
    LD_PRELOAD=/usr/lib64/libasan.so.4 ./bazel-bin/test/test_asan
    LD_PRELOAD=/usr/lib64/libasan.so.4 ./bazel-bin/test/test_asan2
    

    或者也可以在WORKSPACE同级下面增加.bashrc文件

    build --copt=-fsanitize=address
    build --linkopt=-fsanitize=address
    
    # 一些可用的编译选项
    build --copt=-fno-omit-frame-pointer
    build --copt=-fsanitize-recover=address
    
  • 相关阅读:
    Python基础5_字典,集合
    Python基础3_基本数据类型,字符串,for循环
    Python基础2_while循环,格式化输出,基本运算符,编码,
    Python基础1_初识,注释,变量,if语句
    编写高质量代码[读书笔记]
    php地方天气
    [head first php&mysql]读书笔记-基本的安全信息(第五章)
    上传本地图片
    检测IE
    underscore源码解析(实用的功能)
  • 原文地址:https://www.cnblogs.com/gnivor/p/16364729.html
Copyright © 2020-2023  润新知