組み込みソフトウェア・バグの分類学,その傾向と対策 ――ツールを利用してバグ対策の手間を軽減
《バグ・クラス No.2》
バッファ・オーバラン
●バッファ・オーバランとは?
C言語にはメモリを直接操作できるという特徴があり,組み込みソフトウェアを開発するうえで有効ですが,逆に危険な操作になる可能性もあるので注意が必要です.
バッファ・オーバランは,データ構造に割り当てられたメモリの境界外にデータを書き込んだときに発生します.
●バッファ・オーバランの例
簡単な例:
/* メモリ領域の終端を超えたデータに対する書き込みをしています */
char buf[10];
...
buf[10] = 'a';
●バッファ・オーバランの対策
関数の引き数などで渡されたデータ(ポインタ)を転送する前に,それが領域長内に収まることを確認するために,以下のような検査用のロジックを省略せずに記述しましょう.
If(MAXSIZE - 1 < strlen(s))
return ERROR;
●静的解析ツールによるチェック
バッファ・オーバランは,基本的に,実行時の境界外書き込みによって,発生する現象なので,検出するのが難しいとされています.コンパイラでは,バッファ・オーバランの原因となるすべてのソフトウェア欠陥を,コンパイル時には指摘してくれません.コーディングルールチェッカでも,同様に,実行時のメモリ処理が関連してくるようなケースでは,検出することが難しくなります.
図3にCodeSonarによる解析例を示します.これはオープン・ソースのgnuchessプログラムを解析し,実行時におけるバッファ・オーバランを検出した例です.
図3 バッファ・オーバランの解析例(Buffer Overrun Warning)※ 図をクリックすると拡大できます
このバッファ・オーバランは,1774行目で発生しています.1773行目の命令部分が,その原因になります.(プログラム中のコメントにもかかわらず)割り当てられるメモリの合計が間違って計算されています.実際にはmalloc( )で確保したメモリ領域を指すポインタに1が足されているため,strcpy( )が実行され,sの内容をmalloc( )で確保した領域にコピーする際に,バッファ・オーバランが発生する可能性があります.
また,このコードでは,ほかにも別のバグが報告されています.それは,malloc( )による戻り値をチェックしていない(参照後のNULLテスト)という内容です.