From 6.3.1.5 of the C99 standard:

When a {{double}} is demoted to {{float}} \[or\] a {{long double}} is demoted to {{double}} or {{float}}...if the value being converted is outside the range of values that can be represented, the behavior is [undefined|BB. Definitions#undefined behavior].

Non-Compliant Code Example

This non-compliant code example illustrates possible undefined behavior associated with demoting floating point represented numbers.

long double ld;
double d1;
double d2;
float f1;
float f2;

/* initializations */

f1 = (float)d1;
f2 = (float)ld;
d2 = (double)ld;

As a result of these conversions it is possible that d1 is outside the range of values that can be represented by a float or that ld is outside the range of values that can be represented as either a float or a double.

Compliant Solution

This compliant solution properly checks to see whether the values to be stored can be represented in the new type.

#include <float.h>

long double ld;
double d1;
double d2;
float f1;
float f2;

/* initializations */

if (d1 > FLT_MAX || d1 < -FLT_MAX) {
  	/* Handle error condition */
} else {
 	f1 = (float)d1;
}
if (ld > FLT_MAX || ld < -FLT_MAX) {
	/* Handle error condition */
} else {
	f2 = (float)ld;
}
if (ld > DBL_MAX || ld < -DBL_MAX) {
	/* Handle error condition */
} else {
	d2 = (double)ld;
}

Risk Analysis

Failing to check that a floating point value fits within a demoted type can result in a value too large to be represented by the new type, resulting in undefined behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FLP34-C

1 (low)

1 (unlikely)

3 (low)

P3

L3

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

References

\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.3.1.5, "Real floating types"