Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edited by sciSpider v2.4 (sch jbop) (X_X)@==(Q_Q)@

...

Operating System

How to handle floating point errors

Linux
Solaris 10
Mac OS X 10.5

Use the C99 floating point exception functions.

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d7385b46951e488b-898e5bfb-4ca24c97-829482fd-c056cd63ab534780cf6b3b20"><ac:plain-text-body><![CDATA[

Windows

Either use the C99 floating point exception function or structured exception handling through _fpieee_flt [[MSDN

AA. C References#MSDN]]

]]></ac:plain-text-body></ac:structured-macro>

...

Noncompliant Code Example

In the following non-compliant noncompliant code, 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.

...

However, as the comments indicate, various exceptional conditions occur that may lead to unexpected arithmetic results.

Compliant Solution 1

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

Code Block
bgColor#ccccff
#include <fenv.h>
#pragma STDC FENV_ACCESS ON

fpOper_fenv(void) {
  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)

Microsoft 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().

Code Block
bgColor#ccccff
fpOper_usingStatus(void) {
  /* ... */
  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)

Microsoft 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.

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

  unmask_fpsr();

  _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 */

  /* ... */
}

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 C

low

probable

high

P2

L3

Automated Detection

The tool Compass / ROSE could detect violations of this rule, by ensuring that floating point operations are surrounded by feclearexcept() and fetestexcept(). It would need to look for type conversions to float or double, divisions (by a number not known to be nonzero) and multiplication. It may be wisest to apply this to all floating point operations in general.

Related Vulnerabilities

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

References

Wiki Markup
\[[IEEE 754|AA. C References#IEEE 754 2006]\]
\[[Intel 01|AA. C References#Intel 01]\]
\[[Keil 08|AA. C References#Keil 08]\]
\[[MSDN|AA. C References#MSDN]\] "[fpieee_flt (CRT)|http://msdn.microsoft.com/en-us/library/te2k2f2t(VS.80).aspx]"
\[[Open Group 04|AA. C References#Open Group 04]\] "[{{fenv.h}} - Floating point environment|http://www.opengroup.org/onlinepubs/009695399/basedefs/fenv.h.html]"
\[[SecurityFocus 07|AA. C References#SecurityFocus 07]\]

...