...
Function | Domain | Range |
|---|---|---|
|
| noNo |
|
| noNo |
|
| noNo |
|
| noNo |
noneNone | yesYes | |
| noneNone | yesYes |
| noneNone | yesYes |
|
| noNo |
|
| noNo |
|
| yesYes |
| noneNone | yesYes |
| noneNone | yesYes |
| yesYes | |
| noNo | |
| noneNone | yesYes |
|
| yesYes |
| noneNone | yesYes |
|
| noNo |
| noneNone | yesYes |
| noneNone | yesYes |
| noneNone | yesYes |
Domain Checking
The most reliable way to handle domain errors is to prevent them by checking arguments beforehand, as in the following template:
...
It is also difficult to check for math errors using errno because an implementation might not set it. For real functions, the programmer can tell whether the implementation sets errno by checking whether math_errhandling & MATH_ERRNO is nonzero. For complex functions, the C Standard, Section section 7.3.2, simply states that "an implementation may set errno but is not required to" [ISO/IEC 9899:2011].
The System V Interface Definition, Third Edition (SVID3), provides more control over the treatment of errors in the math library. The user can provide a function named matherr that is invoked if errors occur in a math function. This function can print diagnostics, terminate the execution, or specify the desired return value. The matherr() function has not been adopted by C, so its use is not generally portable.
The following error-handing template uses C Standard functions for floating-point errors when the C macro math_errhandling is defined and indicates that they should be used; otherwise, it examines errno.:
| 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
|
...
The following noncompliant code determines the square root of x.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
double x; double result; result = sqrt(x); |
...
Since this function has domain errors but no range errors, bounds checking can be used to prevent domain errors.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
double x;
double result;
if (isless(x, 0)) {
/* Handle domain error */
}
result = sqrt(x);
|
...
This noncompliant code example determines the hyperbolic cosine of x.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
double x; double result; result = cosh(x); |
...
Since this function has no domain errors but may have range errors, the programmer must detect a range error 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;
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
|
...
The following noncompliant code raises x to the power of y.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
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 zero 0 and y is zero0. A domain error or range error may occur if x is zero 0 and y is negative, and a range error may occur if the result cannot be represented as a double.
...
Since 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 if a range error occurs 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 */
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
|
...
Tool | Version | Checker | Description |
|---|---|---|---|
Fortify SCA | 5.0 |
| Can detect violations of this rule with CERT C Rule Pack. |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
| [ISO/IEC 9899:2011] | Section 7.3, "Complex Arithmetic <complex.h>"Section 7.12, "Mathematics < math.h>" |
| [Plum 1985] | Rule 2-2 |
| [Plum 1989] | Topic 2.10, "conv—Conversions and Overflow" |
...