• 巧用clang 的sanitize解决realloc,malloc,calloc失败


    写了一个函数:创建一个节点,并将id 全部克隆到新创建的节点,代码如下

    1. static itree_node_t * itree_new2(id_sets_t * id_sets,unsigned int min,unsigned int max)
    2. {
    3. itree_node_t * new_node = NULL;
    4. new_node = calloc(1,sizeof(itree_node_t));
    5. assert(new_node);
    6. new_node->max = max;
    7. new_node->min = min;
    8. new_node->id_sets.id_num = id_sets->id_num;
    9. new_node->id_sets.id_array_num = ID_PREPARE_MALLOC_SIZE;
    10. new_node->id_sets.id_array = calloc(new_node->id_sets.id_array_num,sizeof(unsigned int));
    11. assert(new_node->id_sets.id_array);
    12. for(int i = 0 ; i < id_sets->id_num;i++)
    13. {
    14. new_node->id_sets.id_array[i] = id_sets->id_array[i];
    15. }
    16. return new_node;
    17. }

    不适用任何特殊编译选项编译这段代码:

    gcc   -g -O0  -Wall  $(DEFINES) $(INCLUDE) 

    运行后出现下面的结果:

    1. itree init...
    2. realloc(): invalid next size ][4%][|]
    3. 已放弃 (核心已转储)

    使用gdb 看堆栈:

    1. #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
    2. #1 0x00007ffff7de0859 in __GI_abort () at abort.c:79
    3. #2 0x00007ffff7e4b26e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7f75298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
    4. #3 0x00007ffff7e532fc in malloc_printerr (str=str@entry=0x7ffff7f735bb "realloc(): invalid next size") at malloc.c:5347
    5. #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
    6. #5 0x00007ffff7e58fb6 in __GI___libc_realloc (oldmem=0x424b50, bytes=800) at malloc.c:3226
    7. #6 0x000000000040235d in itree_node_id_clone (node=0x414510, id_sets=0x4139d8) at ../idps_itree.c:77
    8. #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 

    后重新编译运行,结果如下:

    1. zison@ubuntu:~/work/idps/car_idps/idps_engine$ ./test/itree_test 5000 100
    2. itree init...
    3. ================================================================= ][3%][\]
    4. ==55229==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140002559d0 at pc 0x0000004c7e5a bp 0x7ffde91cf5c0 sp 0x7ffde91cf5b8
    5. WRITE of size 4 at 0x6140002559d0 thread T0
    6. #0 0x4c7e59 in itree_new2 /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:53:39
    7. #1 0x4c4dbe in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:211:35
    8. #2 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    9. #3 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    10. #4 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    11. #5 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    12. #6 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    13. #7 0x4c65e1 in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:350:16
    14. #8 0x4c3499 in itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:424:12
    15. #9 0x4c8ea5 in main /home/zison/work/idps/car_idps/idps_engine/test/itree_test.c:59:9
    16. #10 0x7f7267e1d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    17. #11 0x41b31d in _start (/home/zison/work/idps/car_idps/idps_engine/test/itree_test+0x41b31d)
    18. 0x6140002559d0 is located 0 bytes to the right of 400-byte region [0x614000255840,0x6140002559d0)
    19. allocated by thread T0 here:
    20. #0 0x493bd2 in calloc (/home/zison/work/idps/car_idps/idps_engine/test/itree_test+0x493bd2)
    21. #1 0x4c7bc2 in itree_new2 /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:48:34
    22. #2 0x4c4dbe in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:211:35
    23. #3 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    24. #4 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    25. #5 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    26. #6 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    27. #7 0x4c36ac in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:110:16
    28. #8 0x4c65e1 in _itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:350:16
    29. #9 0x4c3499 in itree_insert /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:424:12
    30. #10 0x4c8ea5 in main /home/zison/work/idps/car_idps/idps_engine/test/itree_test.c:59:9
    31. #11 0x7f7267e1d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    32. SUMMARY: AddressSanitizer: heap-buffer-overflow /home/zison/work/idps/car_idps/idps_engine/test/../idps_itree.c:53:39 in itree_new2
    33. Shadow bytes around the buggy address:
    34. 0x0c2880042ae0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
    35. 0x0c2880042af0: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
    36. 0x0c2880042b00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
    37. 0x0c2880042b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    38. 0x0c2880042b20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    39. =>0x0c2880042b30: 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa
    40. 0x0c2880042b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    41. 0x0c2880042b50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    42. 0x0c2880042b60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    43. 0x0c2880042b70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    44. 0x0c2880042b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    45. 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 加深了解。

  • 相关阅读:
    kubernetes (k8s)的使用
    负数的右移
    MySQL Exception -- Install/Remove of the Service Denied!
    机器学习笔记 - 基于pytorch、grad-cam的计算机视觉的高级可解释人工智能
    一篇文章让你理解 大数据所需要的组件
    MySQL4(多表查询)
    从零开始学习Netty - 学习笔记 -Netty入门-ChannelFuture
    卡尔曼滤波(Kalman Filter)原理浅析-数学理论推导-2
    在Telegram营销后该如何进行客户管理
    MacOS新功能“通用控制”,多台设备操作互联太方便了!
  • 原文地址:https://blog.csdn.net/zison_sun/article/details/125403967