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

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

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

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

違反コード

以下のコード例では、ファイル有効範囲で msg 識別子を定義し、同じ識別子を使って report_error() 関数にローカルな文字配列を宣言している。プログラマは意図せず、report_error() 関数にローカルに宣言された msg 配列へ文字列をコピーする可能性がある。プログラマの意図によって異なるが、このことで、グローバル変数の msg を初期化し損ねるか、または、ローカルバッファに対する境界としてグローバル値 msgsize を使用することでローカル msg バッファのオーバーフローを誘発する可能性がある。

static char msg[100];
static const size_t msgsize = sizeof( msg);

void report_error(const char *str) {
  char msg[80];
  snprintf(msg, msgsize, "Error: %s\n", str);
  /* ... */
}

int main() {
  /* ... */
  report_error("some error");
}
適合コード

以下の適合コードでは、より説明的な違う名前を使っている。

static char message[100];
static const size_t message_size = sizeof( message);

void report_error(const char *str) {
  char msg[80];
  snprintf(msg, sizeof( msg), "Error: %s\n", str);
  /* ... */
}

int main() {
  /* ... */
  report_error("some error");
}

ブロックが小さい場合、変数宣言がすぐに目に見えるため、変数名を再利用する危険性は緩和される。しかし、上記の例であっても、変数名を再利用することは望ましくない。通常、識別子の宣言区域が広がれば、それに伴って識別子の名前はより説明的になり言葉数は増える。

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

例外

DCL01-EX1: 関数宣言内の関数の引数は、関数定義の際に、その関数を包含するどのスコープ内のどの変数とも衝突しない名前を割り当てても、その関数を包含するいずれかのスコープ内の変数と衝突する可能性がある。

extern int name;
void f(char *name);   // 宣言: ここには問題はない
// ...
void f(char *arg) {   // 定義: 問題はない、arg は名前を隠さない
  // use arg
}
リスク評価

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

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

DCL01-C

P2

L3

自動検出

ツール

バージョン

チェッカー

説明

Compass/ROSE

 

 

 

ECLAIR

1.1

declhidn

実装済み

Klocwork

V. 9.1

IF_MULTI_DECL
IF_MULTI_DEF
IF_MULTI_KIND

 

LDRA tool suite

V. 8.5.4

131 S

実装済み

PRQA QA-C 8.1

2547
3334

実装済み

Splint

V. 3.1.1

 

 

関連するガイドライン
CERT C++ Secure Coding Standard DCL01-CPP. Do not reuse variable names in subscopes
MISRA-C

Rule 5.2

翻訳元

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

DCL01-C. Do not reuse variable names in subscopes (revision 114)

Top へ

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