# NUM08-J. Check floating-point inputs for exceptional values

Floating-point numbers can take on three exceptional values: `infinity`, `-infinity`, and `NaN` (not-a-number). These values are produced as a result of exceptional or otherwise unresolvable floating-point operations, such as division by zero. These exceptional values can also be obtained directly from user input through methods such as `Double.valueOf(String s)`. Failure to detect and handle such exceptional values can result in inconsistent behavior.

The method `Double.valueOf(String s)` can return `NaN` or an infinite `double`, as specified by its contract. Programs must ensure that all floating-point inputs (especially those obtained from the user) are free of unexpected exceptional values. The methods `Double.isNaN(double d)` and `Double.isInfinite(double d)` can be used for this purpose.

`NaN` values are particularly problematic because they are unordered. That is, the expression `NaN == NaN` always returns `false` (see NUM07-J. Do not attempt comparisons with NaN for more information).

## Noncompliant Code Example

This noncompliant code example accepts user data without validating it:

```double currentBalance; // User's cash balance

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

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

currentBalance += val;
}
```

This code produces 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 noncompliant example, entering `NaN` for `val` would cause `currentBalance` to be set to `NaN`, corrupting its value. If this value were used in other expressions, every resulting value would also become `NaN`, possibly corrupting important data.

## Compliant Solution

This compliant solution validates the floating-point input before using it. The value is tested to ensure that it is neither `infinity`, `-infinity`, nor `NaN`.

```double currentBalance; // User's cash balance

void doDeposit(String userInput){
double val = 0;
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;
}
```

## Exceptions

NUM08-J-EX0: Occasionally, `NaN`, `infinity`, or `-infinity` may be acceptable as expected inputs to a program. In such cases, explicit checks might not be necessary. However, such programs must be prepared to handle these exceptional values gracefully and should prevent propagation of the exceptional values to other code 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.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

NUM08-J

Low

Probable

Medium

P4

L3

### Automated Detection

Automated detection is infeasible in the general case. It could be possible to develop a taint-like analysis that detects many interesting cases.

ToolVersionCheckerDescription
Parasoft Jtest

2024.1

CERT.NUM08.FPEXCCheck floating-point inputs for exceptional values