AddressSanitizer

概要

C & C++ 言語は強力ですが、プログラムの正確性とプログラムのセキュリティに影響するバグのクラスを使用することはできません。 Visual Studio 2019 バージョン16.9 以降では、Microsoft C/c + + コンパイラ (MSVC) と IDE は AddressSanitizer をサポートしています。 AddressSanitizer (ASan) は、誤検知を ゼロ にして、発見しにくいバグを多数公開するコンパイラおよびランタイムテクノロジです。

AddressSanitizer を使用して、にかかる時間を短縮します。

  • 基本的な正確性
  • クロスプラットフォームの移植性
  • セキュリティ
  • ストレス テスト
  • 新しいコードの統合

Google によって初めて導入された AddressSanitizer は、両方 /RTC (ランタイムエラーチェック) /analyze (スタティック分析)の両方にとって優れた手段です。 既存のビルドシステムと既存のテスト資産を直接使用する、実行時のバグ検索テクノロジを提供します。

AddressSanitizer は、Visual Studio プロジェクトシステム、CMake ビルドシステム、IDE と統合されています。 プロジェクトで AddressSanitizer を有効にするには、プロジェクトのプロパティを設定するか、を使用して追加のコンパイラオプションを使用し /fsanitize=address ます。 新しいオプションは、x86 および x64 のすべてのレベルの最適化および構成と互換性があります。 ただし、 エディットコンティニュインクリメンタルリンク、およびには互換性がありません /RTC

Visual Studio 2019 バージョン16.9 以降では、Microsoft の AddressSanitizer テクノロジにより、Visual Studio IDE との統合が可能になります。 この機能は、実行時にサニタイザーがバグを発見したときに、必要に応じてクラッシュダンプファイルを作成できます。 プログラムを実行する ASAN_SAVE_DUMPS=MyFileName.dmp 前に環境変数を設定した場合、クラッシュダンプファイルが追加のメタデータを使用して作成され、正確に診断されるバグの事後分析が効率的に デバッグ されます。 これらのダンプファイルを使用すると、次のように AddressSanitizer を簡単に使用できます。

  • ローカルコンピューターのテスト、
  • オンプレミスの分散テスト、および
  • テスト用のクラウドベースのワークフロー。

AddressSanitizer をインストールする

AddressSanitizer IDE の統合とライブラリは、既定では Visual Studio インストーラーの C++ ワークロードと共にインストールされます。 ただし、以前のバージョンの Visual Studio 2019 からアップグレードする場合は、インストーラーを使用して、アップグレード後の ASan のサポートを有効にします。

C++ AddressSanitizer コンポーネントを強調表示した Visual Studio インストーラースクリーンショット

Visual Studio インストーラーから既存の Visual Studio インストールの [ 変更 ] を選択して、上の画面に移動できます。

注意

新しい更新プログラムで Visual Studio を実行しても、ASan がインストールされていない場合は、コードの実行時にエラーが発生します。

LNK1356: ライブラリ ' clang_rt ' が見つかりません。

AddressSanitizer を使用する

/fsanitize=address 次のいずれかの一般的な開発方法を使用して、コンパイラオプションを使用して実行可能ファイルのビルドを開始します。

  • コマンドラインビルド
  • Visual Studio のプロジェクト システム
  • Visual Studio CMake 統合

再コンパイルしてから、プログラムを通常どおり実行します。 このコード生成 では、さまざまな種類のバグを正確に診断できます。 これらのエラーは、デバッガー IDE のコマンドラインで、または 新しい種類のダンプファイル に格納されている、正確なオフライン処理の3つの方法で報告されます。

Microsoft では、次の3つの標準ワークフローで AddressSanitizer を使用することをお勧めします。

この記事では、上記の3つのワークフローを有効にするために必要な情報について説明します。 この情報は、プラットフォームに 依存 する AddressSanitizer の Windows 10 実装に固有のものです。 このドキュメントでは、既に公開され ている Google、Apple、および GCC からの優れたドキュメントを補足します。

注意

現在のサポートは、Windows 10 では x86 と x64 に制限されています。 今後のリリースで見たいことについてフィードバックをお送りください。 フィードバックは、、、 /fsanitize=thread /fsanitize=leak /fsanitize=memory/fsanitize=undefined 、またはなど、その他の sanitizers の優先順位付けに役立ち /fsanitize=hwaddress ます。 問題が発生した場合は、 ここでバグを報告 できます。

開発者コマンドプロンプトから AddressSanitizer を使用する

/fsanitize=address AddressSanitizer ランタイムのコンパイルを有効にするには、開発者コマンドプロンプトでコンパイラオプションを使用します。 この /fsanitize=address オプションは、既存の C++ または C のすべての最適化レベルと互換性があります (たとえば、、、、 /Od /O1 、など /O2 /O2 /GL PGO )。 このオプションは、static および dynamic crt と連動します (たとえば、、、 /MD /MDd /MT/MTd )。 EXE または DLL を作成するかどうかによって動作します。 呼び出し履歴を最適に書式設定するには、デバッグ情報が必要です。 次の例で cl /fsanitize=address /Zi は、コマンドラインでが渡されます。

AddressSanitizer ライブラリ (.lib ファイル) は、自動的にリンクされます。 詳細については、「 AddressSanitizer language、build、およびデバッグリファレンス」を参照してください。

例-基本グローバルバッファーオーバーフロー

// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
    printf("Hello!\n");
    x[100] = 5; // Boom!
    return 0;
}

Visual Studio 2019 の開発者コマンドプロンプトを使用し main.cpp て、を使用してコンパイルする /fsanitize=address /Zi

AddressSanitizer オプションを使用してコンパイルするコマンドを示すコマンドプロンプトのスクリーンショット。

結果のをコマンドラインで実行すると、 main.exe 次に示す形式のエラーレポートが作成されます。

7つの主要な情報を強調表示する、次のような赤色の枠が表示されているとします。

基本的なグローバルオーバーフローエラーを示すデバッガーのスクリーンショット。

赤の強調表示 (上から下)

  1. メモリの安全性のバグは、グローバルバッファーオーバーフローです。
  2. ユーザー定義変数の外側に 4 バイト (32 ビット) が 格納さ れています。
  3. ストアは、 main() basic-global-overflow.cpp 7 行目のファイルで定義されている関数で実行されました。
  4. という名前の変数は、 x 3 行目の basic-global-overflow で定義されています (列 8)
  5. このグローバル変数 x のサイズは400バイトです。
  6. ストアの対象となるアドレスを記述する正確な シャドウバイト の値は、 0xf9
  7. シャドウバイトの凡例 0xf9 は、の右側に余白があることを示します。 int x[100]

注意

呼び出し履歴内の関数名は、エラー発生時にランタイムによって呼び出される Llvm のシンボル によって生成されます。

Visual Studio での AddressSanitizer の使用

AddressSanitizer は、Visual Studio IDE に統合されています。 MSBuild プロジェクトの AddressSanitizer をオンにするには、ソリューションエクスプローラーでプロジェクトを右クリックし、[ プロパティ] を選択します。 [プロパティページ] ダイアログボックスで、[構成プロパティ] [ > C/c + + 全般] を選択し、 > [ Enable AddressSanitizer ] プロパティを変更します。 [OK] を選択して変更を保存します。

[プロパティページ] ダイアログのスクリーンショット。 &quot;Enable AddressSanitizer&quot; プロパティが表示されます。

IDE からビルドするには、互換性のない オプションを選択解除します。 (またはデバッグモード) を使用してコンパイルされた既存のプロジェクトでは /Od 、次のオプションを無効にする必要がある場合があります。

デバッガーをビルドして実行するには、「 F5」と入力します。 Visual Studio では、次のウィンドウが表示されます。

グローバルバッファーオーバーフローエラーを示すデバッガーのスクリーンショット。

Visual Studio からの AddressSanitizer の使用: CMake

Windows を対象とするように作成された CMake プロジェクトの AddressSanitizer を有効にするには、次の手順を実行します。

  1. IDE の上部にあるツールバーの [ 構成 ] ドロップダウンを開き、[ 構成の管理] を選択します。

    CMake 構成ドロップダウンのスクリーンショット。

    このオプションを選択すると、[CMake プロジェクト設定エディター] が開き、ファイルの CMakeSettings.jsに保存されます。

  2. エディターで [ JSON の編集 ] リンクを選択します。 この選択により、ビューが未加工の JSON に切り替わります。

  3. プロパティ "addressSanitizerEnabled": true を追加します。

    このイメージは、その変更後に CMakeSettings.jsます。

    CMakeSettings.jsのテキストエディタービューのスクリーンショット。

  4. Ctrl + S キーを押し てこの JSON ファイルを保存し、 F5 キーを押してデバッガーで再コンパイルして実行します。

このスクリーンショットでは、CMake ビルドからエラーをキャプチャします。

CMake ビルドエラーメッセージのスクリーンショット。

AddressSanitizer クラッシュダンプ

クラウドおよび分散ワークフローで使用するために、AddressSanitizer に新機能が導入されました。 この機能により、IDE での AddressSanitizer エラーのオフライン表示が可能になります。 ライブデバッグセッションで発生する場合と同様に、エラーはソースの上にオーバーレイされます。

これらの新しいダンプファイルを使用すると、バグを分析する際の効率が向上する可能性があります。 リモートデータを再実行したり、オフラインになったコンピューターを探したりする必要はありません。

後で別のコンピューターの Visual Studio で表示できる新しい種類のダンプファイルを生成するには、次のようにします。

set ASAN_SAVE_DUMPS=MyFileName.dmp

Visual Studio 16.9 以降では、ファイルに格納されている、ソースコードの上に正確に診断された エラーを 表示でき *.dmp ます。

この新しいクラッシュダンプ機能 により、クラウドベースのワークフローまたは分散テストが可能になります。 また、この方法を使用して、あらゆるシナリオで、実用的な詳細なバグをファイルに登録することもできます。

エラーの例

AddressSanitizer は、いくつかの種類のメモリ誤用エラーを検出できます。 AddressSanitizer () コンパイラオプションを使用してコンパイルされたバイナリを実行したときに報告されるランタイムエラーの多くを次に示し /fsanitize=address ます。

例の詳細については、「 AddressSanitizer error の例」を参照してください。

Clang 12.0 との違い

MSVC は、次の2つの機能領域で Clang 12.0 と現在異なります。

  • stack-スコープ適用後 -この設定は既定でオンになっており、無効にすることはできません。
  • スタック使用-戻り値 -この機能には追加のコンパイラオプションが必要であり、設定でのみ使用することはできません ASAN_OPTIONS

これらの決定は、この最初のバージョンを配信するために必要なテストマトリックスを減らすために行われました。

Visual Studio 2019 16.9 で誤検知につながる可能性がある機能は含まれていませんでした。 この作業分野は、数十年の既存のコードとの相互運用を検討する際に必要な、効果的なテストの整合性を強制しています。 今後のリリースでは、より多くの機能を考慮することができます。

詳細については、「MSVC を使用した AddressSanitizer のビルド」を参照してください。

既存の業界ドキュメント

これらの言語およびプラットフォームに依存する AddressSanitizer テクノロジの実装については、広範なドキュメントが既に存在します。

この AddressSanitizer のよる著書ペーパーでは、実装について説明しています。

関連項目

AddressSanitizer の既知の問題
AddressSanitizer ビルドと言語リファレンス
AddressSanitizer ランタイムリファレンス
AddressSanitizer shadow bytes
AddressSanitizer クラウドまたは分散テスト
AddressSanitizer デバッガーの統合
AddressSanitizer エラーの例