You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# FLP30-C: Do not use floating-point variables as loop counters
2
+
3
+
This query implements the CERT-C rule FLP30-C:
4
+
5
+
> Do not use floating-point variables as loop counters
6
+
7
+
8
+
## Description
9
+
10
+
Because floating-point numbers represent real numbers, it is often mistakenly assumed that they can represent any simple fraction exactly. Floating-point numbers are subject to representational limitations just as integers are, and binary floating-point numbers cannot represent all real numbers exactly, even if they can be represented in a small number of decimal digits.
11
+
12
+
In addition, because floating-point numbers can represent large values, it is often mistakenly assumed that they can represent all significant digits of those values. To gain a large dynamic range, floating-point numbers maintain a fixed number of precision bits (also called the significand) and an exponent, which limit the number of significant digits they can represent.
13
+
14
+
Different implementations have different precision limitations, and to keep code portable, floating-point variables must not be used as the loop induction variable. See Goldberg's work for an introduction to this topic \[[Goldberg 1991](https://www.securecoding.cert.org/confluence/display/java/Rule+AA.+References#RuleAA.References-Goldberg91)\].
15
+
16
+
For the purpose of this rule, a *loop counter* is an induction variable that is used as an operand of a comparison expression that is used as the controlling expression of a `do`, `while`, or `for` loop. An *induction variable* is a variable that gets increased or decreased by a fixed amount on every iteration of a loop \[[Aho 1986](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-Aho1986)\]. Furthermore, the change to the variable must occur directly in the loop body (rather than inside a function executed within the loop).
17
+
18
+
## Noncompliant Code Example
19
+
20
+
In this noncompliant code example, a floating-point variable is used 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. Depending on the implementation, the loop may iterate 9 or 10 times.
21
+
22
+
```cpp
23
+
voidfunc(void) {
24
+
for (float x = 0.1f; x <= 1.0f; x += 0.1f) {
25
+
/* Loop may iterate 9 or 10 times */
26
+
}
27
+
}
28
+
```
29
+
For example, when compiled with GCC or Microsoft Visual Studio 2013 and executed on an x86 processor, the loop is evaluated only nine times.
30
+
31
+
## Compliant Solution
32
+
33
+
In this compliant solution, the loop counter is an integer from which the floating-point value is derived:
34
+
35
+
```cpp
36
+
#include <stddef.h>
37
+
38
+
void func(void) {
39
+
for (size_t count = 1; count <= 10; ++count) {
40
+
float x = count / 10.0f;
41
+
/* Loop iterates exactly 10 times */
42
+
}
43
+
}
44
+
```
45
+
46
+
## Noncompliant Code Example
47
+
48
+
In this noncompliant code example, a floating-point loop counter is incremented by an amount that is too small to change its value given its precision:
49
+
50
+
```cpp
51
+
voidfunc(void) {
52
+
for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {
53
+
/* Loop may not terminate */
54
+
}
55
+
}
56
+
```
57
+
On many implementations, this produces an infinite loop.
58
+
59
+
## Compliant Solution
60
+
61
+
In this compliant solution, the loop counter is an integer from which the floating-point value is derived. The variable `x` is assigned a computed value to reduce compounded rounding errors that are present in the noncompliant code example.
62
+
63
+
```cpp
64
+
void func(void) {
65
+
for (size_t count = 1; count <= 10; ++count) {
66
+
float x = 100000000.0f + (count * 1.0f);
67
+
/* Loop iterates exactly 10 times */
68
+
}
69
+
}
70
+
```
71
+
72
+
## Risk Assessment
73
+
74
+
The use of floating-point variables as loop counters can result in [unexpected behavior ](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-unexpectedbehavior).
Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+FLP30-C).
87
+
88
+
## Related Guidelines
89
+
90
+
[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)
91
+
92
+
<table> <tbody> <tr> <th> Taxonomy </th> <th> Taxonomy item </th> <th> Relationship </th> </tr> <tr> <td> <a> CERT C </a> </td> <td> <a> FLP30-CPP. Do not use floating-point variables as loop counters </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CERT Oracle Secure Coding Standard for Java </a> </td> <td> <a> NUM09-J. Do not use floating-point variables as loop counters </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> ISO/IEC TR 24772:2013 </a> </td> <td> Floating-Point Arithmetic \[PLF\] </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Directive 1.1 (required) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Rule 14.1 (required) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> </tbody> </table>
Copy file name to clipboardExpand all lines: rules.csv
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -543,7 +543,7 @@ c,CERT-C,FIO44-C,Yes,Rule,,,Only use values for fsetpos() that are returned from
543
543
c,CERT-C,FIO45-C,Yes,Rule,,,Avoid TOCTOU race conditions while accessing files,,IO4,Medium,
544
544
c,CERT-C,FIO46-C,Yes,Rule,,,Do not access a closed file,FIO51-CPP,IO1,Hard,
545
545
c,CERT-C,FIO47-C,Yes,Rule,,,Use valid format strings,,IO4,Hard,
546
-
c,CERT-C,FLP30-C,Yes,Rule,,,Do not use floating-point variables as loop counters,,Statements,Easy,
546
+
c,CERT-C,FLP30-C,Yes,Rule,,,Do not use floating-point variables as loop counters,,Statements4,Easy,
547
547
c,CERT-C,FLP32-C,Yes,Rule,,,Prevent or detect domain and range errors in math functions,A0-4-4,Types,Medium,
548
548
c,CERT-C,FLP34-C,Yes,Rule,,,Ensure that floating-point conversions are within range of the new type,,Types,Medium,
549
549
c,CERT-C,FLP36-C,Yes,Rule,,,Preserve precision when converting integral values to floating-point type,,Types,Medium,
@@ -694,9 +694,9 @@ c,MISRA-C-2012,RULE-13-4,Yes,Advisory,,,The result of an assignment operator sho
694
694
c,MISRA-C-2012,RULE-13-5,Yes,Required,,,The right hand operand of a logical && or || operator shall not contain persistent side effects,M5-14-1,SideEffects1,Import,
695
695
c,MISRA-C-2012,RULE-13-6,Yes,Mandatory,,,The operand of the sizeof operator shall not contain any expressiosn which has potential side effects,M5-3-4,SideEffects1,Import,
696
696
c,MISRA-C-2012,RULE-14-1,Yes,Required,,,A loop counter shall not have essentially floating type,FLP30-C A6-5-2,Types,Hard,
697
-
c,MISRA-C-2012,RULE-14-2,Yes,Required,,,A for loop shall be well-formed,M6-5-1...M6-5-6,Statements,Medium,
697
+
c,MISRA-C-2012,RULE-14-2,Yes,Required,,,A for loop shall be well-formed,M6-5-1...M6-5-6,Statements4,Medium,
698
698
c,MISRA-C-2012,RULE-14-3,Yes,Required,,,Controlling expressions shall not be invariant,,Statements,Medium,
699
-
c,MISRA-C-2012,RULE-14-4,Yes,Required,,,The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type,A5-0-2,Statements,Medium,
699
+
c,MISRA-C-2012,RULE-14-4,Yes,Required,,,The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type,A5-0-2,Statements4,Medium,
700
700
c,MISRA-C-2012,RULE-15-1,No,Advisory,,,The goto statement should not be used,A6-6-1,,Import,
701
701
c,MISRA-C-2012,RULE-15-2,Yes,Required,,,The goto statement shall jump to a label declared later in the same function,M6-6-2,Statements2,Import,
702
702
c,MISRA-C-2012,RULE-15-3,Yes,Required,,,"Any label referenced by a goto statement shall be declared in the same block, or in any block enclosing the goto statement",M6-6-1,Statements2,Import,
0 commit comments