EXP19-C. if、for、while 文の本体は波括弧で囲む
if
、for
、while
文に対しては、本体に単一の文しか含まれていない場合でも、必ず開始と終了の波括弧を使用すること。
if
、while
、for
文をマクロの中で使用する場合、マクロ定義の最後をセミコロンで終端すべきではない(「PRE11-C. 単一文からなるマクロ定義をセミコロンで終端しない」を参照)。
波括弧を使用することでコードの一貫性が保たれ、読みやすさも向上する。より重要なことは、文が 1 つしかない本体に新たに文を追加するときに、字下げがその構造に対する強固な(しかし誤解を招きやすい)目安となるため、波括弧を付けるのを忘れがちな点である。
また、波括弧を用いると、複数にわたる文からなるマクロを正しく展開するのにも役立つ。複数にわたる文からなるマクロは do-while ループで包む必要がある(「PRE10-C. 複数にわたる文からなるマクロは do-while ループで包む」を参照)。しかし、d-while ループがなくても、波括弧を使用することでマクロが意図したとおりに展開されることを保証できる。
違反コード
次のコード例は、波括弧を付けずに if
文を使用してユーザの認証を行っている。
int login; if (invalid_login()) login = 0; else login = 1;
上記のコードにログインが有効かどうかを判定するデバッグ文を追加したときに、プログラマが開始と終了の波括弧を追加し忘れたとする。
int login; if (invalid_login()) login = 0; else printf("Login is valid\n"); /* デバッグ行がここに追加される */ login = 1; /* この行はログインが有効かどうかを問わず常に実行される */
コードの字下げが原因で、意図した通りにコードが機能しないということがわかりにくいため、セキュリティの侵害につながる可能性がある。
適合コード
次の適合コードでは、本体が単一の文であっても開始と終了の波括弧を使用している。
int login; if (invalid_login()) { login = 0; } else { login = 1; }
違反コード
次のコード例では、if
と else
の本体を波括弧で囲まずに、if
文の中で if
文を入れ子にしている。
int privileges; if (invalid_login()) if (allow_guests()) privileges = GUEST; else privileges = ADMINISTRATOR;
字下げが原因で、プログラマはユーザのログインが有効な場合に限りユーザに管理者権限が与えられると考えてしまうかもしれない。しかし、else
文は実際には内側の if
文と結び付けられている。
int privileges; if (invalid_login()) if (allow_guests()) privileges = GUEST; else privileges = ADMINISTRATOR;
これはセキュリティの抜け道であり、ログインが無効のユーザでも管理者権限を取得できてしまう可能性がある。
適合コード
次の適合コードは、波括弧を追加することであいまいさを排除し、権限が正しく割り当てられることを保証している。
int privileges; if (invalid_login()) { if (allow_guests()) { privileges = GUEST; } } else { privileges = ADMINISTRATOR; }
リスク評価
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
EXP19-C |
中 |
中 |
中 |
P8 |
L2 |
関連するガイドライン
MISRA-C | Rule 14.8 |
参考資料
[GNU 2010] | Coding Standards, Section 5.3, "Clean Use of C Constructs" |
[ISO/IEC 9899:2011] | Section 6.8.4, "Selection Statements" |
翻訳元
これは以下のページを翻訳したものです。
EXP19-C. Use braces for the body of an if, for, or while statement (revision 50)