Versions Compared

Key

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

Floating-point numbers can take on two kinds of exceptional values, infinity and NaN (not-a-number). These values are produced as a result of exceptional or otherwise unresolvable floating point operations. Additionally, they may be obtained directly from user input through methods like Double.valueOf(String s). Failure to detect and handle such values can result in inconsistent behavior.

NaN values are particularly problematic because they are unordered; that is, the expression NaN == NaN always returns false (See see guideline FLP05-J. Do not attempt comparisons with NaN.) In general, any comparisons with NaN return false, and all arithmetic functions on NaN inputs simply propagate the taint throughout the code. Just one with one or more NaN inputs produce NaN as their output. Consequently, a single occurrence of a NaN value can effectuate cause regressions within other code segments. This correct — and arguably desirable — behavior can cause unexpected results.

The method Double.valueOf(String s) can return NaN or an infinite double as specified by its contract. Programs should install checks to ensure that all floating point inputs (especially those obtained from the user) do not contain either of these values before proceeding to operate on themare free of unexpected exceptional values. The methods Double.isNaN(double d) and Double.isInfinite(double d) can be used for this purpose.

...

Code Block
bgColor#FFCCCC
double currentBalance; // User's cash balance

void doDeposit(String userInput) {
  double val;
  try {
    val = Double.valueOf(userInput);
  }
  catch(NumberFormatException e) {
    // Handle input format error
  }

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

  currentBalance += val;
}

This can be a problem if an invalid code will produce unexpected results when an exceptional value is entered for val and subsequently used in calculations or as control values. The user could, for example, input the strings infinity or NaN on the command line, which would be parsed by Double.valueOf(String s) into the floating-point representations of either infinity or NaN. All subsequent calculations using these values would be invalid, possibly causing runtime exceptions or enabling denial of service (DoS) attacks.

In this compliant solutionnoncompliant example, entering NaN for val would force cause currentBalance to be set to also equal NaN, corrupting its value. If this value is were used in other expressions, every resulting value will would also become NaN, possibly corrupting important data.

...

Code Block
bgColor#ccccff
double currentBalance; // User's cash balance

void doDeposit(String s){
  double val;
  try {
    val = Double.valueOf(userInput);
  }
  catch(NumberFormatException e) {
    // Handle input format error
  }

  if (Double.isInfinite(val)){
    // Handle infinity error
  }

  if (Double.isNaN(val)) {
    // Handle NaN error
  }

  if (val >= Double.MAX_VALUE - currentBalance) {
    // Handle range error
  }
  currentBalance += val;
}

...

FLP06-EX1: Occasionally, NaN or infinity may be acceptable as expected inputs to a program. In such cases, explicit checks may not be necessary. However, such programs must be prepared to handle these inputs exceptional values gracefully, and should not allow the prevent propagation of taint the exceptional values to other values by using them in mathematical expressions where they are inappropriatecode that fails to handle exceptional values. The choice to permit input of exceptional values during ordinary operation should be explicitly documented.

Risk Assessment

Incorrect or missing validation of floating point input can result in miscalculations and unexpected results, possibly leading to inconsistent program behavior and Denial of Service (DoS).

...