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

ERR04-J. finally ブロックの処理を途中で終了しない

finallyブロックの中では、return, break, continue, throw文を決して使用してはならない。プログラムの実行が finallyブロックを持つ tryブロックに入ると、try ブロック(や対応するcatchブロック)の処理が完了するかしないかに関わらず、finallyブロックは必ず実行される。finally ブロックの処理を途中で終了させる文は、try ブロックの処理も中断させてしまう。そのため、tryブロックやcatchブロックからスローされる例外を抑制してしまう。[JLS 2005]

違反コード

以下の違反コードでは、return文が存在するため、finallyブロックの処理が途中で終了してしまう。

class TryFinally {
  private static boolean doLogic() {
    try {
      throw new IllegalStateException();
    } finally {
      System.out.println("logic done");
      return true;
    }
  }
}

return文によってfinallyブロックの処理が終了しているため、IllegalStateException例外の発生が抑制されている。

適合コード

以下の解決法では、finally ブロックから return 文を取り除いている。

class TryFinally {
  private static boolean doLogic() {
    try {
      throw new IllegalStateException();
    } finally {
      System.out.println("logic done");
    }
    // return 文はここに書くこと。ただし、条件に応じて例外がスローされる
    // 場合のみ。
  }
}
例外

ERR04-EX0: finallyブロック内で完結する制御フロー文を書くことは構わない。

たとえば、以下のコードはこのルールの違反には当たらない。break文はwhileループを終了させはするが、finallyブロックは終了させていないからである。

class TryFinally {
  private static boolean doLogic() {
    try {
      throw new IllegalStateException();
    } finally {
      int c;
      try {
        while ((c = input.read()) != -1) {
          if (c > 128) {
            break;
          }
        }
      } catch (IOException x) {
        // ハンドラへ処理を移す
      }
      System.out.println("logic done");
    }
    // return 文はここに書くこと。ただし、条件に応じて例外がスローされる場合のみ。
  }
}
リスク評価

finallyブロックの処理を途中で終了すると、tryブロックやcatchブロックの外にスローされるべき例外がスローされなくなってしまう。

ルール 深刻度 可能性 修正コスト 可能性 レベル
ERR04-J P4 L3
関連ガイドライン
MITRE CWE CWE-459. Incomplete cleanup
  CWE-584. Return inside finally block
参考文献
[Bloch 2005] Puzzle 36. Indecision
[Chess 2007] 8.2, Managing Exceptions, The Vanishing Exception
[JLS 2005] §14.20.2, Execution of try-catch-finally
翻訳元

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

ERR04-J. Do not exit abruptly from a finally block (revision 82)

Top へ

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