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

API04-C. 一貫性があり使いやすいエラー検査方法を提供する

関数は一貫性があり使いやすいエラー検査方法を提供すべきである。インタフェースが複雑だとプログラマに無視されることがあり、結果的にエラー検査の行われないコードが生み出されてしまう。また、一貫性のないインタフェースは誤用されやすく使用しづらいため、コードの品質低下と開発コストの増大につながる。

違反コード (strlcpy())

strlcpy() 関数は、null 終端された文字列を配列へコピーする。この関数は、strcpy() に取って代わる、より安全で一貫した誤用しにくい設計になっている。

strlcpy() 関数は、作成しようとする文字列の長さ(コピー元の文字列の長さ)を返す。

パス名の作成時に文字列の切り捨てを検出するには、例えば次のようなコードを書くかもしれない。

char *dir, *file, pname[MAXPATHLEN];

/* ... */

if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname)) {
  /* コピー元文字列が長すぎる場合のエラー処理 */
}
適合コード (strcpy_m())

CERT managed string library [Burch 2006] は、関数の返り値として常にステータスコードを返すことでエラーに対応する。この方法により、関数のステータスコードはチェックされるようになる。if 文の条件式としてこの関数を呼び出し、関数がエラーを返した場合に適切な処理を行えるからだ。

managed string 関数の1つである strcpy_m() は、コピー元の managed string をコピー先の managed string へコピーする。

errno_t retValue; 
string_m dest, source;  

/* ... */

if (retValue = strcpy_m(dest, source)) { 
  fprintf(stderr, "Error %d from strcreate_m.\n", retValue);
}

この方法の最大の欠点は、関数はステータスコード以外の値を返せないことである。その結果、関数が返す(ステータス以外の)値はすべて、参照渡しの引数として返されなければならず、ゆえに関数呼び出しを入れ子にすることができない。入れ子の関数呼出しは、ステータスコードを検査しようとするプログラマの意図と矛盾するため、これは必要なトレードオフであると言える。

リスク評価

関数が一貫性があり使いやすいエラー検査方法を提供しないと、プログラム内で型に関するエラーが発生する可能性がある。

ルール

深刻度

可能性

修正コスト

優先度

レベル

API04-C

P4

L3

関連するガイドライン
ISO/IEC 9945:2003  
ISO/IEC 23360-1:2006  
ISO/IEC TR 24731-1  
ISO/IEC TR 24731-2  
MISRA C:2012 Rule 21.3 (required)
Directive 4.12 (required)
MITRE CWE CWE-754, Improper check for unusual or exceptional conditions
参考資料
[Burch 2006]  
[CERT 2006c]  
[Miller 1999]  
[Seacord 2013] Chapter 2, "Strings"
翻訳元

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

API04-C. Provide a consistent and usable error-checking mechanism (revision 23)

Top へ

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