メインコンテンツ

CWE Rule 484

Omitted Break Statement in Switch

R2023a 以降

説明

ルールの説明

The program omits a break statement within a switch or similar construct, causing code associated with multiple conditions to execute.This can cause problems when the programmer only intended to execute code associated with one condition.

Polyspace 実装

このルール チェッカーは、[switch case の break がありません] をチェックします。

すべて展開する

問題

この問題は、switch ステートメントの case ブロックが break[[fallthrough]]、またはコードのコメントで終了していない場合に発生します。

case ブロックの最後のエントリがコード コメントの場合の例:

switch (wt)
    {
      case WE_W:
        do_something_for_WE_W();
        do_something_else_for_WE_W();
        /* fall through to WE_X*/
      case WE_X:
        ...
    }
Polyspace は、break がないのは意図的であると判断され、欠陥が発生しないことを前提とします。

リスク

switch case に break ステートメントがないと、次の switch case が実行されます。この動作が意図的でない場合、switch case のコードが意図せず実行され、switch が予期しない結果で終わる可能性があります。

修正方法

break ステートメントを忘れた場合は、switch case の末尾に追加します。

強調表示された switch case を break しない場合は、コードにコメントを追加して、この case に続いて次の case が実行される理由を示します。このコメントにより、結果から欠陥が削除され、コードの保守が容易になります。

テンプレート関数の場合など、欠陥チェッカーが case ステートメントの末尾にあるコメントを無視することがあります。意図的に次の case まで続行することを、より明確に示す方法として、以下の fallthrough 属性のいずれかを使用する方法があります。(可能な場合)

  • [[fallthrough]]:C++17 以降で使用できます。

  • [[gnu::fallthrough]] および [[clang::fallthrough]]: GCC コンパイラと Clang コンパイラで使用できます。

  • __attribute__((fallthrough)):GCC コンパイラで使用できます。

例 — break ステートメントのない switch
enum WidgetEnum { WE_W, WE_X, WE_Y, WE_Z } widget_type;

extern void demo_do_something_for_WE_W(void);
extern void demo_do_something_for_WE_X(void);
extern void demo_report_error(void);

void bug_missingswitchbreak(enum WidgetEnum wt)
{
    /*
      In this non-compliant code example, the case where widget_type is WE_W lacks a
      break statement. Consequently, statements that should be executed only when
      widget_type is WE_X are executed even when widget_type is WE_W.
    */
    switch (wt)
    {
      case WE_W:  //Noncompliant
        demo_do_something_for_WE_W();
      case WE_X:  //Noncompliant
        demo_do_something_for_WE_X();
      default:
        /* Handle error condition */
        demo_report_error();
    }
}

この例には、break ステートメントがない case が 2 つあります。wtWE_W のとき、プログラムでは 2 つの case を中断しないでそのまま続行するため、WE_WWE_X のステートメントと default のケースが実行されます。default のケースまたは最後の case には break ステートメントが必要ないため、欠陥は報告されません。

修正 — コメントまたは break を追加

この例を修正するには、case ブロックの最後のステートメントとマークする次の case ブロックの間にコメントを追加して受け入れ可能なフォール スルーを文書化するか、break ステートメントを追加してフォール スルーを回避します。この例では、case WE_W はそのまま続行することを想定しているため、コメントを追加して明示的にこの動作を示します。2 つ目の case では、default ケースの続行を回避するため break ステートメントを追加します。

enum WidgetEnum { WE_W, WE_X, WE_Y, WE_Z } widget_type;

extern void demo_do_something_for_WE_W(void);
extern void demo_do_something_for_WE_X(void);
extern void demo_report_error(void);

void corrected_missingswitchbreak(enum WidgetEnum wt)
{
    switch (wt)
    {
      case WE_W:
        demo_do_something_for_WE_W();
        /* fall through to WE_X*/
      case WE_X:
        demo_do_something_for_WE_X();
        break;  
      default:
        /* Handle error condition */
        demo_report_error();
    }
}

チェック情報

カテゴリ: Behavioral Problems

バージョン履歴

R2023a で導入