巧用clang 的sanitize解决realloc,malloc,calloc失败
写了一个函数:创建一个节点,并将id 全部克隆到新创建的节点,代码如下
static itree_node_t * itree_new2(id_sets_t * id_sets,unsigned int min,unsigned int max)
{ itree_node_t * new_node = NULL;new_node = calloc(1,sizeof(itree_node_t));assert(new_node);new_node->max = max;new_node->min = min;new_node->id_sets.id_num = id_sets->id_num;new_node->id_sets.id_array_num = ID_PREPARE_MALLOC_SIZE;new_node->id_sets.id_array = calloc(new_node->id_sets.id_array_num,sizeof(unsigned int));assert(new_node->id_sets.id_array);for(int i = 0 ; i < id_sets->id_num;i++){new_node->id_sets.id_array[i] = id_sets->id_array[i];}return new_node;
}
不适用任何特殊编译选项编译这段代码:
gcc -g -O0 -Wall $(DEFINES) $(INCLUDE)
运行后出现下面的结果:
itree init...
realloc(): invalid next size ][4%][|]
已放弃 (核心已转储)
使用gdb 看堆栈:
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff7de0859 in __GI_abort () at abort.c:79
#2 0x00007ffff7e4b26e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7f75298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007ffff7e532fc in malloc_printerr (str=str@entry=0x7ffff7f735bb "realloc(): invalid next size") at malloc.c:5347
#4 0x00007ffff7e56fac in _int_realloc (av=av@entry=0x7ffff7faab80 <main_arena>, oldp=oldp@entry=0x424b40, oldsize=oldsize@entry=416, nb=816) at malloc.c:4564
#5 0x00007ffff7e58fb6 in __GI___libc_realloc (oldmem=0x424b50, bytes=800) at malloc.c:3226
#6 0x000000000040235d in itree_node_id_clone (node=0x414510, id_sets=0x4139d8) at ../idps_itree.c:77
#7 0x0000000000401a78 in _itree_insert (tree=0x7fffffffdfa0, pbase=0x42a070, node=0x4139d0) at ../idps_itree.c:281
可以看到出错的位置在itree_node_id_clone 中realloc 失败了。
但是检查代码,这里的代码并没有问题,使用malloc,calloc 替换后情况类似。
于是我们借助clang的sanitizer 来定位问题,使用如下编译选项:
clang -g -O0 -Wall $(DEFINES) $(INCLUDE) -fsanitize=address -fno-omit-frame-pointer
后重新编译运行,结果如下:
zison@ubuntu:~/work/idps/car_idps/idps_engine$ ./test/itree_test 5000 100
itree init...
================================================================= ][3%][\]
==55229==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140002559d0 at pc 0x0000004c7e5a bp 0x7ffde91cf5c0 sp 0x7ffde91cf5b8
WRITE of size 4 at 0x6140002559d0 thread T0#0 0x4c7e59 in itree_new2 /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:53:39#1 0x4c4dbe in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:211:35#2 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#3 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#4 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#5 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#6 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#7 0x4c65e1 in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:350:16#8 0x4c3499 in itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:424:12#9 0x4c8ea5 in main /home/zison/work/idps/car_idps/idps_engine/test/itree_test.c:59:9#10 0x7f7267e1d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16#11 0x41b31d in _start (/home/zison/work/idps/car_idps/idps_engine/test/itree_test+0x41b31d)0x6140002559d0 is located 0 bytes to the right of 400-byte region [0x614000255840,0x6140002559d0)
allocated by thread T0 here:#0 0x493bd2 in calloc (/home/zison/work/idps/car_idps/idps_engine/test/itree_test+0x493bd2)#1 0x4c7bc2 in itree_new2 /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:48:34#2 0x4c4dbe in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:211:35#3 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#4 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#5 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#6 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#7 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16#8 0x4c65e1 in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:350:16#9 0x4c3499 in itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:424:12#10 0x4c8ea5 in main /home/zison/work/idps/car_idps/idps_engine/test/itree_test.c:59:9#11 0x7f7267e1d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16SUMMARY: AddressSanitizer: heap-buffer-overflow /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:53:39 in itree_new2
Shadow bytes around the buggy address:0x0c2880042ae0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd0x0c2880042af0: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa0x0c2880042b00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 000x0c2880042b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c2880042b20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2880042b30: 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa0x0c2880042b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c2880042b80: 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):
观察结果,发现idps_itree.c:53
这里溢出了,这里才是真正引起问题的地方。检查代码 ,发现在id_sets->id_num 大于ID_PREPARE_MALLOC_SIZE 的情况下,就会出现溢出new_node->id_sets.id_array 的情况。
如果不使用clang 的sanitizer ,程序报错往往是在其他的malloc,calloc,realloc 的地方,出现类似“realloc(): invalid next size”的问题,往往根据报错比较难找到真正出问题的地方。
clang 的sanitizer 不仅能方便的查找内存溢出,还能方便的检查线程死锁等等。有兴趣的可以自行google ,baidu 加深了解。
巧用clang 的sanitize解决realloc,malloc,calloc失败相关推荐
- realloc,malloc,calloc的区别
三个函数的申明分别是: void* realloc(void* ptr, unsigned newsize); void* malloc(unsigned size); void* calloc ...
- 内存动态分配之realloc(),malloc(),calloc()与new运算符
1,malloc与free是C/C++的标准库函数,new/delete是C++的运算符,是C++面向对象的特征,它们都可用于申请动态内存和释放内存. 2,对于非内部数据类型的对象而言,光用maloc ...
- C语言学习笔记10-指针(动态内存分配malloc/calloc、realloc、释放free,可变数组实现;Tips:返回指针的函数使用本地变量有风险!;最后:函数指针)
C语言:指针 1. 指针:保存地址的变量 *p (pointer) ,这种变量的值是内存的地址. 取地址符& 只用于获取变量(有地址的东西)的地址:scanf函数-取地址符 地址的大小 ...
- c语言malloc,calloc,realloc函数介绍
malloc,calloc,realloc动态内存管理函数的出现解决了在某些c语言标准中不能使用变长数组的问题 这三个函数的使用需要头文件stdlib.h,这些函数开辟的空间在堆区,系统不会自动释放, ...
- malloc calloc realloc的对比
函数原型 三个函数的声明分别是: void* realloc(void* ptr, unsigned newsize); void* malloc(unsigned size); void* call ...
- Python selenium巧用Javascript脚本注入解决按钮点选问题
Python selenium巧用Javascript脚本注入解决按钮点选问题 参考文章: (1)Python selenium巧用Javascript脚本注入解决按钮点选问题 (2)https:// ...
- 内存分配函数 malloc、realloc、calloc
C 语言主要提供 malloc.realloc.calloc.alloca 与 aligned_alloc 等内存分配函数来实现对内存的分配功能. 1) malloc 函数原型如下: void * m ...
- 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现
内存分布 一.C语言中的动态内存管理方式:malloc/calloc/realloc和free 1.malloc: 从堆上获得指定字节的内存空间,函数声明:void *malloc (int n); ...
- C++自学21:动态分配内存(malloc/calloc/realloc/new)/回收内存(free/delete)
一:malloc函数,请求系统分配内存 // 让系统分配8个字节的内存,这8个字节是连续的,就是一个数组 int* a=(int*)malloc(8); // 如果分配成功,则返回数组首字节的地址,分 ...
最新文章
- 【SAP BI】BW如何连接SQLSERVER数据库
- virsh 关机_kvm虚拟机不能使用virsh shutdownw命令关闭虚拟机的解决方法
- 系统架构设计师考试 重要的部分
- vmware创建虚拟机并安装centos7系统
- linux硬盘系统安装教程图解,Linux操作系统添加安装新硬盘的方法图解
- Selenium WebDriver Api 知识梳理
- ArrayList源码解析
- 合并时显示是无效的m3u8文件_如何合并m3u8及ts文件
- LMS激光传感器的TCP/IP协议问题
- thinkphp 提示验证码错误
- 复制csdn或者博客园文章时,图片无法直接粘贴过来解决办法
- HTML初心自学记录(四)列表超链接
- 数据分析入门 | kaggle泰坦尼克任务
- python 如何调试uc浏览器_如何使用 UC浏览器开发者版 进行移动端调试
- Redis常用命令和操作
- vscode如何同时运行多个vue项目
- Python之logic
- cmd命令 从C盘跳到D盘
- python自学第六天之列表增删改查
- 谭浩强C语身教程第一章---C措辞概述(2)