You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 37 Next »

Because floating-point numbers can represent fractions, programmers often mistakenly assume that they can represent any simple fraction exactly. In fact, floating-point numbers are subject to precision limitations just as integers are. Further, binary floating-point numbers cannot represent all decimal fractions exactly, even when the fractions can be represented in a small number of decimal digits.

In addition, because floating-point numbers can represent large values, programmers often mistakenly assume that they can represent all digits of those values. To gain a large dynamic range, floating-point numbers maintain a fixed number of bits of precision and an exponent. Incrementing a large floating-point value might not change that value within the available precision. Consequently, floating-point variables should not be used as loop counters.

Noncompliant Code Example

This noncompliant code example uses a floating-point variable as a loop counter. The decimal number 0.1 is a repeating fraction in binary and cannot be exactly represented as a binary floating-point number.

for (float x = 0.1f; x <= 1.0f; x += 0.1f) {
  // ... 
}

This loop executes only nine times. (If the value of x is printed inside the loop, the following values appear: 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.70000005, 0.8000001, 0.9000001.)

Compliant Solution

This compliant solution uses an integer loop counter from which the desired floating-point value is derived.

for (int count = 1; count <= 10; count += 1) {
  float x = count/10.0f;
  // ...
}

Noncompliant Code Example

This noncompliant code example uses a floating-point loop counter that is incremented by an amount that is too small to change its value given the precision.

for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {
  /* ... */
}

The code loops forever on execution.

Compliant Solution

This compliant solution uses an integer loop counter from which the floating-point value is derived. Additionally, it uses a double so that the available precision suffices to represent the desired values.

for (int count = 1; count <= 10; count += 1) {
  double x = 100000000.0 + count;
  /* ... */
}

Risk Assessment

Using floating-point loop counters can lead to unexpected behavior.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

FLP07-J

low

probable

low

P6

L2

Automated Detection

Automated detection of floating-point loop counters is straightforward.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Related Guidelines

C Secure Coding Standard: FLP30-C. Do not use floating point variables as loop counters

C++ Secure Coding Standard: FLP30-CPP. Do not use floating point variables as loop counters

Bibliography

[[Bloch 2005]] Puzzle 34: Down for the Count
[[JLS 2005]] Section 4.2.3, Floating-Point Types, Formats, and Values


FLP06-J. Check floating point inputs for exceptional values      Floating Point (FLP)      FLP08-J. Avoid using floating point literals with the BigDecimal constructor

  • No labels