EXP04-C. 構造体を含むバイト単位の比較を行わない
このガイドラインは廃止され、以下のガイドラインに統合されました。
構造体は、メモリ上に適切にアラインされるようデータでパディングされるかもしれない。パディングの中身と量は指定されない。(C 標準の附属書 J、セクション J.1 の「未規定の動作」の 10 を参照。[ISO/IEC 9899:2011])そのため、構造体同士をバイト単位で比較しても間違った結果が得られる可能性がある。[Summit 1995]
違反コード
以下のコード例では、memcmp()
を使用して二つの構造体を比較している。
struct my_buf { char buff_type; size_t size; char buffer[50]; }; bool buf_equal(const struct my_buf *s1, const struct my_buf *s2) { return 0 == memcmp(s1, s2, sizeof *s1); } void f (void) { my_buf a = { 0, 0, "" }; my_buf b; memset(&b, 0, sizeof b); assert(true == buf_equal(&a, &b)); /* 保持する必要はない */ /* ... */ }
多くの計算機は、値が適切にアラインされている場合に最も効率的にメモリ上の値にアクセスする。たとえば、バイトアドレッシング方式の計算機では、2バイトの整数short
は偶数アドレスに配置するのが最も効率的であり、4バイト整数 long
は4の倍数のアドレスに配置するのが最も効率的である。計算機によってはアラインされていないエータへのアクセスができず、すべてのデータが適切にアラインされることを要求する場合もある。
この例にある構造体の場合、コンパイラは通常、size_t
フィールドが適切にアラインされるように char
と size_t
フィールドの間に名前のない未使用の穴をあける。このように先頭のメンバフィールドから順番にアラインすることで、もっとも厳しいアラインメント要求下でも、構造体自身が適切にアラインされると考えられる。コンパイラはmalloc()
が行うのと同じように、メモリに配置する構造体がアラインされていることを保証する。
これらの構造体がどのように初期化されるかに関係なく、構造体のフィールドの値は同じなのに、構造化パディングのせいで memcmp()
は等しくないと評価するかもしれない。パディングされたメモリは初期化されておらず、任意のコンテンツを含む可能性がある。この例に限って言うと、初期化時に memset()
を呼び出してメンバをすべてゼロで初期化しているにもかかわらず、文字配列 buffer
に割り当てられた未使用部分のメモリのせいでオブジェクト a
と b
が等しくないと評価されるかもしれない。どちらの方法でも、パディングビットの値への影響は保証されない。
適合コード
以下の適合コードでは、buf_compare
関数を書き直し、フィールド毎の比較を行っている。
struct my_buf { char buff_type; size_t size; char buffer[50]; }; bool buf_equal(const struct my_buf *s1, const struct my_buf *s2) { if ( s1->buff_type != s2->buff_type || s1->size != s2->size) return false; return 0 == strcmp(s1->buffer, s2->buffer); }
リスク評価
構造体を正しく比較し損ねると予期せぬプログラムの動作につながる恐れがある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
EXP04-C |
中 |
低 |
高 |
P2 |
L3 |
自動検出
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
関連するガイドライン
CERT C++ Secure Coding Standard | EXP04-CPP. Do not perform byte-by-byte comparisons between classes or structs |
ISO/IEC TS 17961 (ドラフト) | Comparison of padding data [padcomp] |
参考資料
[Dowd 2006] | Chapter 6, "C Language Issues" ("Structure Padding," pp. 284–287) |
[Kerrighan 1988] | Chapter 6, "Structures" ("Structures and Functions," p. 129) |
[Summit 1995] | Question 2.8, Question 2.12 |
翻訳元
これは以下のページを翻訳したものです。
EXP04-C. Do not perform byte-by-byte comparisons involving a structure (revision 101)