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

FIO36-C. fgets() が改行文字を読み取ると仮定しない

FIO36-C. fgets() が改行文字を読み取ると仮定しない

fgets() 関数は通常、改行で終わる行を入力ストリームから読み込むために使用される。fgets() 関数は、サイズ引数をとり、最大で size-1 文字をストリームからコピー先バッファにコピーする。プログラマがコピー先文字列の最後の文字に必ず改行が入っていると思い込むと、切り捨てエラーが発生する可能性がある。

違反コード

以下のコード例では、入力行から末尾の改行(\n)を削除しようとしている。

char buf[BUFSIZ + 1];

if (fgets(buf, sizeof(buf), fp)) {
  if (*buf) { /* FIO37-Cを参照 */
    buf[strlen(buf) - 1] = '\0';
  }
}
else {
  /* エラー処理 */
}

しかし、buf の最後の文字が改行でない場合、このコードは有効な文字を上書きしてしまう。

適合コード

以下の解決法では、strchr() を使用して文字列中の改行文字(それが存在する場合)を置き換えている。fgetws() が使用されている場合は、同様に wcschr() を使用する。

char buf[BUFSIZ + 1];
char *p;

if (fgets(buf, sizeof(buf), fp)) {
  p = strchr(buf, '\n');
  if (p) {
   *p = '\0';
  }
}
else {
  /* エラー処理 */
}

他の解決法としてすぐ思いつくのは、バッファに1文字分のスペースを残しておいて、改行コードがコピーされていなかったら null 終端文字の前に改行を追加するという方法である。しかし、このアプローチは危険である。実際には意図されていなかった入力を暗黙的に受けつけてしまい、予測できない結果となる恐れがあるからである。

リスク評価

改行文字が読み取られると想定すると、データが切り捨てられる可能性がある。

ルール 深刻度 可能性 修正コスト 優先度 レベル
FIO36-C P12 L1
参考情報
翻訳元

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

FIO36-C. Do not assume a newline character is read when using fgets()

Top へ

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