...
Code Block |
---|
if (/* Arguments that will cause a domain error. */) { /* Handle domain error. */ } else { /* Perform computation. */ } |
Range Checking
Range errors cannot usually be prevented, so the most reliable way to handle range errors is to detect when they have occurred and act accordingly.
...
Code Block |
---|
#include <math.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv.h> #endif /* ... */ #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) feclearexcept(FE_ALL_EXCEPT); #endif errno = 0; /* Call the function. */ #if !defined(math_errhandling) \ || (math_errhandling & MATH_ERRNO) if (errno != 0) { /* Handle range error. */ } #endif #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error. */ } #endif |
See FLP03-C. Detect and handle floating-point errors for more details on how to detect floating-point errors.
Anchor | ||||
---|---|---|---|---|
|
Noncompliant Code Example (sqrt(
...
)
)
...
The following noncompliant code determines the square root of x
:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <math.h> void func(double x;) { double result; result = sqrt(x); } |
However, this code may produce a domain error if x
is negative.
Compliant Solution (sqrt()
)
Because this function has domain errors but no range errors, bounds checking can be used to prevent domain errors:
Code Block | ||||
---|---|---|---|---|
| ||||
double x; double #include <math.h> void func(double x) { double result; if (isless(x, 0)) { /* Handle domain error. */ } result = sqrt(x); } |
Anchor | ||||
---|---|---|---|---|
|
Noncompliant Code Example (cosh(
...
)
, sinh(
...
)
...
, Range Errors)
This noncompliant code example determines the hyperbolic cosine of x
:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <math.h> void func(double x;) { double result; result = coshsinh(x); } |
This code may produce a range error if x
has a very large magnitude.
Compliant Solution (cosh()
, sinh()
, Range Errors)
Because this function has no domain errors but may have range errors, the programmer must detect a range error and act accordingly:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <math.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv.h> #endif void func(double x) { /* ... */ double result; result = sinh(x); #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) feclearexcept(FE_ALL_EXCEPT); #endif errno = 0; double x; double result; result = sinh(x); #if !defined(math_errhandling) \ || (math_errhandling & MATH_ERRNO) if (errno != 0) { /* Handle range error. */ } #endif #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error. */ } #endif } |
Anchor | ||||
---|---|---|---|---|
|
Noncompliant Code Example (pow(
...
)
)
The following noncompliant code raises x
to the power of y
:
Code Block | |||||||
---|---|---|---|---|---|---|---|
| |||||||
#include <math.h> void func(double x; , double y;) { double result; result = pow(x, y); } |
However, this code may produce a domain error if x
is negative and y
is not an integer or if x
is 0 and y
is 0. A domain error or range error may occur if x
is 0 and y
is negative, and a range error may occur if the result cannot be represented as a double
.
Compliant Solution (pow()
)
Because the pow()
function can produce both domain errors and range errors, the programmer must first check that x
and y
lie within the proper domain, then detect whether a range error occurs and act accordingly:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <math.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv.h> #endif /* ... */ ) #include <fenv.h> #endif void func(double x, double y) { #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) feclearexcept(FE_ALL_EXCEPT); #endif errno = 0; /* Call the function */ double x; double y; double result; if (((x == 0.f) && islessequal(y, 0)) || (isless(x, 0))) { /* Handle domain error. */ } result = pow(x, y); #if !defined(math_errhandling) \ || (math_errhandling & MATH_ERRNO) if (errno != 0) { /* Handle range error. */ } #endif #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error. */ } #endif } |
Risk Assessment
Failure to prevent or detect domain and range errors in math functions may result in unexpected results.
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
...
[ISO/IEC 9899:2011] | Subclause 7.3, "Complex Arithmetic <complex.h >"Subclause 7.12, "Mathematics < math.h >" |
[Plum 1985] | Rule 2-2 |
[Plum 1989] | Topic 2.10, "conv—Conversions and Overflow" |
[UNIX 1992] | System V Interface Definition (SVID3) |
...