吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于編譯器用于快速檢測原生代碼中內存錯誤的ASan

電子工程師 ? 來源:哆啦安全 ? 作者:哆啦安全 ? 2022-07-29 16:04 ? 次閱讀

什么是 ASan

ASan 是Address Sanitizer簡稱,它是是一種基于編譯器用于快速檢測原生代碼中內存錯誤的工具

簡而言之,ASan 就是一個用于快速檢測內存錯誤的工具。這里很多朋友有誤解,ASan 其實并不能用于內存泄漏檢測,Android 平臺內存泄漏檢測推薦 MallocDebug

另外需要注意的是Android O(API >= 27)及以上版本才支持 ASan ,NDK 需要選用 r20 及以上版本。

ASan 可以檢測到內存錯誤類型如下:

Stack and heap buffer overflow/underflow 棧和堆緩沖區上溢/下溢;

Heap use after free 堆內存被釋放之后還在使用其指針;

Stack use outside scope 在某個局部變量的作用域之外,使用其指針;

Double free/wild free 指針重復釋放的情況。

ASan 支持 arm 和 x86 平臺,使用 ASan 時,APP 性能會變慢且內存占用會飆升。針對 arm64 平臺,Android 官方推薦使用 HWAddress Sanitizer (HWASan),后面會介紹。

關于 ASan 的原理本文不做深入討論,該文章的主要目的是幫助開發者快速上手 ASan 的使用。

這里感性地介紹下 ASan 的工作原理ASan 相當于接管了內存的分配,當分配一塊內存時,會在這塊內存的前后添加"標志位",然后再次使用該內存的時候檢查"標志位"是否被修改,當發現"標志位"被修改時,判斷出現內存錯誤。

怎么使用 ASan

之所以寫這篇文件,就是因為發現一些文章介紹 ASan 使用方法搞得非常復雜,不易上手。

其實 Android 官方的使用說明非常簡潔,就是復制黏貼,添加兩行代碼就搞定。

官方文檔:https://developer.android.com/ndk/guides/asan

修改編譯腳本

CMake 方式

APP 下面的 build.gradle 添加:

android{
defaultConfig{
externalNativeBuild{
cmake{
#CanalsousesystemornoneasANDROID_STL.
arguments"-DANDROID_ARM_MODE=arm","-DANDROID_STL=c++_shared"
}
}
}
}

CMakeLists.txt 腳本添加:

target_compile_options(${libname}PUBLIC-fsanitize=address-fno-omit-frame-pointer)
set_target_properties(${libname}PROPERTIESLINK_FLAGS-fsanitize=address)

Ndk-Build 方式

Application.mk 文件添加:

APP_STL:=c++_shared#Orsystem,ornone.
APP_CFLAGS:=-fsanitize=address-fno-omit-frame-pointer
APP_LDFLAGS:=-fsanitize=address

Android.mk 文件添加:

APP_STL:=c++_shared#Orsystem,ornone.
APP_CFLAGS:=-fsanitize=address-fno-omit-frame-pointer
APP_LDFLAGS:=-fsanitize=address

拷貝 Asan 庫到 jniLibs 目錄下

Asan 庫位于下面路徑下:

android-ndk-r21toolchainsllvmprebuiltwindows-x86_64lib64clang9.0.8liblinux

64 位 libclang_rt.asan-aarch64-android.so , 32 位 libclang_rt.asan-arm-android.so ,分別拷貝兩個庫到 jniLibs 相應的目錄下。

新建 wrap.sh 文件,拷貝下面內容到文件中:

#!/system/bin/sh
HERE="$(cd"$(dirname"$0")"&&pwd)"
exportASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
ASAN_LIB=$(ls$HERE/libclang_rt.asan-*-android.so)
if[-f"$HERE/libc++_shared.so"];then
#Workaroundforhttps://github.com/android-ndk/ndk/issues/988.
exportLD_PRELOAD="$ASAN_LIB$HERE/libc++_shared.so"
else
exportLD_PRELOAD="$ASAN_LIB"
fi
"$@"

在 main 文件夾下新建目錄 resourceslib 然后將 wrap.sh 文件拷貝到相應的目錄下面,最終的目錄結構是這樣的:


└──app
└──src
└──main
├──jniLibs
│├──arm64-v8a
││└──libclang_rt.asan-aarch64-android.so
│├──armeabi-v7a
││└──libclang_rt.asan-arm-android.so
│├──x86
││└──libclang_rt.asan-i686-android.so
│└──x86_64
│└──libclang_rt.asan-x86_64-android.so
└──resources
└──lib
├──arm64-v8a
│└──wrap.sh
├──armeabi-v7a
│└──wrap.sh
├──x86
│└──wrap.sh
└──x86_64
└──wrap.sh

自此 ASan 接入完成,是不是很簡單?

ASan 檢測內存錯誤

這一節我們在代碼中故意設置一些常見的內存錯誤(內存越界等)用來測試 ASan 檢測出來的結果是否正確。

需要注意的是,當 ASan 檢測出內存錯誤,程序就會立即 crash ,不再往下執行,log 中會出現關鍵字 AddressSanitizer

堆內存溢出

staticvoidHeapBufferOverflow(){
int*arr=newint[1024];
arr[0]=11;
arr[1024]=12;
LOGCATE("HeapBufferOverflowarr[0]=%d,arr[1024]",arr[0],arr[1024]);
}

ASan 檢測結果(crash log)中出現關鍵字 heap-buffer-overflow :

05-1319:52:16.24741944194Icom.byteflow.learnffmpeg:=================================================================
05-1319:52:16.24741944194Icom.byteflow.learnffmpeg:==4194==ERROR:AddressSanitizer:heap-buffer-overflowonaddress0x004f0d5a8100atpc0x0074f822b648bp0x007ff0227a00sp0x007ff02279f8
05-1319:52:16.24741944194Icom.byteflow.learnffmpeg:WRITEofsize4at0x004f0d5a8100threadT0
05-1319:52:16.2572333423334DLauncher_UnlockAnimationStateMachine:mResetIdleStateRunnable
05-1319:52:16.26541944194Icom.byteflow.learnffmpeg:#00x74f822b644(/data/app/com.byteflow.learnffmpeg-mVg7CcQSTXVnJhfo7u0XLA==/lib/arm64/liblearn-ffmpeg.so+0x146644)
05-1319:52:16.26541944194Icom.byteflow.learnffmpeg:#10x74f8229b20(/data/app/com.byteflow.learnffmpeg-mVg7CcQSTXVnJhfo7u0XLA==/lib/arm64/liblearn-ffmpeg.so+0x144b20)
05-1319:52:16.26541944194Icom.byteflow.learnffmpeg:#20x74f8229a7c(/data/app/com.byteflow.learnffmpeg-mVg7CcQSTXVnJhfo7u0XLA==/lib/arm64/liblearn-ffmpeg.so+0x144a7c)
05-1319:52:16.26541944194Icom.byteflow.learnffmpeg:#30x74fdaac0a0(/data/app/com.byteflow.learnffmpeg-mVg7CcQSTXVnJhfo7u0XLA==/oat/arm64/base.odex+0xb0a0)
05-1319:52:16.26541944194Icom.byteflow.learnffmpeg:........

棧內存溢出

//stack-buffer-overflow
staticvoidStackBufferOverflow(){
intarr[1024];
arr[0]=11;
arr[1024]=12;
LOGCATE("StackBufferOverflowarr[0]=%d,arr[1024]",arr[0],arr[1024]);
}

ASan 檢測結果(crash log)中出現關鍵字 stack-buffer-overflow :

05-1319:54:30.37150025002Icom.byteflow.learnffmpeg:=================================================================
05-1319:54:30.37150025002Icom.byteflow.learnffmpeg:==5002==ERROR:AddressSanitizer:stack-buffer-overflowonaddress0x007ff02278c0atpc0x0074f8bd6640bp0x007ff0226890sp0x007ff0226888
05-1319:54:30.37250025002Icom.byteflow.learnffmpeg:WRITEofsize4at0x007ff02278c0threadT0
05-1319:54:30.38950025002Icom.byteflow.learnffmpeg:#00x74f8bd663c(/data/app/com.byteflow.learnffmpeg-aaLGh4G_-2c2WC7sX0ibag==/lib/arm64/liblearn-ffmpeg.so+0x14663c)
05-1319:54:30.38950025002Icom.byteflow.learnffmpeg:#10x74f8bd4a20(/data/app/com.byteflow.learnffmpeg-aaLGh4G_-2c2WC7sX0ibag==/lib/arm64/liblearn-ffmpeg.so+0x144a20)
05-1319:54:30.38950025002Icom.byteflow.learnffmpeg:#20x74f8bd497c(/data/app/com.byteflow.learnffmpeg-aaLGh4G_-2c2WC7sX0ibag==/lib/arm64/liblearn-ffmpeg.so+0x14497c)
......

使用已釋放的指針

//heap-use-after-free
staticvoidUseAfterFree(){
int*arr=newint[1024];
arr[0]=11;
delete[]arr;
LOGCATE("UseAfterFreearr[0]=%d,arr[1024]",arr[0],arr[1024]);
}

ASan 檢測結果(crash log)中出現關鍵字 heap-use-after-free :

05-131944.43052355235Icom.byteflow.learnffmpeg:=================================================================
05-131944.43052355235Icom.byteflow.learnffmpeg:==5235==ERROR:AddressSanitizer:heap-use-after-freeonaddress0x004f0d5a7100atpc0x0074f7ac945cbp0x007ff02279d0sp0x007ff02279c8
05-1319:56:44.43052355235Icom.byteflow.learnffmpeg:READofsize4at0x004f0d5a7100threadT0
05-1319:56:44.44752355235Icom.byteflow.learnffmpeg:#00x74f7ac9458(/data/app/com.byteflow.learnffmpeg-w2WNuKKPLEj7i4_8_Oj3Sw==/lib/arm64/liblearn-ffmpeg.so+0x146458)
05-1319:56:44.44852355235Icom.byteflow.learnffmpeg:#10x74f7ac7920(/data/app/com.byteflow.learnffmpeg-w2WNuKKPLEj7i4_8_Oj3Sw==/lib/arm64/liblearn-ffmpeg.so+0x144920)
05-1319:56:44.44852355235Icom.byteflow.learnffmpeg:#20x74f7ac787c(/data/app/com.byteflow.learnffmpeg-w2WNuKKPLEj7i4_8_Oj3Sw==/lib/arm64/liblearn-ffmpeg.so+0x14487c)
......

局部變量的作用域之外使用其指針

//stack-use-after-scope
staticint*p;
staticvoidUseAfterScope()
{
{
inta=0;
p=&a;
}
*p=1111;
LOGCATE("UseAfterScope*p=%d",*p);
}

ASan 檢測結果(crash log)中出現關鍵字 stack-use-after-scope :

https://developer.android.com/ndk/guides/asan#cmake05-132019.44759075907Icom.byteflow.learnffmpeg:=================================================================
05-132019.44759075907Icom.byteflow.learnffmpeg:==5907==ERROR:AddressSanitizer:stack-use-after-scopeonaddress0x007ff02279a0atpc0x0074f8236438bp0x007ff0227970sp0x007ff0227968
05-1320:01:19.44859075907Icom.byteflow.learnffmpeg:WRITEofsize4at0x007ff02279a0threadT0
05-1320:01:19.4622333423334DLauncher_UnlockAnimationStateMachine:mResetIdleStateRunnable
05-1320:01:19.46459075907Icom.byteflow.learnffmpeg:#00x74f8236434(/data/app/com.byteflow.learnffmpeg-jx_Xi14rwGHag_VZ9KWXYA==/lib/arm64/liblearn-ffmpeg.so+0x146434)
05-1320:01:19.46559075907Icom.byteflow.learnffmpeg:#10x74f8234860(/data/app/com.byteflow.learnffmpeg-jx_Xi14rwGHag_VZ9KWXYA==/lib/arm64/liblearn-ffmpeg.so+0x144860)
05-1320:01:19.46559075907Icom.byteflow.learnffmpeg:#20x74f82347bc(/data/app/com.byteflow.learnffmpeg-jx_Xi14rwGHag_VZ9KWXYA==/lib/arm64/liblearn-ffmpeg.so+0x1447bc)
05-1320:01:19.46559075907Icom.byteflow.learnffmpeg:#30x74fdabe0a0(/data/app/com.byteflow.learnffmpeg-jx_Xi14rwGHag_VZ9KWXYA==/oat/arm64/base.odex+0xb0a0)
.....

重復釋放指針

//double-free
staticvoidDoubleFree(){
int*arr=newint[1024];
arr[0]=11;
delete[]arr;
delete[]arr;
LOGCATE("UseAfterFreearr[0]=%d",arr[0]);
}

ASan 檢測結果(crash log)中出現關鍵字 double-free :

05-1320:02:16.47461026102Icom.byteflow.learnffmpeg:=================================================================
05-1320:02:16.47561026102Icom.byteflow.learnffmpeg:==6102==ERROR:AddressSanitizer:attemptingdouble-freeon0x004f0d5a7100inthreadT0:
05-1320:02:16.49261026102Icom.byteflow.learnffmpeg:#00x74f9f2b7b0(/data/app/com.byteflow.learnffmpeg-kjj44NZxl-eyA06gf3E2MA==/lib/arm64/libclang_rt.asan-aarch64-android.so+0xd57b0)
05-1320:02:16.49261026102Icom.byteflow.learnffmpeg:#10x74f88cd210(/data/app/com.byteflow.learnffmpeg-kjj44NZxl-eyA06gf3E2MA==/lib/arm64/liblearn-ffmpeg.so+0x146210)
05-1320:02:16.49261026102Icom.byteflow.learnffmpeg:#20x74f88cb720(/data/app/com.byteflow.learnffmpeg-kjj44NZxl-eyA06gf3E2MA==/lib/arm64/liblearn-ffmpeg.so+0x144720)
05-1320:02:16.49261026102Icom.byteflow.learnffmpeg:#30x74f88cb67c(/data/app/com.byteflow.learnffmpeg-kjj44NZxl-eyA06gf3E2MA==/lib/arm64/liblearn-ffmpeg.so+0x14467c)
......

ASan 基本上可以覆蓋到常見的內存錯誤問題,還有其他情況就不一一展示了。

編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Android
    +關注

    關注

    12

    文章

    3945

    瀏覽量

    127944
  • 內存
    +關注

    關注

    8

    文章

    3055

    瀏覽量

    74334
  • 編譯器
    +關注

    關注

    1

    文章

    1642

    瀏覽量

    49288

原文標題:Android Native開發內存越界檢測

文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    ARM最優CC++編譯器用戶指南

    ARM最優CC++編譯器用戶指南
    發表于 03-14 10:48 ?3次下載

    使用英特爾編譯器和庫的新功能構建快速代碼

    https://software.intel.com/zh-cn/intel-advisor-xe使用新的英特爾?編譯器15.0版編譯器和庫,可以更快地構建快速
    的頭像 發表于 11-12 07:03 ?1977次閱讀

    CompCert編譯器目標代碼生成機制研究綜述

    CompCert是著名的C語言可信編譯器,是經過形式化驗證的編譯器的杰出代表,近年來被廣泛應用于學術界和工業界的許多研發工作。 Compcert
    發表于 05-07 10:17 ?7次下載

    用于Python代碼的開源式即時編譯器NUMBA介紹

    Numba 是一個適用于 Python 代碼的開源式即時編譯器。借助該編譯器,開發者可以使用標準 Python 函數在 CPU 和 GPU 上加速數值函數。
    的頭像 發表于 07-08 09:15 ?1724次閱讀

    CC-RL 編譯器用戶手冊

    CC-RL 編譯器用戶手冊
    發表于 01-13 19:13 ?1次下載
    CC-RL <b class='flag-5'>編譯器用</b>戶手冊

    CC-RX 編譯器用戶手冊

    CC-RX 編譯器用戶手冊
    發表于 01-13 19:13 ?1次下載
    CC-RX <b class='flag-5'>編譯器用</b>戶手冊

    Neuron 現場編譯器用戶指南

    Neuron 現場編譯器用戶指南
    發表于 03-13 19:29 ?0次下載
    Neuron 現場<b class='flag-5'>編譯器用</b>戶指南

    R32C/100系列C編譯器包V.1.01 C編譯器用戶手冊

    R32C/100系列C編譯器包V.1.01 C編譯器用戶手冊
    發表于 04-28 19:54 ?1次下載
    R32C/100系列C<b class='flag-5'>編譯器</b>包V.1.01 C<b class='flag-5'>編譯器用</b>戶手冊

    CC-RL 編譯器用戶手冊

    CC-RL 編譯器用戶手冊
    發表于 07-03 20:03 ?0次下載
    CC-RL <b class='flag-5'>編譯器用</b>戶手冊

    CC-RX 編譯器用戶手冊

    CC-RX 編譯器用戶手冊
    發表于 07-03 20:03 ?0次下載
    CC-RX <b class='flag-5'>編譯器用</b>戶手冊

    Neuron 現場編譯器用戶指南

    Neuron 現場編譯器用戶指南
    發表于 07-04 20:47 ?0次下載
    Neuron 現場<b class='flag-5'>編譯器用</b>戶指南

    用于AVR MCU的MPLAB XC8 C編譯器用戶指南

    電子發燒友網站提供《適用于AVR MCU的MPLAB XC8 C編譯器用戶指南.pdf》資料免費下載
    發表于 09-19 15:47 ?3次下載
    適<b class='flag-5'>用于</b>AVR MCU的MPLAB XC8 C<b class='flag-5'>編譯器用</b>戶指南

    MPLAB XC16 C編譯器用戶指南

    電子發燒友網站提供《MPLAB XC16 C編譯器用戶指南.pdf》資料免費下載
    發表于 09-21 09:27 ?1次下載
    MPLAB XC16 C<b class='flag-5'>編譯器用</b>戶指南

    Triton編譯器與GPU編程的結合應用

    Triton編譯器簡介 Triton編譯器是一種針對并行計算優化的編譯器,它能夠自動將高級語言代碼轉換為針對特定硬件優化的低級代碼。Trit
    的頭像 發表于 12-25 09:13 ?324次閱讀

    用于PIC MCU的MPLAB XC8 C編譯器用戶指南

    電子發燒友網站提供《適用于PIC MCU的MPLAB XC8 C編譯器用戶指南.pdf》資料免費下載
    發表于 01-22 16:45 ?0次下載
    適<b class='flag-5'>用于</b>PIC MCU的MPLAB XC8 C<b class='flag-5'>編譯器用</b>戶指南
    摩纳哥百家乐官网娱乐城| 大发8888娱乐城| 大家赢百家乐投注| 澳门百家乐秘诀| 免费百家乐官网过滤工具| 江山百家乐官网的玩法技巧和规则| 路冲铺面能做生意吗| 宝龙百家乐娱乐城| 百家乐网络真人斗地主| 肯博百家乐的玩法技巧和规则| 百家乐线路图分析| 大发888注册送58元| 现金游戏网| 南京市| 真人百家乐官网试玩游戏| 百家乐官网筹码盒| 欧洲百家乐官网的玩法技巧和规则 | 大发888 游戏下载| 大发888娱乐场下载iyou qrd| bet365怎么上不去| 广南县| 狮威百家乐官网娱乐场| 博彩百家乐官网五2013124预测| 百家乐天下第一缆| 百家乐切入法| 大发888娱乐场下载com| 威尼斯人娱乐棋牌| 全球最大赌博网站| 百家乐官网真钱游戏下载| 百家乐官网代理龙虎| 百家乐官网游戏规范| 网络百家乐游赌博| 大发888论坛爱好| 荔波县| 百家乐官网赌场软件| 博九百家乐娱乐城| 威尼斯人娱乐最新地址| 大发888电话| 百家乐官网视频连连看| 百家乐看单技术| 真人游戏机|