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

安全・安心なIT社会のための、国内・国際連携を支援する

お問い合わせ サイトマップ English

Home > ラーニング > セキュアコーディング > C セキュアコーディングスタンダード > 02. 宣言と初期化 (DCL)

  1. HTTPS

02. 宣言と初期化 (DCL)

最終更新: 2010-07-26

DCL01-C. サブスコープで変数名を再利用しない

あるスコープが他方のスコープに包含されるような二つのスコープで同一の変数名を使用しないこと。たとえば、

  • いかなる変数も、その変数がグローバル変数のサブスコープにあるならば、グローバル変数の名前を共有してはならない。
  • あるブロックは、そのブロックを包含するいかなるブロックで宣言されている変数とも、同じ名前の変数を定義してはならない。

変数名を再利用すると、どの変数が変更されているのだろうという混乱をプログラマに与える。また、変数名が再利用されているというのは、変数名が一般的に過ぎるということでもある。

違反コード

以下のコード例では、翻訳単位のはじまりで msg 識別子を定義し(ファイル有効範囲)、同じ識別子を使ってreport_error()関数にローカルな文字配列を宣言している。したがって、プログラマは意図せず、report_error()関数にローカルに宣言されたmsg配列へ文字列をコピーし、グローバル変数の msg を初期化し損ね、バッファオーバーフローを引き起こす可能性がある。

char msg[100];

void report_error(char *error_msg) {
  char msg[80];
  /* ... */
  strncpy(msg, error_msg, sizeof(msg));
  return;
}

int main(void) {
  char error_msg[80];
  /* ... */
  report_error(error_msg);
  /* ... */
}
適合コード

以下の解決法では、より説明的な違う名前を使っている。

char system_msg[100];

void report_error(char *error_msg) {
  char default_msg[80];
  /* ... */
  if (error_msg)
    strncpy(system_msg, error_msg, sizeof(system_msg));
  else
    strncpy(system_msg, default_msg, sizeof(system_msg));
  system_msg[ sizeof(system_msg) - 1] = '\0';
  return;
}

int main(void) {
  char error_msg[80];
  /* ... */
  report_error(error_msg);
  /* ... */
}

ブロックが小さい場合、変数宣言がすぐに目に見えるため、変数名を再利用する危険性は緩和される。しかし、上記の例であっても、変数名を再利用することは望ましくない。

グローバルにもローカルにも異なる変数名を使用することで、コンパイラは、ディベロッパーが変数名に関してより厳密かつ説明的であることを強制する。

リスク評価

サブスコープで変数名を再利用すると、間違った変数を意図せず参照することにつながりうる。

レコメンデーション 深刻度 可能性 修正コスト 優先度 レベル
DCL01-C P2 L3
自動検出

LDRA tool suite Version 7.6.0 はこのレコメンデーションの違反を検出することができる。

Splint Version 3.1.1 はこのレコメンデーションの違反を検出することができる。

Compass/ROSE はこのレコメンデーションの違反を検出することができる。

Klocwork Version 8.0.4.16 は IF_MULTI_DECL, IF_MULTI_DEF, IF_MULTI_KIND チェッカを使ってこのレコメンデーションの違反を検出することができる。

参考情報
  • [ISO/IEC 9899:1999] Section 5.2.4.1, "Translation limits"
  • [MISRA 04] Rule 5.2
翻訳元

DCL01-C. Do not reuse variable names in subscopes

Top へ