首页 > 其他分享 >动态库单独添加Address Sanitizer

动态库单独添加Address Sanitizer

时间:2023-07-09 11:35:29浏览次数:45  
标签:00 Sanitizer integration how 添加 Address main

原文地址:https://www.cnblogs.com/liqinglucky/p/address-sanitizer-in-library.html

Address Sanitizer集成的原理是在汇编过程中(参考:程序编译过程与运行时内存 - liqinglucky - 博客园 (cnblogs.com))编译出.o文件时就将AddressSanitizer的运行时库替换malloc()/free()实现内存检测功能的。所以可以单独在执行程序(main executable)加Address Sanitizer,也可以在链接库中单独加Address Sanitizer。

main executable sanitized as well or only the shared library

也就是说当软件是由一个main函数调用很多动态库(也是自己源码)生成的可执行程序,那编译时main函数有编译进address senitizer库检测内存,那些被调用的动态库源码GCC编译时也要单独 加address senitizer参数编译才能检测动态库的内存。如果只在main程序加了address senitizer参数编译,就会出现main程序内存问题能发现,有些调用的动态库内存问题不会发现。为了验证这一想法我用一个由main程序调用动态库的代码做演示。

源代码:Address-Sanitizer-C-Language: 内存泄漏/越界检查工具 - Gitee.com

一、主程序加Address Sanitizer参数编译

代码

how_to_integration/CMakeLists.txt加上编译参数

project( app )

//加上编译参数
add_compile_options(-fsanitize=address -fsanitize-recover=all -fsanitize=leak)
add_link_options(-fsanitize=address -fsanitize-recover=all -fsanitize=leak) 

1 主程序的测试代码

/Address-Sanitizer-C-Language# git diff how_to_integration/main.c
diff --git a/how_to_integration/main.c b/how_to_integration/main.c
index 0010f95..0dabebe 100755
--- a/how_to_integration/main.c
+++ b/how_to_integration/main.c
@@ -7,7 +7,7 @@ int main(void)
   printf("add:%d \n", add(a,b));
   printf("sub:%d \n", sub(a,b));

+  int a1[10] = {0};
+  printf("%s a1 %d\n", __FUNCTION__, a1[11]);
   return 0;
 }

2 库程序的测试代码

/Address-Sanitizer-C-Language# git diff how_to_integration/lib/add.c
diff --git a/how_to_integration/lib/add.c b/how_to_integration/lib/add.c
index 96d8ea7..ed007f8 100755
--- a/how_to_integration/lib/add.c
+++ b/how_to_integration/lib/add.c
@@ -2,5 +2,8 @@

 int add(int a, int b)
 {
+  int a1[10] = {0};
+  printf("%s a1 %d\n", __FUNCTION__, a1[11]);

   return a+b;
 }

编译

build# cmake ..
build# make
build# ./app

测试

1 检测主程序的测试代码

/Address-Sanitizer-C-Language/how_to_integration/build# ./app
add:6
sub:2
=================================================================
==352812==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffee86702fc at pc 0x5591df96445c bp 0x7ffee8670280 sp 0x7ffee8670270
READ of size 4 at 0x7ffee86702fc thread T0
    #0 0x5591df96445b in main (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x145b)
    #1 0x7f3d2a8a6082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x5591df9641cd in _start (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x11cd)

Address 0x7ffee86702fc is located in stack of thread T0 at offset 92 in frame
    #0 0x5591df964298 in main (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x1298)

  This frame has 1 object(s):
    [48, 88) 'a1' (line 10) <== Memory access at offset 92 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x145b) in main
Shadow bytes around the buggy address:
  0x10005d0c6000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10005d0c6050: 00 00 00 00 f1 f1 f1 f1 f1 f1 00 00 00 00 00[f3]
  0x10005d0c6060: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c6090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d0c60a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Shadow gap:              cc
==352812==ABORTING

2 检测库程序的测试代码

/Address-Sanitizer-C-Language/how_to_integration/build# ./app
=================================================================
==352873==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffee9e7d24c at pc 0x7fa8c086b397 bp 0x7ffee9e7d1d0 sp 0x7ffee9e7d1c0
READ of size 4 at 0x7ffee9e7d24c thread T0
    #0 0x7fa8c086b396 in add (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/bin/libmath.so+0x1396)
    #1 0x558b93e3f231 in main (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x1231)
    #2 0x7fa8c069c082 in __libc_start_main ../csu/libc-start.c:308
    #3 0x558b93e3f14d in _start (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x114d)

Address 0x7ffee9e7d24c is located in stack of thread T0 at offset 92 in frame
    #0 0x7fa8c086b228 in add (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/bin/libmath.so+0x1228)

  This frame has 1 object(s):
    [48, 88) 'a1' (line 5) <== Memory access at offset 92 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/bin/libmath.so+0x1396) in add
Shadow bytes around the buggy address:
  0x10005d3c79f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
=>0x10005d3c7a40: f1 f1 f1 f1 00 00 00 00 00[f3]f3 f3 f3 f3 00 00
  0x10005d3c7a50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005d3c7a90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Shadow gap:              cc
==352873==ABORTING

二、库程序加Address Sanitizer参数编译

代码

how_to_integration/lib/CMakeLists.txt加上编译参数

//加上编译参数
add_compile_options(-fsanitize=address -fsanitize-recover=all -fsanitize=leak)
add_link_options(-fsanitize=address -fsanitize-recover=all -fsanitize=leak) 

1 主程序的测试代码

/Address-Sanitizer-C-Language# git diff how_to_integration/main.c
diff --git a/how_to_integration/main.c b/how_to_integration/main.c
index 0010f95..0dabebe 100755
--- a/how_to_integration/main.c
+++ b/how_to_integration/main.c
@@ -7,7 +7,7 @@ int main(void)
   printf("add:%d \n", add(a,b));
   printf("sub:%d \n", sub(a,b));

+  int a1[10] = {0};
+  printf("%s a1 %d\n", __FUNCTION__, a1[11]);
   return 0;
 }

2 库程序的测试代码

/Address-Sanitizer-C-Language# git diff how_to_integration/lib/add.c
diff --git a/how_to_integration/lib/add.c b/how_to_integration/lib/add.c
index 96d8ea7..ed007f8 100755
--- a/how_to_integration/lib/add.c
+++ b/how_to_integration/lib/add.c
@@ -2,5 +2,8 @@

 int add(int a, int b)
 {
+  int a1[10] = {0};
+  printf("%s a1 %d\n", __FUNCTION__, a1[11]);

   return a+b;
 }

编译

在库程序单独加编译参数-fsanitize=address编译时需要在编译环境上加环境变量

参考:【解决】asan runtime does not come first in initial library list - C/C++ - 清泛网 - 专注C++内核技术 (tsingfun.com)

build# export ASAN_OPTIONS=verify_asan_link_order=0

然后编译

build# cmake ..
build# make
Scanning dependencies of target math
[ 20%] Building C object bin/CMakeFiles/math.dir/add.o
[ 40%] Building C object bin/CMakeFiles/math.dir/sub.o
[ 60%] Linking C shared library libmath.so
[ 60%] Built target math
[ 80%] Linking C executable app
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tmpnam' is dangerous, better use `mkstemp'
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tempnam' is dangerous, better use `mkstemp'
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tmpnam_r' is dangerous, better use `mkstemp'
[100%] Built target app
root@ubuntu:/var/lte/Address-Sanitizer-C-Language/how_to_integration/build# ./app

测试

1 检测主程序的测试代码

/Address-Sanitizer-C-Language/how_to_integration/build# cmake ..
/Address-Sanitizer-C-Language/how_to_integration/build# make
Scanning dependencies of target math
[ 20%] Building C object bin/CMakeFiles/math.dir/add.o
[ 40%] Building C object bin/CMakeFiles/math.dir/sub.o
[ 60%] Linking C shared library libmath.so
[ 60%] Built target math
[ 80%] Linking C executable app
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tmpnam' is dangerous, better use `mkstemp'
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tempnam' is dangerous, better use `mkstemp'
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tmpnam_r' is dangerous, better use `mkstemp'
[100%] Built target app

/Address-Sanitizer-C-Language/how_to_integration/build# ./app
add:6
sub:2
main a1 1382831681   <<< 主程序不检测, 说明库程序的编译参数并未在主程序生效

2 检测库程序的测试代码

/Address-Sanitizer-C-Language/how_to_integration/build# ./app
=================================================================
==352965==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc0218bfcc at pc 0x7f3b9539e397 bp 0x7ffc0218bf50 sp 0x7ffc0218bf40
READ of size 4 at 0x7ffc0218bfcc thread T0
    #0 0x7f3b9539e396 in add (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/bin/libmath.so+0x1396)
    #1 0x55a7479e11e0 in main (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x11e0)
    #2 0x7f3b951bd082 in __libc_start_main ../csu/libc-start.c:308
    #3 0x55a7479e10ed in _start (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/app+0x10ed)

Address 0x7ffc0218bfcc is located in stack of thread T0 at offset 92 in frame
    #0 0x7f3b9539e228 in add (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/bin/libmath.so+0x1228)

  This frame has 1 object(s):
    [48, 88) 'a1' (line 5) <== Memory access at offset 92 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/var/lte/Address-Sanitizer-C-Language/how_to_integration/build/bin/libmath.so+0x1396) in add
Shadow bytes around the buggy address:
  0x1000004297a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000004297b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000004297c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000004297d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000004297e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
=>0x1000004297f0: f1 f1 f1 f1 00 00 00 00 00[f3]f3 f3 f3 f3 00 00
  0x100000429800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100000429810: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100000429820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100000429830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100000429840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Shadow gap:              cc
==352965==ABORTING

遇到的问题

1 程序运行失败:ASan runtime does not come first in initial library list

/Address-Sanitizer-C-Language/how_to_integration/build# make
Scanning dependencies of target math
[ 20%] Building C object bin/CMakeFiles/math.dir/add.o
[ 40%] Building C object bin/CMakeFiles/math.dir/sub.o
[ 60%] Linking C shared library libmath.so
[ 60%] Built target math
Scanning dependencies of target app
[ 80%] Building C object CMakeFiles/app.dir/main.o
[100%] Linking C executable app
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tmpnam' is dangerous, better use `mkstemp'
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tempnam' is dangerous, better use `mkstemp'
/usr/bin/ld: /lib/x86_64-linux-gnu/libasan.so.5: warning: the use of `tmpnam_r' is dangerous, better use `mkstemp'
[100%] Built target app

/Address-Sanitizer-C-Language/how_to_integration/build# ./app
==343885==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.

调查:

1 错误:ASan runtime does not come first in initial library list; you should either link runtime to_w_唯_w的博客-CSDN博客

2 c - valgrind asan runtime does not come first in initial library list - Stack Overflow

3 c++ - CLion wont run binary with address sanitizer - Stack Overflow

4 单独在库里编译Address Sanitizer:gcc - Asan : Issue with asan library loading - Stack Overflow

main executable sanitized as well or only the shared library

建议方法:

  1. build main executable with -fsanitize=address
  2. get rid of /etc/ld.so.preload on your test machine
  3. disable the check (need recent GCC) with export ASAN_OPTIONS=verify_asan_link_order=0; but you have to be sure that libraries from /etc/ld.so.preload do not intercept symbols important for Asan e.g. malloc, free, etc., otherwise things will start breaking

标签:00,Sanitizer,integration,how,添加,Address,main
From: https://www.cnblogs.com/liqinglucky/p/address-sanitizer-in-library.html

相关文章

  • docker中测试Address Sanitizer
    原文地址:https://www.cnblogs.com/liqinglucky/p/address-sanitizer-in-docker.htmlDocker只是提供了一个运行环境,Docker里的程序集成AddressSanitizer与Linux环境编译相比并不需要做任何额外改动。源代码:liqinglucky/DockerHelloWorld-码云-开源中国(gitee.com)一、代码......
  • 给input文本框添加灰色提示文字
    灰色提示功能大家都见到很多网站的文本框都有灰色提文字,一点即消失,鼠标一开又出现(没填写状态下)用下面这段短短的代码就可以实现啦!将这段代码加载input中!value="你的提示文字"onFocus="if(value==defaultValue){value='';this.style.color='#000'}"onBlur="if(!value){value=de......
  • 解决MySQL sql 添加当前时间戳的具体操作步骤
    MySQLsql添加当前时间戳在实际的数据库应用中,我们经常需要对数据进行时间戳的记录,以便追踪数据的变化和操作时间。MySQL提供了多种方式来添加当前时间戳,本文将介绍几种常见的方法。1.使用NOW()函数NOW()函数是MySQL内置的一个函数,可以返回当前的系统日期和时间。我们可以在IN......
  • 通过在本地项目中添加服务引用访问外部WebService项目接口
    访问外部WebService项目接口的第二种方式就是通过在本地项目中添加服务引用。以下学习验证过程,通过在本地建立一个winfrom项目,通过按钮点击,触发调用接口,执行代码处理逻辑,并在文本显示区域显示最终拿回的数据。(1)在Visualstudio新建一个winfrom项目: (2)右键项目,添加服务应用,填......
  • WEB API 添加jwt认证后,跨域失效问题
    WEBAPI添加jwt认证后,跨域失效问题跨域配置策略如下://添加跨域策略builder.Services.AddCors(options=>{options.AddPolicy("CorsPolicy",opt=>opt.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().WithExposedHeaders("......
  • 【Scala】在IDEA中右键没有添加scala object和class的选项
    首先要确保在AddFrameworkSupprt中添加了scala(选中项目根目录) 然后在File->ProjectStructure...中选择Libraries   最后是关键,要选择SourceRoot文件夹上级目录,一般是xxx.main  在sourceroot文件夹上右击,New里就有了ScalaClass ......
  • windows 文件夹添加备注
    1,选中希望改动的文件夹,然后右键“单击”,选择“属性”按钮。2,打开“自定义”面板,选择“更改图标”,将原来的默认文件夹图标更换为自己喜欢的图标样式,其实这两步完全是个性化的操作,可有可无,全看个人爱好3,返回到该文件夹中,将所有隐藏文件全部显示出来,找到Desktop.ini配置文件(没有就......
  • SublimeText添加对vue的支持和格式化
    添加对vue的语法的高亮支持首先需要安装插件installpackage,按下ctrl+shift+p,输入install即可看见installpackage,选中回车即可,等待一段时间会提示是否安装成功安装成功后开始安装开发VUE需要用到的插件,安装方式为ctrl+shift+p,选择installpackage......
  • postgresql建表后添加自增序列
    postgresql建表后添加自增序列//添加id自增序列createSEQUENCEpoi_id_seqstart1;//自增序列重新设置起始值selectsetval('poi_id_seq',(selectmax(id)frompoi)+1);......
  • vue(五)CSS样式添加
    Vue具有三种样式化应用程序的方法:外部CSS文件。单文件组件(.vue文件)中的全局样式。单文件组件中组件范围的样式。外部CSS导入外部CSS文件import"./assets/reset.css";单组件全局样式<style>/*全局样式*/.btn{padding:0.8rem1rem0.7rem;......