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)