C uses the IEEE 754 standard for floating point representation. In this representation floats are encoded using 1 sign bit, 8 exponent bits and 23 mantissa bits. Doubles are encoded and used exactly the same way except they use 1 sign bit, 11 exponent bits, and 52 mantissa bits.These bits encode the values of s, the sign; M, the significand; and E, the exponent. Floating point numbers are then calculated as (-1)^s * M * 2^E.
Ordinarily all of the mantissa bits are used to express significant figures in addition to a leading 1 which is implied and therefore left out. Thus floats ordinarily have 24 significant bits of precision and doubles ordinarily have 53 significant bits of precision. Such numbers are called normalized numbers.
However, to express extremely small numbers that are too small to encode normally because not enough exponent bits are available mantissa bits are used to extend the possible range of exponents. These bits no longer function as significant bits of precision so the total precision of extremely small numbers is smaller than usual. Such numbers are called denormalized.
Using denormalized numbers can severely impair the precision of floating point numbers and should not be used.
Noncompliant Code Example
This code attempts to reduce a floating point number to a denormalized value and then restore the value. This operation is very imprecise. FLP02-C
#include <stdio.h> int main() { float x = 1/3.0; printf("Original : %e\n", x); x = x * 7e-45; printf("Denormalized? : %e\n", x); x = x / 7e-45; printf("Restored : %e\n", x); }
This code produces the following output
Original : 3.333333e-01 Denormalized? : 2.802597e-45 Restored : 4.003710e-01
Compliant Solution
Don't produce code that could use denormalized numbers. If floats are producing denormalized numbers use doubles instead.
#include <stdio.h> #include <stdio.h> int main() { float x = 1/3.0; printf("Original : %e\n", x); x = x * 7e-45; printf("Denormalized? : %e\n", x); x = x / 7e-45; printf("Restored : %e\n", x); }
Original : 3.333333e-01 Denormalized? : 2.333333e-45 Restored : 3.333333e-01
If using doubles also produces denormalized numbers some other solution must be found.
Risk Assessment
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FLP05-C |
medium |
probable |
high |
P4 |
L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Computer Systems: A Programmer's Perspective. Section 2.4 Floating Point