You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 22 Next »

Errors during floating point operation are often ignored by the applications; instead much effort is only in validating the operands before an operation.

This recommendation suggests ways to capture errors during floating point operations. What makes it difficult to detect these errors is that the application will not abort or even complain when they occur. For example, the following statement generates a runtime error or exception.

int j = 0;
int iResult = 1 / j;

This one, however, generates no error messages.

double x = 0.0;
double dResult = 1 / x;

Though floating point exception conditions and handling are standardized by [[IEEE 754]], operating systems implement support for handling floating point errors and other conditions in different ways.

Operating System

Handling FP errors

Linux
Solaris 10
Mac OS X 10.5
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="0119d81d-49fd-4cfa-be9e-40f35a15ba4d"><ac:plain-text-body><![CDATA[Fedora Core 5

C99 FP functions - These functions are declared in fenv.h [[Open Group 04

AA. C References#Open Group 04]]
]]></ac:plain-text-body></ac:structured-macro>
Before fenv.h based functions were standardized; an alternative to using these C99/fenv() functions is using ieee_flags and ieee_handler

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="fe17dc93-511d-461c-8f95-b31e0ffa4c9f"><ac:plain-text-body><![CDATA[

Windows

Structured Exception Handling - user defined handler _fpieee_flt [[MSDN

AA. C References#MSDN]]
]]></ac:plain-text-body></ac:structured-macro>
 

Non-Compliant Code Example

In this NCCE, floating point operations are carried out and there is no observation for errors during floating point operations. Please note that the range check on various operands for the operations has been intentionally ignored because we intend to capture the errors during a floating point operation.

fpOper_noErrorChecking() {
  /* ... */
  double a = 1e-40, b, c = 0.1;
  float x = 0, y;
  /* inexact and underflows */
  y = a;
  /* divide by zero operation */
  b = y / x;
  /* inexact (loss of precision) */
  c = sin(30) * a;
  /* ... */
}

Compliant Solution 1

This compliant solution uses C99 standard functions to handle floating point errors.

#include <fenv.h>

fpOper_fenv() {
  double a = 1e-40, b, c = 0.1;
  float x = 0, y;
  int fpeRaised;
  /* ... */

  feclearexcept(FE_ALL_EXCEPT);
  /* Store a into y is inexact and underflows: */
  y = a;
  fpeRaised = fetestexcept(FE_ALL_EXCEPT);
  /* fpeRaised  has FE_INEXACT and FE_UNDERFLOW */

  feclearexcept(FE_ALL_EXCEPT);

  /* divide by zero operation */
  b = y / x;
  fpeRaised = fetestexcept(FE_ALL_EXCEPT);
  /* fpeRaised has FE_DIVBYZERO */

  feclearexcept(FE_ALL_EXCEPT);

  c = sin(30) * a;
  fpeRaised = fetestexcept(FE_ALL_EXCEPT);
  /* fpeRaised has FE_INEXACT */

  feclearexcept(FE_ALL_EXCEPT);
  /* ... */
}

Compliant Solution 2 (Windows)

MS Visual Studio 2008 and earlier does not support C99 functions to handle floating point errors. Windows provides an alternative method to get floating point exception code using _statusfp(), _statusfp2(), and _clearfp().

fpOper_usingStatus() {
  /* ... */
  double a = 1e-40, b, c;
  float x = 0, y;
  unsigned int rv = _clearfp() ;

  /* Store into y is inexact and underflows: */
  y = a;
  rv = _clearfp() ;  /* rv has _SW_INEXACT and _SW_UNDERFLOW */

  /* zero-divide */
  b = y / x; rv = _clearfp() ; /* rv has _SW_ZERODIVIDE */

  /* inexact */
  c = sin(30) * a; rv = _clearfp() ; /* rv has _SW_INEXACT */
  /* ... */
}

Compliant Solution 3 (Windows)

MS Visual Studio 2008 also uses structured exception handling (SEH) to handle floating point operation. Using the SEH allows the programmer to change the results of the floating point operation that caused the error condition. Using SEH also provides more information about the error condition.

fp_usingSEH() {
  /* ... */
  double a = 1e-40, b, c = 0.1;
  float x = 0, y;
  unsigned int rv ;

  unmask_fp();

  _try {
    /* Store into y is inexact and underflows */
    y = a;

    /* divide by zero operation */
    b = y / x;

    /* inexact */
    c = sin(30) * a;
  }

  _except (_fpieee_flt (GetExceptionCode(), GetExceptionInformation(), fpieee_handler)) {
	printf ("fpieee_handler: EXCEPTION_EXECUTE_HANDLER");
  }

  /* ... */
}

void unmask_fpsr(void) {
  unsigned int u;
  unsigned int control_word;
  _controlfp_s(&control_word, 0, 0);
  u = control_word & ~(_EM_INVALID \| _EM_DENORMAL \| _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT);
  _controlfp_s( &control_word, u, _MCW_EM);
  return ;
}

int fpieee_handler(_FPIEEE_RECORD *ieee) {
  /* ... */

  switch(ieee->RoundingMode) {
    case _FpRoundNearest:
      /* ... */
      break;

      /* Other RMs include _FpRoundMinusInfinity, _FpRoundPlusInfinity, _FpRoundChopped */
      /* ... */
    }

  switch(ieee->Precision) {
    case _FpPrecision24:
      /* ... */
      break;

      /* Other Ps include _FpPrecision53*/
      /* ... */
    }

   switch(ieee->Operation) {
     case _FpCodeAdd:
       /* ... */
       break;

       /* Other Ops include _FpCodeSubtract, _FpCodeMultiply, _FpCodeDivide, _FpCodeSquareRoot, _FpCodeCompare, _FpCodeConvert, _FpCodeConvertTrunc */
       /* ... */
    }

  /* process the bitmap ieee->Cause */
  /* process the bitmap ieee->Enable */
  /* process the bitmap ieee->Status */
  /* process the Operand ieee->Operand1, evaluate format and Value */
  /* process the Operand ieee->Operand2, evaluate format and Value */
  /* process the Result ieee->Result, evaluate format and Value */
  /* the result should be set according to the operation specified in ieee->Cause and the result format as specified in ieee->Result */
  /* the Result set is based on the */
  /* ... */
}

Risk Assessment

If floating point exceptions go undetected, they will cause one or more of these conditions: a security vulnerability, lower program efficiency, and inaccurate results. Most processors stall for a significant duration (sometimes up to a second or even more on 32-bit desktop processors) when an operation incurs a NaN.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

FLP03-A

1 (low)

2 (probable)

2 (medium)

P4

L3


References

[[IEEE 754]]
[[Intel 01]]
[[Keil 08]]
[[MSDN]] "fpieee_flt (CRT)"
[[Open Group 04]] "fenv.h - Floating point environment"
[[SecurityFocus 07]]


FLP02-A. Understand the caveats of floating point exceptions      05. Floating Point (FLP)       FLP30-C. Do not use floating point variables as loop counters

  • No labels