次の方法で共有


エラー: stack-use-after-return

Address Sanitizer エラー: 戻り後のスタック メモリの使用

このチェックでは、追加のコンパイラ オプションである /fsanitize-address-use-after-return によってアクティブ化され、環境変数 ASAN_OPTIONS=detect_stack_use_after_return=1 を設定してコードを生成する必要があります。

このチェックにより、アプリケーションの速度が大幅に低下する可能性があります。 リターンの後にサポートが使用する Clang の概要と、より大きなパフォーマンス コストについて考えます。

重要

追加のコンパイラ オプション /fsanitize-address-use-after-return を使用してオブジェクト ファイルを作成する場合、コンパイラによって生成されたコードは、スタック フレームの割り当て方法について実行時に決定します。 環境変数 ASAN_OPTIONSdetect_stack_use_after_return に設定されていない場合、コードはそれ自体で /fsanitize=address を使用するよりも遅くなります。 alloca() を使用してフレームの一部に領域を割り当てるスタック フレームの一部から追加のオーバーヘッドが引き続き発生するので、処理が遅くなります。 use-after-return エラーの処理が完了したら、これらのオブジェクト ファイルを削除してください。

例 - 単純な C

// example1.cpp
// stack-use-after-return error
volatile char* x;

void foo() {
    char stack_buffer[42];
    x = &stack_buffer[13];
}

int main() {

    foo();
    *x = 42; // Boom!

    return (*x == 42);
}

この例をビルドしてテストするには、Visual Studio 2019 バージョン 16.9 以降の開発者コマンド プロンプトで次のコマンドを実行します。

cl example1.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example1.exe

結果のエラー - 単純な C

例 1 のスタック使用後のエラーが表示されているデバッガーのスクリーンショット。

例 - C++ とテンプレート

// example2.cpp
// stack-use-after-return error
#include <stdlib.h>

enum ReadOrWrite { Read = 0, Write = 1 };

struct S32 {
    char x[32];
};

template<class T>
T* LeakStack() {
    T t[100];
    static volatile T* x;
    x = &t[0];
    return (T*)x;
}

template<class T>
void StackUseAfterReturn(int Idx, ReadOrWrite w) {
    static T sink;
    T* t = LeakStack<T>();
    if (w)
        t[100 + Idx] = T();
    else
        sink = t[100 + Idx];
}

int main(int argc, char* argv[]) {

    if (argc != 2) return 1;
    int kind = atoi(argv[1]);

    switch (kind) {
    case 1: StackUseAfterReturn<char>(0, Read); break;
    case 2: StackUseAfterReturn<S32>(0, Write); break;
    }
    return 0;
}

この例をビルドしてテストするには、Visual Studio 2019 バージョン 16.9 以降の開発者コマンド プロンプトで次のコマンドを実行します。

cl example2.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi /Od
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example2.exe 1

ASAN は動的分析の一種であり、実際に実行された不適切なコードのみを検出できることを意味します。 オプティマイザーは、 t[100 + Idx] または sink の値が使用されないことを判断し、割り当てを省略できます。 その結果、この例では /Od フラグが必要です。

結果のエラー - C++ とテンプレート

例 2 のスタック使用後のエラーが表示されているデバッガーのスクリーンショット。

関連項目

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