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()



