String representations of floating-point numbers must should not be compared or inspected. If they are used, significant care needs to be taken to ensure expected behavior.
Noncompliant Code Example (String Comparison)
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"
.
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")) {
// ...
}
|
While the comparison does succeed on the code above, it fails on the similar code below, 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.
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5ec4027a-f8f7-4531-8e8e-f3dfc92855a8"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="134b54c0-88f9-4490-8023-d185fc8759e0"><ac:plain-text-body><![CDATA[ | [[JLS 2005 | AA. Bibliography#JLS 05]] | ]]></ac:plain-text-body></ac:structured-macro> |
Android Implementation Details
Comparing or inspecting the string representation of floating-point values may have unexpected results on Android.
Bibliography
...