Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Mantissa bits are used to express extremely small numbers that are too small to encode normally because of the lack of available exponent bits. Using mantissa bits extends the possible range of exponents. Because these bits no longer function as significant bits of precision, the total precision of extremely small numbers is less than usual. Such numbers are called denormalized, and they are more limited than normalized numbers. However, even using normalized numbers where precision is required can pose a risk. See FLP02-C. Avoid using floating-point numbers when precise computation is needed for more information.

Using denormalized 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.

Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
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 on implementations that use IEEE 754 floats:

Code Block
Original      : 3.333333e-01
Denormalized? : 2.802597e-45
Restored      : 4.003710e-01

Compliant Solution

Do not produce code that could use not allow code to produce denormalized numbers. If floats are producing denormalized numbers, use doubles instead.

Code Block
bgColor#ccccff
langc
#include <stdio.h>
double 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);
Code Block
Original      : 3.333333e-01
Denormalized? : 2.333333e-45
Restored      : 3.333333e-01

If using doubles also produces denormalized numbers, using long doubles may or may not help. (On some implementations, long double has the same exponent range as double.) If using long doubles produces denormalized numbers, some other solution must be found.

Printing Denormalized Numbers

Denormalized numbers can also be troublesome because some functions have implementation-defined behavior when used with denormalized values. For example, using the %a or $%A conversion specifier in a format string can produce implementation-defined results when applied to denormalized numbers.

...

Code Block
#include<stdio.h>
float x = 0x1p-125;
double y = 0x1p-1020;

printf("normalized float with %%e    : %e\n", x);
printf("normalized float with %%a    : %a\n", x);
x = 0x1p-140;
printf("denormalized float with %%e  : %e\n", x);
printf("denormalized float with %%a  : %a\n", x);
printf("normalized double with %%e   : %e\n", y);
printf("normalized double with %%a   : %a\n", y);
y = 0x1p-1050;
printf("denormalized double with %%e : %e\n", y);
printf("denormalized double with %%a : %a\n", y);

Implementation Details

On a 32-bit Linux machine using GCC 4.3.2, this code produces the following output:

Code Block
normalized float with %e    : 2.350989e-38
normalized float with %a    : 0x1p-125
denormalized float with %e  : 7.174648e-43
denormalized float with %a  : 0x1p-140
normalized double with %e   : 8.900295e-308
normalized double with %a   : 0x1p-1020
denormalized double with %e : 8.289046e-317
denormalized double with %a : 0x0.0000001p-1022

Risk Assessment

Floating-point numbers are an approximation; using subnormal floating-point number are a worse approximation.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FLP05-C

lowLow

probableProbable

highHigh

P2

L3

Automated Detection

TODO

Related Vulnerabilities

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

Related Guidelines

Bibliography

[Bryant 2003]Section 2.4, "Floating Point"
[IEEE 754] 
[ISO/IEC 9899:2011]Subclause 7.21.6.1, "The fprintf Function"

 

...

Image Modified Image Modified Image Modified