Last Update 2021/05/16
-Wformat-overflow(-Wformat-overflow=)
バッファオーバーフローが発生する可能性が高いフォーマット文字列を伴う関数呼び出しに関する警告を出力
テスト概要
-Wformat-overflow、-Wformat-overflow=1、=2をそれぞれ指定した場合の出力を比較
実行環境
GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1
GNU C Library 2.28
GNU Binutils 2.31.1
コード例・出力内容中の表記
・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
使用ファイル
sample.c
#include <stdio.h>
int main(void)
{
int n = 123456;
char c1[5];
char c2[11];
char c3[12];
/* バッファオーバーフローの可能性の無い関数呼び出し */
sprintf(c1, "test");
/* バッファオーバーフローが発生する関数呼び出し */
sprintf(c1, "test\n");
/* 生成される文字列長が最小でもバッファオーバーフローが発生する関数呼び出し */
sprintf(c1, "test%i", n);
/* 変数の値次第ではバッファオーバーフローの可能性が有る関数呼び出し */
sprintf(c2, "%i", n);
/* 生成される文字列長が最大でもバッファオーバーフローの可能性の無い関数呼び出し */
sprintf(c3, "%i", n);
return 0;
}
動作テスト
-Wformat-overflow、-Wformat-overflow=1、=2をそれぞれ指定した場合の出力を比較
オプション無しで実行
$ gcc sample.c
$ 一切警告は出力されない
-Wformat-overflowオプションを指定して実行
$ gcc -Wformat-overflow sample.c
sample.c: In function ‘main’:
sample.c:14:21: warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow=]
sprintf(c1, "test\n"); 文字列最後のヌル文字が格納先終端を越えて書き込まれる旨の警告
^
sample.c:14:2: note: ‘sprintf’ output 6 bytes into a destination of size 5
sprintf(c1, "test\n"); 出力6バイトに対し格納先サイズは5バイト(確実に超過)
^~~~~~~~~~~~~~~~~~~~~
sample.c:17:21: warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow=]
sprintf(c1, "test%i", n); 文字列最後のヌル文字が格納先終端を越えて書き込まれる旨の警告
^
sample.c:17:2: note: ‘sprintf’ output between 6 and 16 bytes into a destination of size 5
sprintf(c1, "test%i", n); 出力6〜16バイトに対し格納先サイズは5バイト(確実に超過)
^~~~~~~~~~~~~~~~~~~~~~~~
$
-Wformat-overflow=1オプションを指定して実行
$ gcc -Wformat-overflow=1 sample.c
sample.c: In function ‘main’:
sample.c:14:21: warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow=]
sprintf(c1, "test\n");
^
sample.c:14:2: note: ‘sprintf’ output 6 bytes into a destination of size 5
sprintf(c1, "test\n");
^~~~~~~~~~~~~~~~~~~~~
sample.c:17:21: warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow=]
sprintf(c1, "test%i", n);
^
sample.c:17:2: note: ‘sprintf’ output between 6 and 16 bytes into a destination of size 5
sprintf(c1, "test%i", n);
^~~~~~~~~~~~~~~~~~~~~~~~
$ -Wformat-overflowオプションと同一の出力内容
-Wformat-overflow=2オプションを指定して実行
$ gcc -Wformat-overflow=2 sample.c
sample.c: In function ‘main’:
sample.c:14:21: warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow=]
sprintf(c1, "test\n");
^
sample.c:14:2: note: ‘sprintf’ output 6 bytes into a destination of size 5
sprintf(c1, "test\n");
^~~~~~~~~~~~~~~~~~~~~
sample.c:17:19: warning: ‘%i’ directive writing between 1 and 11 bytes into a region of size 1 [-Wformat-overflow=]
sprintf(c1, "test%i", n);
^~
sample.c:17:2: note: ‘sprintf’ output between 6 and 16 bytes into a destination of size 5
sprintf(c1, "test%i", n);
^~~~~~~~~~~~~~~~~~~~~~~~
sample.c:20:17: warning: ‘sprintf’ may write a terminating nul past the end of the destination [-Wformat-overflow=]
sprintf(c2, "%i", n); 文字列最後のヌル文字が格納先終端を越える可能性がある旨の警告
^
sample.c:20:2: note: ‘sprintf’ output between 2 and 12 bytes into a destination of size 11
sprintf(c2, "%i", n); 出力2〜12バイトに対し格納先サイズは11バイト(超過の可能性有り)
^~~~~~~~~~~~~~~~~~~~
$ -Wformat-overflow=1に加え、変数の値次第でオーバーフローする可能性のある場合も警告を出力