...
This noncompliant code example incorrectly compares the string representations of two floating-point values:
Code Block | ||
---|---|---|
| ||
int i = 1;
String s = Double.valueOf(i / 1000.0).toString();
if (s.equals("0.001")) {
// ...
}
|
The comparison unexpectedly fails because s
contains the string "0.0010"
, which is not equal to
."0.001"
Noncompliant Code Example (Regex)
This noncompliant code example attempts to mitigate the extra trailing zero by using a regular expression on the string before comparing it:
Code Block | ||
---|---|---|
| ||
int i = 1;
String s = Double.valueOf(i / 1000.0).toString();
s = s.replaceFirst("[.0]*$", "");
if (s.equals("0.001")) {
// ...
}
|
Although the comparison succeeds on the preceding code, it fails on the following similar code, which uses 1/10000.0
instead of 1/1000decimal string literal generated by 1/10000.0
. The string produced is not 0.00010
but 0001
but rather 1.0E-4
.
Code Block | ||
---|---|---|
| ||
int i = 1;
String s = Double.valueOf(i / 10000.0).toString();
s = s.replaceFirst("[.0]*$", "");
if (s.equals("0.0001")) {
// ...
}
|
...
This compliant solution uses the BigDecimal
class to avoid precision lossthe conversion into scientific notation. It then performs a numeric comparison, which passes as expected.
Code Block | ||
---|---|---|
| ||
int i = 1; BigDecimal d = new BigDecimal(Double.valueOf(i / 100010000.0).toString()); if (d.compareTo(new BigDecimal("0.0010001")) == 0) { // ... } |
Risk Assessment
Comparing or inspecting the string representation of floating-point values may have unexpected results.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
NUM11-J | Low | Likely | Medium | P6 | L2 |
Related Vulnerabilities
Hibernate Validator bug report HV-192 describes a violation of this rule.
Android Implementation Details
Comparing or inspecting the string representation of floating-point values may have unexpected results on Android.
Bibliography
...
...