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

Compare with Current View Page History

« Previous Version 2 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 these exceptions occur. For example, while the following statement

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

readily generates a runtime error / exception , whereas

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

generates no error messages.

Though the floating point exception conditions and handling is standardized by IEEE [1], the 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="01b83f31-09ad-4ff3-b25e-bd50074d6ebb"><ac:plain-text-body><![CDATA[Fedora Core 5

C99 FP functions - These functions are declared in fenv.h [2]
]]></ac:plain-text-body></ac:structured-macro>
Before fenv.h based functions were standardized; an alternative to using these C99/fenv function is using ieee_flags and ieee_handler  

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ba1577ab-d7de-44db-a842-a133eaba1168"><ac:plain-text-body><![CDATA[

Windows

Structured Exception Handling - user defined handler _fpieee_flt [3]
]]></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 the range check on various operands for the operations has been intentionally ignored, since our intention is 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

Here is an example that demonstrates how to handle FP operations using the FP functions as standardized in C99.

#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);
	.....
}

Implementation-Specific Details

Windows OS nor the libraries with MS Visual studio support C99 functions, instead Structured Exception Handling is used to handle for FP operation .  Windows also provides an alternative method to get the FP exception code - using _statusfp/_statusfp2.

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

Using the SEH allows the programmer to change the results of the FP operation that caused the error condition. Using SEH also provides more information about the error condition

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unmask_fp();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \_try
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Store into y is inexact and underflows:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y = a;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // divide by zero operation
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b = y / x;

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

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...
}

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

int fpieee_handler (_FPIEEE_RECORD \*ieee)
{
&nbsp;&nbsp;&nbsp; // ...

&nbsp;&nbsp;&nbsp; switch(ieee->RoundingMode)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case \_FpRoundNearest:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ....
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /\* Other RMs include \_FpRoundMinusInfinity, \_FpRoundPlusInfinity, \_FpRoundChopped \*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ....
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; switch(ieee->Precision)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case \_FpPrecision24:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ....
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /\* Other Ps include \_FpPrecision53*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ....
&nbsp;&nbsp; }

&nbsp;&nbsp; switch(ieee->Operation)
&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case \_FpCodeAdd:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /\* Other Ops include \_FpCodeSubtract, \_FpCodeMultiply, \_FpCodeDivide, \_FpCodeSquareRoot, \_FpCodeCompare, \_FpCodeConvert, \_FpCodeConvertTrunc \*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ....

&nbsp;&nbsp; }

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

Risk Assessment

The Floating point exceptions if they go undetected will cause one or more of these conditions - security vulnerability, lower program efficiency and generate inaccurate results. Most processors stall for significant duration (sometimes upto a second or even more on 32bit desktop processors) when an operation incur a NaN.

References

[1] IEEE standard for binary floating-point arithmetic

http://ieeexplore.ieee.org/xpl/standardstoc.jsp?isnumber=1316http://ieeexplore.ieee.org/xpl/standardstoc.jsp?isnumber=1316

[2] fenv.h - Floating point environment

http://www.opengroup.org/onlinepubs/009695399/basedefs/fenv.h.htmlhttp://www.opengroup.org/onlinepubs/009695399/basedefs/fenv.h.html

[3] MSDN - CRT - fpieee_flt

http://msdn2.microsoft.com/en-us/library/te2k2f2t(VS.80).aspxhttp://msdn2.microsoft.com/en-us/library/te2k2f2t(VS.80).aspx

[4] Floating-Point IEEE Filter for Microsoft* Windows* 2000 on the Intel® Itanium™ Architecture

ftp://download.intel.com/software/opensource/libraries/ieee/ieee_filter_windows2000.pdfftp://download.intel.com/software/opensource/libraries/ieee/ieee_filter_windows2000.pdf

[5] Linux Kernel Floating Point Exception Handler Local Denial of Service Vulnerability

http://www.securityfocus.com/bid/10538/discuss

[6] ARM support for floating-point computations

http://www.keil.com/support/man/docs/armlib/armlib_bihbjiea.htmhttp://www.keil.com/support/man/docs/armlib/armlib_bihbjiea.htm

  • No labels