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行所申请的内存没释放

相关推荐
正在努力的小河1 小时前
Linux设备树简介
linux·运维·服务器
荣光波比1 小时前
Linux(十一)——LVM磁盘配额整理
linux·运维·云计算
LLLLYYYRRRRRTT1 小时前
WordPress (LNMP 架构) 一键部署 Playbook
linux·架构·ansible·mariadb
轻松Ai享生活2 小时前
crash 进程分析流程图
linux
大路谈数字化3 小时前
Centos中内存CPU硬盘的查询
linux·运维·centos
luoqice4 小时前
linux下查看 UDP Server 端口的启用情况
linux
倔强的石头_5 小时前
【Linux指南】动静态库与链接机制:从原理到实践
linux
赏点剩饭7785 小时前
linux中的hostpath卷、nfs卷以及静态持久卷的区别
linux·运维·服务器
神鸟云5 小时前
DELL服务器 R系列 IPMI的配置
linux·运维·服务器·网络·边缘计算·pcdn
herderl6 小时前
**僵尸进程(Zombie Process)** 和**孤儿进程(Orphan Process)**
linux·运维·服务器·网络·网络协议