パスワードを忘れた? アカウント作成
733944 journal

pasasの日記: sprintf 関数と snprintf 関数

日記 by pasas

C で文字列のフォーマットを行うときに、sprintf() 関数を使用するプログラマがいる。
例えば、

int main( void) {
    int a = 12345;
    char buf[ 10 ];

    sprintf( buf, "0x%04X", a);
}

なんてすると、buf に 12345 を 16 進数に変換したモノが文字列として入る。
ただ、sprintf 関数には危険がある。

例えば、

int main( int argc, char *argv[]) {
    char buf[ 30 ];

    if( argc < 2 ) exit(-1);
    sprintf( buf, "Input string = %s", argv[1]);
}

なんてすると、引数が長大になったときにバッファオーバーフローが発生し、場合によってはセキュリティホールになる。
そのため sprintf 関数は使うべきではないと思う。

代わりに snprintf 関数を使うべきだと思う。
つまり、

int main( int argc, char *argv[]) {
    char buf[ 30 ];

    if( argc < 2 ) exit(-1);
    snprintf( buf, sizeof( buf), "Input string = %s", argv[1]);
}

という感じ。
同様の理由から gets() は使わずに fgets() を使うべきだと思う。
ちなみに snprintf 関数は返値から、すべての文字列が書き込まれたかを確認することができるのでチェックも忘れずに。
(返値は glibc のバージョンによって違う。)

プログラマのちょっとした心がけがバグとセキュリティホールを無くすことにつながってくれればいいな。

typodupeerror

UNIXはシンプルである。必要なのはそのシンプルさを理解する素質だけである -- Dennis Ritchie

読み込み中...