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 mEath 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 because the expression NaN == NaN (for every possible value of NaN) returns 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 scanf will accept the values INF, INFINITY, or NAN (not case sensitiveinsensitive) 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 neither of these values if doing so would be inappropriate. The <math.h> library provides two macros for this purpose: isinf and isnan.

...

The isinf macro tests an input floating-point value for infinity. isinf(val) is non-zero nonzero if val is an infinity (positive or negative), and 0 otherwise.

isnan tests if an input is NaN. isnan(val) is non-zero nonzero if val is a NaN, and 0 otherwise.

...

Noncompliant Code Example

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

Code Block
bgColor#FFCCCC
langc
float currentBalance; /* User's cash balance */
void doDeposit() {
  float val;

  scanf("%f", &val);

  if(val >= MAX_VALUE - currentBalance) {
    /* Handle range error */
  }

  currentBalance += val;
}

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 strings "INF", "INFINITY", or "NAN" (case insensitive) 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 denial-of-service attack.

Here, for example, entering "nan" for val would force currentBalance to also equal "nan", corrupting its value. If this value is used elsewhere for calculations, every resulting value would also be a NaN, possibly destroying important data.

Implementation Details

The following code was run on 32-bit GNU Linux using the GCC version 3.4.6 compiler. On this platform, FLT_MAX has the value 340282346638528859811704183484516925440.000000.

Code Block

#include <stdio.h>

int main(int argc, char *argv[]) {
  float val, currentBalance=0;
  scanf("%f", &val);
  currentBalance+=val;
  printf("%f\n", currentBalance);
  return 0;
}

The following table shows the value of currentBalance returned for various arguments.:

Input

currentBalance

25

25.00000

infinity

inf

inf

inf

-infinity

-inf

NaN

nan

nan

nan

1e9999

inf

-1e9999

-inf

As this example demonstrates, the user can enter the exceptional values infinity and NaN, as well as force a float's value to be infinite, by entering out-of-range floats. These entries subsequently corrupt the value of currentBalance. So by entering exceptional floats, an attacker can corrupt the program data, possibly leading to a crash.

Compliant

...

Solution

This compliant solution The following code first validates the input float before using it. The value is tested to ensure that it is neither an infinity nor a NaN.

Code Block
bgColor#ccccff
langc

float currentBalance; /* User's cash balance */

void doDeposit() {
  float val;

  scanf("%f", &val);
  if (isinf(val)) {
    /* handleHandle infinity error */
  }
  if (isnan(val)) {
    /* handleHandle NaN error */
  }
  if (val >= MAX_VALUE - currentBalance) {
    /* Handle range error */
  }

  currentBalance += val;
}

...

Risk Assessment

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

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

FLP04-C

.

low

probable

high

P6

L2

Low

Probable

High

P2

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

Supported: Astrée reports potential runtime error resulting from missing checks for exceptional values.

 Related Related Vulnerabilities

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

Other Languages

...

Related Guidelines

...

...

...

...

References

...

Bibliography

...


...

Image Added Image Added Image Added|AA. C References#IEEE 754 2006]\] \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] \[[IEEE 1003.1, 2004|AA. C References#IEEE 1003]\]FLP03-C. Detect and handle floating point errors      05. Floating Point (FLP)      FLP05-C. Don't use denormalized numbers