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)



