AddressSanitizerページ


紹介する
AddressSanitizerは、コンパイル時に杭を挿入するモジュールと実行ライブラリからなる高速メモリエラー検出ツールです.このツールでは、次のタイプのエラーを検出できます.
  • OOB(スタック、スタック、およびグローバル変数を含む)
  • UAF
  • Use-After-Return(runtime flag ASAN_OPTIONS=detect_stack_use_after_return=1)
  • Use-After-Scope(clang flag -fsanitize-address-use-after-scope)
  • Doube-Free
  • Memory Leaks

  • AddressSanitizerが導入した一般的な速度低下は2倍程度である
    構築方法
    CMAKEを使用したLLVM/CLangの構築
    使用法-fsanitize=addressを使用してプログラムをコンパイルし、AddressSanitizerのランタイムライブラリを最終的な実行可能ファイルにリンクするだけです.したがって、最終的なリンクでclang(not ld)が使用されていることを確認してください.共有ライブラリをリンクし、AddressSanitizerの実行時にライブラリがリンクされていない場合、-Wl,-z,defsによってリンクエラーが発生する可能性があります(AddressSanitizerと併用しないでください).適切なパフォーマンスオーバーヘッドを得るために、-O1以上を追加してください.エラー・メッセージにより良いスタック・トラッキングを追加するには、-fno-omit-frame-pointerを有効にします.完全なスタックトラッキング情報を取得するには、インラインを無効にする必要がある場合があります(-O 1を使用します).
    % cat example_UseAfterFree.cc
    int main(int argc, char **argv) {
      int *array = new int[100];
      delete [] array;
      return array[argc];  // BOOM
    }
    
    # Compile and link
    % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc

    または
    # Compile
    % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
    # Link
    % clang++ -g -fsanitize=address example_UseAfterFree.o

    バグが検出されると、プログラムはstderrにエラーメッセージを出力し、0以外の終了コードで終了します.AddressSanitizerは、最初のエラーが検出されたときに終了します.
  • この方法により、AddressSanitizerは、より高速でより小型の生成コード(平均約5%)
  • を生成することができる.
  • バグの修正は避けられなくなり、AddressSanitizerでは誤報は発生しません.メモリの破損が発生すると、プログラムが不一致になり、困惑する結果を招く可能性があり、後続のレポート
  • を誤導する可能性があります.
    プロセスが砂箱化され、OS X 10.10以下で実行されている場合は、DYLD_INSERT_LIBRARIES環境変数を設定し、実行可能ファイルを生成するために使用されるコンパイラとパッケージ化されたASANライブラリ(asanの名前を検索することでライブラリを検索できます)に指定する必要があります.環境変数が設定されていない場合、プロセスは再実行を試みます.また、実行可能ファイルを別のマシンに移動する場合は、ASANライブラリもコピーする必要があることを覚えておいてください.
    シンボリックレポート
    AddressSanitizerをシンボル化して出力するには、環境変数ASAN_SYMBOLIZER_PATHを設定してllvm-symbolizerバイナリプログラムを指す必要があります(またはllvm-symbolizerが$PATHにあることを確認します)
    % ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out
    ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
    READ of size 4 at 0x7f7ddab8c084 thread T0
        #0 0x403c8c in main example_UseAfterFree.cc:4
        #1 0x7f7ddabcac4d in __libc_start_main ??:0
    0x7f7ddab8c084 is located 4 bytes inside of 400-byte region [0x7f7ddab8c080,0x7f7ddab8c210)
    freed by thread T0 here:
        #0 0x404704 in operator delete[](void*) ??:0
        #1 0x403c53 in main example_UseAfterFree.cc:4
        #2 0x7f7ddabcac4d in __libc_start_main ??:0
    previously allocated by thread T0 here:
        #0 0x404544 in operator new[](unsigned long) ??:0
        #1 0x403c43 in main example_UseAfterFree.cc:2
        #2 0x7f7ddabcac4d in __libc_start_main ??:0
    ==9442== ABORTING

    これが適用されない場合(プロセスが砂箱化されているなど)、個別のスクリプトをオフラインで結果をマークできます(オンラインシンボル化はASAN_OPTIONS=symbolize=0を無効にすることができます).
    % ASAN_OPTIONS=symbolize=0 ./a.out 2> log
    % projects/compiler-rt/lib/asan/scripts/asan_symbolize.py / < log | c++filt
    ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8
    READ of size 4 at 0x7f7ddab8c084 thread T0
        #0 0x403c8c in main example_UseAfterFree.cc:4
        #1 0x7f7ddabcac4d in __libc_start_main ??:0
    ...

    OS Xでは、プログラム上でdsymutilを実行する必要がある場合があります.AddressSanitizerのレポートに保存されている情報はfile:lineです.
    エクストラチェック
    イニシャルシーケンスチェック
    AddressSanitizerは、ある翻訳ユニットで定義されたグローバル変数初期化が別の翻訳ユニットで定義されたグローバル変数を使用する場合に、動的初期化順序の問題を選択的に検出することができる
    OS Xではサポートされていませんのでご注意ください
    メモリリークチェック
    AddressSanitizerのリーク検出器の詳細については、LeakSanitizerセクションを参照してください.Linuxでは脆弱性検出がデフォルトで開き、OS XではASAN_OPTIONS=detect_leaks=1で開くことができます.しかし、他のプラットフォームではサポートされていません.
    問題の抑制
    AddressSanitizerでは誤報は発生しません.誤報を見つけたらさらに見てください.誤報ではないかもしれません.
    外部ライブラリのレポートの抑制
    実行時の介入により、AddressSanitizerは再コンパイルされていないコードでバグを検索できます.外部ライブラリでバグが発生した場合は、すぐにライブラリ保守者に報告して解決することをお勧めします.このようなブロッキング関係を解除するために、抑制メカニズムを有効にして、継続的なテストを維持することもできる.この抑制メカニズムは外部コードの問題を抑制するためにのみ使用され、AddressSanitizerが再コンパイルしたコードには適用されません.外部ライブラリのエラーを解消するには、ASAN_OPTIONS環境変数を抑制ファイルに設定します.ファイルのフルパスを指定するか、実行可能ファイルに対するパスを指定できます.
    ASAN_OPTIONS=suppressions=MyASan.supp

    抑制する関数またはライブラリの名前を指定するには、次のフォーマットを使用します.エラーレポートにこれらの情報が表示されます.抑制の範囲が小さいほど、捉えられるバグが多いことを覚えておいてください.
    interceptor_via_fun:NameOfCFunctionToSuppress
    interceptor_via_fun:-[ClassName objCMethodToSuppress:]
    interceptor_via_lib:NameOfTheLibraryToSuppress

    じょうけんコンパイル
    場合によっては、AddressSanitizerを有効にするかどうかによって、異なるコードを実行する必要がある場合があります.__has_featureは、この目的のために使用することができる
    #if defined(__has_feature)
    #  if __has_feature(address_sanitizer)
    // code that builds only under AddressSanitizer
    #  endif
    #endif

    ピン止め
    一部のコードはAddressSanitizerによって検出されるべきではありません.特定の関数の検出は、同義語no_sanitize_addressおよびno_address_safety_analysisが破棄された関数属性__attribute__ (no_sanitize ( "address"))を使用して無効にすることができる.他のコンパイラではサポートされていない可能性がありますので、__has_feature (address_sanitizer)と一緒に使用することをお勧めします.
    再コンパイルコードのエラー(ブラックリスト)
    AddressSanitizerは、特定の状況リストでsrcおよびfunエンティティタイプをサポートし、指定したソースファイルまたは関数のエラーレポートを抑制します.さらに、AddressSanitizerは、名前またはタイプを決定するグローバル変数を持つOOBのエラーレポートを抑制するために使用できるglobalおよびtypeエンティティタイプを導入し、クラスまたは構造体タイプのみを指定できます.initカテゴリを使用して、特定のソースファイルまたは特定のグローバル変数で発生する初期化順序の問題のエラーレポートを抑制できます.
    # Suppress error reports for code in a file or in a function:
    src:bad_file.cpp
    # Ignore all functions with names containing MyFooBar:
    fun:*MyFooBar*
    # Disable out-of-bound checks for global:
    global:bad_array
    # Disable out-of-bound checks for global instances of a given class ...
    type:Namespace::BadClassName
    # ... or a given struct. Use wildcard to deal with anonymous namespace.
    type:Namespace2::*::BadStructName
    # Disable initialization-order checks for globals:
    global:bad_init_global=init
    type:*BadInitClassSubstring*=init
    src:bad/init/files/*=init

    メモリリークの抑制
    LeakSanitizerによって生成されたメモリリークレポート(AddressSanitizerの一部として実行されている場合)は、個別のファイルにエクスポートできます.
    LSAN_OPTIONS=suppressions=MyLSan.supp

    そのモードはleak:で、モードが漏洩レポートのシンボル化スタックトラッキングの関数名、ソースファイル名、またはライブラリ名と一致すると、メモリ漏洩が抑制されます.詳細については、「完全ドキュメント」を参照してください.
    制限
  • はより多くの物理メモリを使用し、正確なオーバーヘッドは割り当ての細かさに依存し、割り当てが細ければ細いほど、オーバーヘッドが大きくなる
  • である.
  • AddressSanitizerより多くのスタックメモリを使用し、
  • の約3倍の増加
  • 64ビットプラットフォーム上のAddressSanitizerマッピングは、16 TB+の仮想アドレス空間を保持しない.これは、ulimitのようなツールが予想通りに動作しない可能性があることを意味する.
  • 静的リンク
  • はサポートされていません.
    サポートプラットフォーム
    AddressSanitizerのサポート:
  • Linux i386/x86_64 (tested on Ubuntu 12.04)
  • OS X 10.7 - 10.11 (i386/x86_64)
  • iOS Simulator
  • Android ARM
  • FreeBSD i386/x86_64 (tested on FreeBSD 11-current)

  • 他のプラットフォームのインタフェースが開発されています
    現在のステータス
    AddressSanitizerは、LLVM 3.1以降にサポートされているプラットフォームで完全に使用できます.このテストキットはCMakeの構築に統合されており、コマンドmake check-asanで実行できます.
    詳細
    https://github.com/google/sanitizers/wiki/AddressSanitizer
    テキストアドレス