BLOGTIMES
2022/10/06

gcc で配列の境界外アクセスをチェックする

  c  programming 
このエントリーをはてなブックマークに追加

gcc で練習用のプログラムをコンパイルしていろいろ試していたら、配列の境界外アクセスでも意外と SIGSEGV しないパターンが多いことに気づきました。

test.c

#include <stdio.h> int main(void){ int a[10] = {1,2,3}; int b[2] = {4,5}; printf("a[0] %p\n", &a[0]); printf("b[2] %p\n", &b[2]); b[2] = 9; // a[0] アドレスと同じなので、a[0]への代入になる for(int i = 0; i < 3; i++){ printf("a[%d] = %d\n",i,a[i]); } }

例えば、上記のプログラムを実行すると a[0]9 になってしまいます。

$ gcc test.c $ ./a.out a[0] 0x7fffd1363e80 b[2] 0x7fffd1363e80 a[0] = 9 a[1] = 2 a[2] = 3

初学者だとこういう間違いが非常に多いので、コンパイラの設定でチェックできる方法がないか調べてみたところ、最近の gcc には AddressSanitizer*1 という仕組みが入っているようです。

仕組みについては USENIX ATC'12 で発表された論文と GitHub のリポジトリがあります。

上記と同じプログラムをサニタイザありでコンパイルして実行すると、こんな感じで runtime error が出るようになります。

$ gcc -g -fsanitize=bounds test.c $ ./a.out a[0] 0x7ffdff286da0 b[2] 0x7ffdff286da0 test.c:9:3: runtime error: index 2 out of bounds for type 'int [2]' a[0] = 9 a[1] = 2 a[2] = 3

トラックバックについて
Trackback URL:
お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/13528
Trackbacks
このエントリにトラックバックはありません
Comments
愛のあるツッコミをお気軽にどうぞ。[policy]
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントはありません
Comments Form

コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。

OpenID を使ってログインすることができます。

Identity URL: Yahoo! JAPAN IDでログイン