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

NUM11-J. 浮動小数点数の文字列表現を比較したり内容を調べたりしない

浮動小数点数の文字列表現を比較したり、その内容を調べたりしてはならない。

違反コード (文字列の比較)

以下の違反コードでは2つの浮動小数点数の文字列表現を比較している。

int i = 1;
String s = Double.valueOf(i / 1000.0).toString();
if (s.equals("0.001")) {
  // ...
}

s の値は文字列"0.0010" であるため、比較は予期せず失敗する。

違反コード (正規表現)

以下の違反コードでは、文字列の比較を行う前に、正規表現を用いて末尾の余分なゼロを取り除こうとしている。

int i = 1;
String s = Double.valueOf(i / 1000.0).toString();
s = s.replaceFirst("[.0]*$", "");
if (s.equals("0.001")) {
  // ...
}

上記のコードの比較は成功するが、似たような下記のコードでは失敗する。下記のコードでは、1/1000.0の代わりに1/10000.0を用いている。生成される文字列は0.00010ではなく、1.0E-4になる。

int i = 1;
String s = Double.valueOf(i / 10000.0).toString();
s = s.replaceFirst("[.0]*$", "");
if (s.equals("0.0001")) {
  // ...
}
適合コード (文字列の比較)

以下の適合コードでは、BigDecimalクラスを使用して浮動小数点数の精度の欠損を防いでいる。数値の比較も想定した通りに行われる。

int i = 1;
BigDecimal d = new BigDecimal(Double.valueOf(i / 1000.0).toString());
if (d.compareTo(new BigDecimal("0.001")) == 0) {
  // ...
}
リスク評価

浮動小数点数の文字列表現を比較したり内容を調べたりすると、予期せぬ結果が得られる場合がある。

ルール 深刻度 可能性 修正コスト 優先度 レベル
NUM11-J P6 L2
関連する脆弱性

Hibernate Validator バグレポート HV-192 はこのルールの違反例である。

参考文献
[API 2006]
[JLS 2005]
翻訳元

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

NUM11-J. Do not compare or inspect the string representation of floating-point values (revision 66)

Top へ

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