Versions Compared

Key

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

...

Formatted-input functions such as scanf 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(val) is non-zero if val is an infinity (positive or negative), and 0 otherwise.

...

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

void doDeposit() {
  float val;

  scanf("%f", &val);

  if(val>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 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 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.

...

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

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

void doDeposit() {
  float val;

  scanf("%f", &val);

  if (isinf(val)) {

    /* handle infinity error */

  }

  if (isnan(val)) {

    /* handle NaN error */

  }

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

  currentBalance += val;
}

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.

...