スタック セーフティ解析

はじめに

スタック セーフティ解析により、スタックに割り当てられた変数がメモリアクセスバグに対して「セーフ」と見なせるかどうかが判別されます。

この解析の主な目的は、サニタイザーが「セーフ」な変数を不必要に計装しないようにすることです。SafeStack が最初のユーザーになります。

「セーフ」な変数は、スコープ外で使用できない変数(例: use-after-return)や、範囲外のアクセスができない変数と定義できます。将来的には、他の変数プロパティを追跡するように拡張できます。たとえば、使用されていないメモリの使用のチェックを最適化するために、変数が読み取りごとに常に初期化されていることを確認するチェックを実装で拡張する予定です。

仕組み

この解析は 2 段階で実装されています

関数内または「ローカル」段階では、関数の内側で深く検索し、各アロカの使用箇所をすべて収集します。これにはロード/ストア、関数の引数としての使用が含まれます。この段階では、アロカのどの部分が関数自体で使用されているかがわかりますが、別の関数に引数として渡した後はどうなるかわかりません。

関数間または「グローバル」段階では、関数の引数として渡された後のアロカに何が起こるのかが解決されます。この段階では、単一のモジュール内の関数呼び出しで深く検索し、アロカの使用状況を関数呼び出しで伝播させます。

ThinLTO で使用する場合、グローバル段階はモジュール サマリー インデックス上で全体プログラムの解析を実行します。

テスト

この解析は、lit テストでカバーされています。

実際には「セーフ」であるにもかかわらず、変数を「アンセーフ」に誤って分類してもユーザーが許容できるのではないかと考えています。これにより、コードの効率が悪くなる場合があります。ただし、「セーフ」であるという誤った分類は認められません。それが原因で、サニタイザーが計装されたコードでの実際のバグを見逃してしまう場合があります。これを回避するため、追加の検証ツールが必要です。

この検証には AddressSanitizer が役立ちます。いつものようにすべての変数を記録できますが、さらに ASanStackVariableDescription にスタックセーフの情報を格納することもできます。AddressSanitizer が「セーフ」変数でバグを検出した場合、さらにレポートを作成して、ユーザーにスタックセーフの分析に失敗した可能性があり、コンパイラのバグを確認する必要があることを伝えることができます。