The object representation for floating-point values is implementation defined. However, an implementation that defines the __STDC_IEC_559__
macro shall conform to the IEC 60559 floating-point standard and uses what is frequently referred to as IEEE 754 floating-point arithmetic [ISO/IEC 9899:2011]. The floating-point object representation used by IEC 60559 is one of the most common floating-point object representations in use today.
All floating-point object representations use specific bit patterns to encode the value of the floating-point number being represented. However, equivalence of floating-point values is not encoded solely by the bit pattern used to represent the value. For instance, if the floating-point format supports negative zero values (as IEC 60559 does), the values -0.0
and 0.0
are equivalent and will compare as equal, but the bit patterns used in the object representation are not identical. Similarly, if two floating-point values are both (the same) NaN, they will not compare as equal, despite the bit patterns being identical, because they are not equivalent.
Do not compare floating-point object representations directly, such as by calling memcmp()
or its moral equivalents. Instead, the equality operators (==
and !=
) should be used to determine if two floating-point values are equivalent.
Noncompliant Code Example
In this noncompliant code example, memcmp()
is used to compare two structures for equality. However, since the structure contains a floating-point object, this code may not behave as the programmer intended.
#include <stdbool.h> #include <string.h> struct S { int i; float f; }; bool are_equal(const struct S *s1, const struct S *s2) { if (!s1 && !s2) return true; else if (!s1 || !s2) return false; return 0 == memcmp(s1, s2, sizeof(struct S)); }
Compliant Solution
In this compliant solution, the structure members are compared individually:
#include <stdbool.h> #include <string.h> struct S { int i; float f; }; bool are_equal(const struct S *s1, const struct S *s2) { if (!s1 && !s2) return true; else if (!s1 || !s2) return false; return s1->i == s2->i && s1->f == s2->f; }
Risk Assessment
Using the object representation of a floating-point value for comparisons can lead to incorrect equality results, which can lead to unexpected behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FLP37-C | Low | Unlikely | Medium | P2 | L3 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Astrée | 24.04 | memcmp-with-float | Partially checked |
Axivion Bauhaus Suite | 7.2.0 | CertC-FLP37 | Fully implemented |
Helix QAC | 2024.3 | C5026 C++3118 | |
Klocwork | 2024.3 | MISRA.STDLIB.MEMCMP.PTR_ARG_TYPES | |
LDRA tool suite | 9.7.1 | 618 S | Enhanced Enforcement |
Parasoft C/C++test | 2023.1 | CERT_C-FLP37-c | Do not use object representations to compare floating-point values |
PC-lint Plus | 1.4 | 2498, 2499 | Fully supported |
R2024a | CERT C: Rule FLP37-C | Checks for memory comparison of floating-point values (rule fully covered) | |
PVS-Studio | 7.33 | V1014 | |
RuleChecker | 24.04 | memcmp-with-float | Partially checked |
TrustInSoft Analyzer | 1.38 | Exhaustively verified. |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
[ISO/IEC 9899:2011] | Annex F, "IEC 60559 floating-point arithmetic" |