JPCERT コーディネーションセンター

ERR01-C. errno ではなく ferror() を使って FILE ストリームエラーを検査する

ファイルストリームにエラーが発生したかどうかを検査する場合は、errno ではなく ferror() を使うこと(たとえば、stdio 関数群を複数回呼び出した後など)。ferror() 関数は、指定されたストリームのエラー表示子を判定し、ストリームのエラー表示子がセットされている場合、そしてその場合に限り、0以外の値を返す。

違反コード

stdio 関数群の実装の多くは、 stdout が端末の場合に少しだけ動作が変わる。端末かどうかを判定するために、これらの実装は stdout が端末でない場合に失敗となる(ENOTTY が返される)何らかの処理を実行する。出力操作は正常に終了しても、errnoENOTTY のままである。この動作はやや混乱を招く可能性があるが、プログラムにとっては、errno の値はエラーが報告された後にのみ意味を持つため、厳密には間違いではない。より正確にいうと、errno は、エラー時に errno を設定するライブラリ関数がエラーコードを返した後にのみ意味を持つ。

errno = 0;
printf("This\n");
printf("is\n");
printf("a\n");
printf("test.\n");
if (errno != 0) {
  fprintf(stderr, "printf failed: %s\n", strerror(errno));
}
適合コード

以下の解決法は、ferror() を使用してエラーを検出している。また、ある printf() が操作に失敗したとして、その後の printf() が(操作に失敗したかどうかに関係なく)errno を変更している可能性があるため、一連のライブラリ関数の呼び出しが全て終了した後では、最初に失敗した原因を正しく特定できない。

printf("This\n");
printf("is\n");
printf("a\n");
printf("test.\n");
if (ferror(stdout)) {
  fprintf(stderr, "printf failed\n");
}
リスク評価

ライブラリ関数を複数回呼び出した後で errno を検査すると、誤ったエラーが報告される可能性があり、結果として誤ったプログラム動作を引き起こす可能性がある。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

ERR01-C

P6

L2

自動検出

ツール

バージョン

チェッカー

説明

ECLAIR

1.1

stlibuse

実装済み

関連するガイドライン
CERT C++ Secure Coding Standard ERR01-CPP. Use ferror() rather than errno to check for FILE stream errors
参考資料
[Horton 1990] Section 14, p. 254
[Koenig 1989] Section 5.4, p. 73
翻訳元

これは以下のページを翻訳したものです。

ERR01-C. Use ferror() rather than errno to check for FILE stream errors (revision 45)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter