アドレスサニタイザ

概要

アドレスサニタイザは、Clangコンパイラとランタイム、IDEが連携し不正なメモリアクセスを実行時に検出する機能です。 本機能では、以下のメモリアクセス違反が検出可能です。

  • ローカル変数(スタック領域)の範囲外アクセス
  • グローバル変数に対しての範囲外アクセス
  • 動的に確保(malloc)したメモリに対しての範囲外アクセス
  • freeしたメモリ領域へのアクセス
  • 二重free

使い方

実際に、Starter Kitに付属のアドレスサニタイザデモ <ボード名>-demo-sanitizer を動作させてみます。

アドレスサニタイザデモについて

本サンプルには、malloc で確保したバッファの範囲外アクセスと、free したバッファへのメモリアクセスの2種類のバグが入っています。 この程度であれば、対象となるプログラムに大きな影響を与える事なく動作を継続できる可能性が高いですが、場合によっては重大なクラッシュを引き起こす事もあります。

実際に、デフォルトの Debug 構成(アドレスサニタイザ無効)でビルド、実行すると、特に問題は発生せずプログラムが動作します。 これらのバグを、アドレスサニタイザを有効にしてビルドする事で、自動的に検出してみましょう。

構成の変更と実行

サンプルアプリケーションの実行 を参考に、<ボード名>-demo-sanitizer を開き、 ビルドの構成を Debug_tasan に変更します。

../_images/change-debug-const.png

ビルドと実行

メニューの [ビルド]-[ソリューションのビルド] でプロジェクトをビルドし、[デバッグ]-[デバッグの開始] で実行します。

バグの検出

実行後、確保したバッファの範囲外をアクセスする直前に、自動的にプログラムが停止し、問題のあるソース行がハイライト表示されます。 また、デバッグ例外 ウィンドウには、検出されたバグの種類やアクセス先のアドレス、アクセスサイズ、アクセスタイプ(ReadまたはWrite)、 タスクID、エラーの発生する実行アドレス(PC)が表示されます。

../_images/asan-detect-oob.png

これらの情報から、実行アドレス0xf0c003c0で、1バイトのライトアクセスが0xf0ca3838に対して発生し、それがメモリの範囲外アクセス である事がわかりました。

注釈

本機能では、バグを引き起こす操作(上記の例では strb 命令)が実行される前にプログラムが停止します。

さらに実行を再開すると、次は free したバッファへのアクセスが発生する直前で停止します。

../_images/asan-detect-uaf.png

ここでも デバッグ例外 ウィンドウなどの情報から、実行アドレス0xf0c003f4で、1バイトのライトアクセスが0xf0ca3438に対して発生し、それが既にfreeされたメモリに対してのアクセス である事がわかります。