メインコンテンツ

CERT C: Rec.FIO11-C

Take care when specifying the mode parameter of fopen()

説明

ルール定義

fopen() のモード パラメーターは慎重に指定します。1

Polyspace 実装

ルール チェッカーは、"ファイル アクセス モードまたはステータスが不適切です" をチェックします。

すべて展開する

問題

ファイル アクセス モードまたはステータスが不適切ですは、fopen または open グループの関数を、無効または互換性のないファイル アクセス モードで、ファイル作成フラグで、あるいはファイル ステータス フラグを引数として使用した場合に発生します。たとえば、関数 open の場合、有効な例は次のとおりです。

  • 有効なアクセス モードには、O_RDONLYO_WRONLY および O_RDWR が含まれる。

  • 有効なファイル作成フラグには、O_CREATO_EXCLO_NOCTTY および O_TRUNC が含まれる。

  • 有効なファイル ステータス フラグには、O_APPENDO_ASYNCO_CLOEXECO_DIRECTO_DIRECTORYO_LARGEFILEO_NOATIMEO_NOFOLLOWO_NONBLOCKO_NDELAYO_SHLOCKO_EXLOCKO_FSYNCO_SYNC などが含まれる。

欠陥は次のような状態で発生します。

状態リスク修正方法

関数 fopen に、空であるか無効なアクセス モードが渡される。

ANSI® C 標準によると、fopen への有効なアクセス モードは次のとおり。

  • r,r+

  • w,w+

  • a,a+

  • rb, wb, ab

  • r+b, w+b, a+b

  • rb+, wb+, ab+

fopen では、無効なアクセス モードについて動作が未定義となる。

実装によっては、アクセス モードの次のような拡張が許可されている。

  • GNU®: rb+cmxe,ccs=utf

  • Visual C++®: a+t (ここで、t にはテキスト モードを指定)

ただし、アクセス モードの文字列は、有効なシーケンスのいずれかで始まらなければならない。

fopen に有効なアクセス モードを渡す。
ステータス フラグ O_APPEND が、O_WRONLY または O_RDWR のいずれかと組み合わされずに関数 open に渡される。

O_APPEND は、ファイルの末尾に新規の内容が追加されることを示す。しかし、O_WRONLY または O_RDWR がないとファイルへの書き込みはできない。

関数 open は、この論理エラーについては -1 を返さない。

O_APPEND|O_WRONLY または O_APPEND|O_RDWR をアクセス モードとして渡す。
ステータス フラグ O_APPEND および O_TRUNC がともに関数 open に渡される。

O_APPEND は、ファイルの末尾に新規の内容が追加されることを示す。しかし、O_TRUNC は、ファイルを打ち切ってゼロにすることを示す。したがって、この 2 つのモードは一緒に動作できない。

関数 open は、この論理エラーについては -1 を返さない。

意図することに応じて、2 つのモードのいずれかを渡す。
ステータス フラグ O_ASYNC が関数 open に渡される。 特定の実装では、モード O_ASYNC によって信号駆動の I/O 操作が有効にされない。代わりに、fcntl(pathname, F_SETFL, O_ASYNC); を使用する。

修正方法

修正方法は欠陥の根本原因によって異なります。多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

以下の修正例を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - fopen での無効なアクセス モード
#include <stdio.h>

void func(void) {
    FILE *file = fopen("data.txt", "rw"); //Noncompliant
    if(file!=NULL) {
        fputs("new data",file);
        fclose(file);
    }
}

この例では、アクセス モード rw は無効です。r はファイルを読み取り用に開くことを示し、w は書き込み用に新規ファイルを作成することを示しますが、この 2 つのアクセス モードには互換性がないためです。

修正 — rw のいずれか一方をアクセス モードとして使用

1 つの修正方法として、意図することに応じたアクセス モードを使用します。

#include <stdio.h>

void func(void) {
    FILE *file = fopen("data.txt", "w");
    if(file!=NULL) {
        fputs("new data",file);
        fclose(file);
    }
}

チェック情報

グループ: Rec.09.入出力 (FIO)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.