-fmudflap
GCCで試しましたか?これらは実行時チェックですが、とにかく実行時に計算されたインデックスを処理する必要がある場合が多いため、便利です。黙って作業を続ける代わりに、それらのバグについて通知します。
-fmudflap -fmudflapth -fmudflapir
それをサポートするフロントエンド (C および C++) の場合、すべての危険なポインター/配列の逆参照操作、いくつかの標準ライブラリの文字列/ヒープ関数、および範囲/有効性テストを備えたその他の関連する構成要素をインストルメント化します。このようにインストルメント化されたモジュールは、バッファ オーバーフロー、無効なヒープの使用、およびその他のクラスの C/C++ プログラミング エラーの影響を受けないようにする必要があります。インスツルメンテーションは、リンク時に -fmudflap が指定された場合にプログラムにリンクされる別のランタイム ライブラリ (libmudflap) に依存します。インストルメント化されたプログラムの実行時の動作は、MUDFLAP_OPTIONS 環境変数によって制御されます。オプションについては、「env MUDFLAP_OPTIONS=-help a.out」を参照してください。
プログラムがマルチスレッドの場合は、-fmudflap の代わりに -fmudflapth を使用してコンパイルおよびリンクします。計測器がポインターの読み取りを無視する必要がある場合は、-fmudflap または -fmudflapth に加えて -fmudflapir を使用します。これにより、インスツルメンテーションが少なくなり (したがって実行が速くなり)、あからさまなメモリ破損書き込みに対するある程度の保護が提供されますが、誤って読み取られたデータがプログラム内で伝播することを許してしまいます。
あなたの例でマッドフラップが私に与えるものは次のとおりです。
[js@HOST2 cpp]$ gcc -fstack-protector-all -fmudflap -lmudflap mudf.c
[js@HOST2 cpp]$ ./a.out
*******
mudflap violation 1 (check/write): time=1229801723.191441 ptr=0xbfdd9c04 size=56
pc=0xb7fb126d location=`mudf.c:4:3 (main)'
/usr/lib/libmudflap.so.0(__mf_check+0x3d) [0xb7fb126d]
./a.out(main+0xb9) [0x804887d]
/usr/lib/libmudflap.so.0(__wrap_main+0x4f) [0xb7fb0a5f]
Nearby object 1: checked region begins 0B into and ends 16B after
mudflap object 0x8509cd8: name=`mudf.c:3:7 (main) a'
bounds=[0xbfdd9c04,0xbfdd9c2b] size=40 area=stack check=0r/3w liveness=3
alloc time=1229801723.191433 pc=0xb7fb09fd
number of nearby objects: 1
[js@HOST2 cpp]$
たくさんのオプションがあります。たとえば、違反時に gdb プロセスをフォークしたり、プログラムがリークした場所を表示したり (を使用-print-leaks
)、初期化されていない変数の読み取りを検出したりできます。MUDFLAP_OPTIONS=-help ./a.out
オプションのリストを取得するために使用します。マッドフラップはアドレスのみを出力し、ソースのファイル名や行は出力しないので、ちょっとした gawk スクリプトを書きました:
/^ / {
file = gensub(/([^(]*).*/, "\\1", 1);
addr = gensub(/.*\[([x[:xdigit:]]*)\]$/, "\\1", 1);
if(file && addr) {
cmd = "addr2line -e " file " " addr
cmd | getline laddr
print $0 " (" laddr ")"
close (cmd)
next;
}
}
1 # print all other lines
これにマッドフラップの出力をパイプすると、ソースファイルと各バックトレース エントリの行が表示されます。
また-fstack-protector[-all]
:
-fstack-protector
スタック破壊攻撃などのバッファ オーバーフローをチェックする追加のコードを発行します。これは、脆弱なオブジェクトを持つ関数にガード変数を追加することによって行われます。これには、alloca を呼び出す関数と、8 バイトを超えるバッファーを持つ関数が含まれます。ガードは、関数に入るときに初期化され、関数が終了するときにチェックされます。ガード チェックが失敗すると、エラー メッセージが出力され、プログラムが終了します。
-fstack-protector-all
-fstack-protector と同様ですが、すべての機能が保護されています。