Versions Compared

Key

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

Floating-point numbers can take on two classes of exceptional values; infinity and NaN (not-a-number). These values are returned as the result of exceptional or otherwise unresolvable floating point operations. (See also: FLP32-C. Prevent or detect domain and range errors in math functions). Additionally, they can be directly input by a user by scanf or similar functions. Failure to detect and handle such values can result in undefined behavior.
NaN values are particularly problematic, as the expression NaN==NaN (for every possible value of NaN) returns false. It is possible to test that a variable x is NaN by checking that (x==x) evaluates to false. Any comparisons made with NaN as one of the arguments returns false, and all arithmetic functions on NaNs simply propagate them through the code. Hence, a NaN entered in one location in the code and not properly handled could potentially cause problems in other, more distant sections.

Formatted-input functions such as sscanf will accept the values INF, INFINITY, or NAN (not case sensitive) as valid inputs for the %f format specification, allowing malicious users to feed them directly to a program. Programs should therefore check to ensure that all input floating point values (especially those controlled by the user) do not have either of these values if doing so would be inappropriate. The <math.h> library provides two macros for this purpose: isinf and isnan.

isinf and isnan

The isinf macro tests an input floating point value for infinity. isinf(x) returns 1 if x is infinity, -1 if x is negative infinity, and 0 otherwise.

isnan tests if an input is NaN. isnan(\x) is 1 if x is NaN, and 0 otherwise.

If infinity or NaN values are not acceptable inputs in a program, these macros should be used to ensure they are not passed to vulnerable functions.

Noncompliant Code Example

The following noncompliant code accepts user data without first validating it.

...

This can be a problem if an invalid value is entered for val and subsequently used for calculations or as control values. The user could, for example, input the values "INF", "INFINITY", or "NAN" on the command line, which would be parsed by scanf into the floating-point representations of infinity and NaN. All subsequent calculations using these values would be invalid, possibly crashing the program and enabling a DOS attack.

isinf and isnan

Compliant Code Example

The following code first validates the input float before using it. The value is tested to ensure that it is within the acceptable range of MIN_VAL to MAX_VAL (and is therefore neither infinity nor negative infinity). Note the use of "val!=val" to test for NaN.

Code Block
bgColor#ccccff
double val;

scanf("%g", &val);

if(val<MIN_VAL || val>MAX_VAL) {

/* handle range error */

}

if(isnan(val!=val)) /* test NaN */

{

/* handle NaN error */

}



 

Exceptions

Occasionally, NaN or infinity may be acceptable or expected inputs to a program. If this is the case, then explicit checks may not be necessary. Such programs must, however, be prepared to handle these inputs gracefully and not blindly use them in mathematical expressions where they are not appropriate.

Risk Assessment

Inappropriate floating point inputs can result in invalid calculations and unexpected results, possibly leading to crashing and providing a DOS opportunity.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

X FLP37-C.

low

probable

high

P6

L2

Related Vulnerabilities

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

Other Languages

This rule appears in the C++ Secure Coding Standard as FLP03-CPP. Detect and handle floating point errors.

References

Wiki Markup
\[[IEEE 754|AA. C References#IEEE 754 2006]\]
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\]