publicメソッドの引数の検証にassertを使わないこと。Java言語仕様 §4.10「assert文」には以下のように規定されている。
...パブリックメソッドの引数チェックにassertを用いるべきでない。たいていの場合、引数チェックはメソッド契約の一部を成しており、この契約はassertが有効であるか否かに関わらず、守らなければならない。
assertを引数の検証に使った場合に発生するもう1つの問題として、誤った引数があった場合、適切な実行時例外(たとえばIllegalArgumentException、IndexOutOfBoundsException、NullPointerException)をスローしなければならないという点が挙げられる。assertが失敗しても、適切な例外がスローされるわけではない。
違反コード
getAbsAdd()メソッドは、引数xとyの絶対値の和を計算して返す。メソッドは引数の検証を行っておらず、「MET00-J. メソッドの引数を検証する」に違反している。したがって、整数オーバーフローが発生する場合や、引数のいずれかもしくは両方がInteger.MIN_VALUEである場合、誤った計算結果を返してしまう。
public static int getAbsAdd(int x, int y) {
  return Math.abs(x) + Math.abs(y);
}
getAbsAdd(Integer.MIN_VALUE, 1);
違反コード
以下の違反コード例では、assertを用いてパブリックメソッドの引数を検証している。
public static int getAbsAdd(int x, int y) {
  assert x != Integer.MIN_VALUE;
  assert y != Integer.MIN_VALUE;
  int absX = Math.abs(x);
  int absY = Math.abs(y);
  assert (absX <= Integer.MAX_VALUE - absY);
  return absX + absY;
}
assertによるチェックの条件自体は正しい。しかし、assertを無効にしてコードが実行されると、検証コードは実行されない。
適合コード
以下の適合コードでは、メソッドの引数の検証において、Math.abs()に渡す値がInteger.MIN_VALUEでないこと、また、整数オーバーフローを引き起こす値ではないことを確認している。
public static int getAbsAdd(int x, int y) {
  if (x == Integer.MIN_VALUE || y == Integer.MIN_VALUE) {
    throw new IllegalArgumentException();
  }
  int absX = Math.abs(x);
  int absY = Math.abs(y);
  if (absX > Integer.MAX_VALUE - absY) {
    throw new IllegalArgumentException();
  }
  return absX + absY;
}
別の解決策としては、longを使用して加算を行い、演算結果をlong型のローカル変数に保存するという方法もある。この方法をとるのであれば、結果のlong値がintの幅で表現できる範囲に収まることを確認しなくてはならない。この確認に失敗するということは、intの幅では加算が整数オーバーフローを引き起こすことを意味する。
リスク評価
メソッドの引数の検証にassertを使うと、誤った計算、実行時例外、プログラムの制御フローに関する脆弱性を引き起こす恐れがある。
| ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル | 
|---|---|---|---|---|---|
| MET01-J | 中 | 中 | 中 | P8 | L2 | 
関連ガイドライン
| MITRE CWE | CWE-617. Reachable assertion | 
参考文献
| [Daconta 2003] | Item 7: My Assertions Are Not Gratuitous | 
| [ESA 2005] | Rule 68: Explicitly check method parameters for validity, and throw an adequate exception in case they are not valid. Do not use the assert statement for this purpose | 
| [JLS 2005] | §4.10 The assert statement | 
翻訳元
これは以下のページを翻訳したものです。
MET01-J. Never use assertions to validate method arguments (revision 28)



