04-工具篇-ascan内存工具

利用C或C++编写系统时,容易出现内存方面的问题,当代码量过大时,我们需要用工具检查代码。其中ascan工具在开销小,本章对此工具的使用作一个简单介绍。

1.栈溢出

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int func0(void)
{
   char str[4] = {0};
   strcpy(str,"1234");
   return 0;
}
int main(int argc,char *argv[])
{
   func0();
   return 0;
}  

编译

bash 复制代码
$ g++ -g 1.cpp -o 1  -fsanitize=leak -fsanitize=address  -fno-omit-frame-pointer

运行

bash 复制代码
$ ./1
=================================================================
==21786==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc1f3df6e4 at pc 0x7faf3475077a bp 0x7ffc1f3df6b0 sp 0x7ffc1f3dee58
WRITE of size 5 at 0x7ffc1f3df6e4 thread T0
    #0 0x7faf34750779  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x79779)
    #1 0x5643f7fedb48 in func0() /home/zg/zg_code/zg_test/test/ascan_demo/1.cpp:8
    #2 0x5643f7fedbac in main /home/zg/zg_code/zg_test/test/ascan_demo/1.cpp:13
    #3 0x7faf34307c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
    #4 0x5643f7fed999 in _start (/home/zg/zg_code/zg_test/test/ascan_demo/1+0x999)

定位出第8行有栈溢出

2 堆溢出

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

 void func1(void)
 {
   char * p = (char*) malloc(sizeof(char)*4);
   char chs[] ={"12345"};
   memset(p,0x0,4);
   if (p != NULL) {
     memcpy(p,chs,5);
   }
}
 
int main(int argc,char *argv[])
{
   func1();
   return 0;
}  

编译

bash 复制代码
$ g++ -g 2.cpp -o 2  -fsanitize=leak -fsanitize=address  -fno-omit-frame-pointer

运行

bash 复制代码
$ ./2
=================================================================
==21804==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000014 at pc 0x7fa9abe2477a bp 0x7ffefe188770 sp 0x7ffefe187f18
WRITE of size 5 at 0x602000000014 thread T0
    #0 0x7fa9abe24779  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x79779)
    #1 0x558db4c94b3e in func1() /home/zg/zg_code/zg_test/test/ascan_demo/2.cpp:11
    #2 0x558db4c94ba0 in main /home/zg/zg_code/zg_test/test/ascan_demo/2.cpp:17
    #3 0x7fa9ab9dbc86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
    #4 0x558db4c94919 in _start (/home/zg/zg_code/zg_test/test/ascan_demo/2+0x919)

0x602000000014 is located 0 bytes to the right of 4-byte region [0x602000000010,0x602000000014)
allocated by thread T0 here:
    #0 0x7fa9abe89b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
    #1 0x558db4c94a86 in func1() /home/zg/zg_code/zg_test/test/ascan_demo/2.cpp:7
    #2 0x558db4c94ba0 in main /home/zg/zg_code/zg_test/test/ascan_demo/2.cpp:17
    #3 0x7fa9ab9dbc86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x79779) 
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[04]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: 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
==21804==ABORTING

检测出第11行有堆溢出

3 释放后使用

就是申请了一块内存区域,释放后没有设置为NULL,后续继续使用了。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func2(void)
{
   int * a = (int*)malloc(sizeof(int)*1);
   if ( a != NULL ) {
		*a = 1;
		printf("a is:%d.",*a);
		free(a);
		*a = 2;
		printf("error a is:%d.",*a);
	}
}

int main(int argc,char *argv[])
{
   func2();
   return 0;
}  
bash 复制代码
g++ -g 3.cpp -o 3  -fsanitize=leak -fsanitize=address  -fno-omit-frame-pointer
bash 复制代码
$ ./3
=================================================================
==21822==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000010 at pc 0x561a596b4ae8 bp 0x7ffed1292570 sp 0x7ffed1292560
WRITE of size 4 at 0x602000000010 thread T0
    #0 0x561a596b4ae7 in func2() /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:12
    #1 0x561a596b4b21 in main /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:19
    #2 0x7f6527861c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
    #3 0x561a596b4949 in _start (/home/zg/zg_code/zg_test/test/ascan_demo/3+0x949)

0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014)
freed by thread T0 here:
    #0 0x7f6527d0f7a8 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xde7a8)
    #1 0x561a596b4ab0 in func2() /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:11
    #2 0x561a596b4b21 in main /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:19
    #3 0x7f6527861c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)

previously allocated by thread T0 here:
    #0 0x7f6527d0fb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
    #1 0x561a596b4a3b in func2() /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:7
    #2 0x561a596b4b21 in main /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:19
    #3 0x7f6527861c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)

SUMMARY: AddressSanitizer: heap-use-after-free /home/zg/zg_code/zg_test/test/ascan_demo/3.cpp:12 in func2()
Shadow bytes around the buggy address:

检测出第12行,内存使用有问题

4 全局缓存溢出

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int g_abc[11];

int func3(void)
{
    int i = 0;
    for (i = 0; i <= 100; i++) {
      printf("value:%d\t",g_abc[i]);
      if (i%10 == 0 && i != 0) {
        printf("\n");
      }
   }
   return g_abc[12];
}

int main(int argc,char *argv[])
{
   func3();
   return 0;
}  
bash 复制代码
 g++    -fsanitize=address  -fno-omit-frame-pointer -fsanitize=leak    -use-after-free  -g 4.cpp -o 4
bash 复制代码
$ ./4
value:0	value:0	value:0	value:0	value:0	value:0	value:0	value:0	value:0	value:0value:0	
=================================================================
==21989==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55e55885b10c at pc 0x55e558659a94 bp 0x7fff8b9bbc00 sp 0x7fff8b9bbbf0
READ of size 4 at 0x55e55885b10c thread T0
    #0 0x55e558659a93 in func3() /home/zg/zg_code/zg_test/test/ascan_demo/4.cpp:11
    #1 0x55e558659b4b in main /home/zg/zg_code/zg_test/test/ascan_demo/4.cpp:21
    #2 0x7f24d7366c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
    #3 0x55e558659949 in _start (/home/zg/zg_code/zg_test/test/ascan_demo/4+0x949)

0x55e55885b10c is located 0 bytes to the right of global variable 'g_abc' defined in '4.cpp:5:5' (0x55e55885b0e0) of size 44
SUMMARY: AddressSanitizer: global-buffer-overflow /home/zg/zg_code/zg_test/test/ascan_demo/4.cpp:11 in func3()
Shadow bytes around the buggy address:

检测出第11行有全局缓存溢出

5 内存泄漏

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int func4(void)
{
  char * p = (char*) malloc(5);
  memset(p,0x0,5);
  memcpy(p,"1234",4), 
  printf("%s\n",p);
}

int main(int argc,char *argv[])
{
   func4();
   return 0;
}  
bash 复制代码
$ g++    -fsanitize=address  -fno-omit-frame-pointer -fsanitize=leak    -use-after-free  -g 5.cpp -o 5
cpp 复制代码
$ ./5
1234

=================================================================
==22003==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 5 byte(s) in 1 object(s) allocated from:
    #0 0x7f6d980d6b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
    #1 0x55d89de199eb in func4() /home/zg/zg_code/zg_test/test/ascan_demo/5.cpp:7
    #2 0x55d89de19a40 in main /home/zg/zg_code/zg_test/test/ascan_demo/5.cpp:15
    #3 0x7f6d97c28c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)

SUMMARY: AddressSanitizer: 5 byte(s) leaked in 1 allocation(s).

第7行所申请的内存没释放

相关推荐
朱容君6 分钟前
Linux系统编程多线程之读写锁讲解
linux·开发语言
大风吹PP凉12 分钟前
38配置管理工具(如Ansible、Puppet、Chef)
linux·运维·服务器·ansible·puppet
康熙38bdc30 分钟前
Linux 进程间通信——共享内存
linux·运维·服务器
jwybobo200733 分钟前
redis7.x源码分析:(3) dict字典
linux·redis
scoone41 分钟前
ssh登陆服务器后支持Tab键命令补全
linux·shell
运维佬2 小时前
CentOS 9 配置网卡
linux·centos
轩轩曲觞阁2 小时前
Linux网络——网络初识
linux·网络
2401_840192272 小时前
python基础大杂烩
linux·开发语言·python
weixin_438197383 小时前
K8S创建云主机配置docker仓库
linux·云原生·容器·eureka·kubernetes
舞动CPU9 小时前
linux c/c++最高效的计时方法
linux·运维·服务器