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

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フィールドが適切にアラインされるように charsize_t フィールドの間に名前のない未使用の穴をあける。このように先頭のメンバフィールドから順番にアラインすることで、もっとも厳しいアラインメント要求下でも、構造体自身が適切にアラインされると考えられる。コンパイラはmalloc() が行うのと同じように、メモリに配置する構造体がアラインされていることを保証する。

これらの構造体がどのように初期化されるかに関係なく、構造体のフィールドの値は同じなのに、構造化パディングのせいで memcmp() は等しくないと評価するかもしれない。パディングされたメモリは初期化されておらず、任意のコンテンツを含む可能性がある。この例に限って言うと、初期化時に memset() を呼び出してメンバをすべてゼロで初期化しているにもかかわらず、文字配列 buffer に割り当てられた未使用部分のメモリのせいでオブジェクト ab が等しくないと評価されるかもしれない。どちらの方法でも、パディングビットの値への影響は保証されない。

適合コード

以下の適合コードでは、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)

Top へ

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