FIO17-C. fread() を使用するときは、null 終端文字に依存しない
C 言語規格 [ISO/IEC 9899:1999] で定義されている fread() 関数は、読み取った文字列を明示的に null 終端しない。
構文
size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream)機能
fread 関数は、stream が指すストリームから、最大 nmemb 個の大きさ size の要素を、ptr が指す配列に読み取る。
ファイルの内容に null 終端された文字列が含まれていても、nmemb が文字列の長さより短い場合は、fread() 関数は nmemb 文字以降を読み取らない。fread() は読み取った文字列の終端に null 文字を追加しない。
違反コード
ファイル内に null 終端された文字列があり、null 終端バイト文字列を抽出する必要があると仮定する。
#include <stdio.h> #include <stdlib.h> int main (void) { FILE *fp; size_t size; long length; char *buffer; fp = fopen("file.txt", "rb"); if (fp == NULL) { /* ファイルオープンエラーの処理 */ } /* ファイルサイズの取得 */ if (fseek(fp, 0, SEEK_END) != 0) { /* fseek エラーの処理 */ } length = ftell(fp); if (fseek(fp, 0L, SEEK_SET) != 0) { /* fseek エラーの処理 */ } /* ファイル全体を格納するメモリを割り当てる */ buffer = (char*) malloc(length); if (buffer == NULL) { /* メモリ割り当てエラーの処理 */ } /* size に値を設定 */ if (fread(buffer, 1, size, fp) < size) { /* ファイル読み取りエラーの処理 */ } fclose(fp); return 0; }
size がファイル(file.txt)全体の長さよりも短い場合は、buffer は正しく null 終端されない。
適合コード
上記のコード例を修正するには、buffer のサイズをファイル全体の長さと比較して、size が length と一致しない場合をエラーとして識別する必要がある。現時点ではこのエラーの処理はプログラマに委ねられている。
#include <stdio.h> #include <stdlib.h> int main (void) { FILE *fp; size_t size; long length; char *buffer; fp = fopen("file.txt", "rb"); if (fp == NULL) { /* ファイルオープンエラーの処理 */ } /* ファイルサイズの取得 */ if (fseek(fp, 0, SEEK_END) != 0) { /* fseek エラーの処理 */ } length = ftell(fp); if (fseek(fp, 0L, SEEK_SET) != 0) { /* fseek エラーの処理 */ } /* ファイル全体を格納するメモリを割り当てる */ buffer = (char*) malloc(length); if (buffer == NULL) { /* メモリ割り当てエラーの処理 */ } /* ... ここで size を設定する ... */ if (length != size) { /* size がファイルの長さでない場合の処理 */ } /* ... 追加のコード ... */ if (fread(buffer, 1, size, fp) < size) { /* ファイル読み取りエラーの処理 */ } fclose(fp); return 0; }
リスク評価
fread() 関数を使って入力ストリームを読み取る際、読み取る文字列は fread() 関数によって明示的に null 終端されない。そのため、バッファへの書き込み操作はオーバーランを引き起こし、プログラムを異常終了させるおそれがある。
レコメンデーション | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
FIO17-C | 低 | 高 | 中 | P6 | L2 |
参考情報
- [ISO/IEC 9899:1999] Section 7.19.8.1, "The fread function"
翻訳元
これは以下のページを翻訳したものです。
FIO17-C. Do not rely on an ending null character when using fread()