Main Content

CERT C: Rule FLP32-C

Prevent or detect domain and range errors in math functions

Description

Rule Definition

Prevent or detect domain and range errors in math functions.1

Polyspace Implementation

The rule checker checks for Invalid use of standard library floating point routine.

Extend Checker

Extend this checker to check for defects caused by specific values and invalid use of functions from a custom library. For instance:

Examples

expand all

Issue

Invalid use of standard library floating point routine occurs when you use invalid arguments with a floating point function from the standard library. This defect picks up:

  • Rounding and absolute value routines

    ceil, fabs, floor, fmod

  • Fractions and division routines

    fmod, modf

  • Exponents and log routines

    frexp, ldexp, sqrt, pow, exp, log, log10

  • Trigonometry function routines

    cos, sin, tan, acos, asin, atan, atan2, cosh, sinh, tanh, acosh, asinh, atanh

Risk

Domain errors on standard library floating point functions result in implementation-defined values. If you use the function return value in subsequent computations, you can see unexpected results.

Fix

The fix depends on the root cause of the defect. Often the result details show a sequence of events that led to the defect. Use this event list to determine how the function argument acquires invalid values. You can implement the fix on any event in the sequence. If the result details do not show the event history, you can trace back using right-click options in the source code and see previous related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface.

It is a good practice to handle for domain errors before using a standard library floating point function. For instance, before calling the acos function, check if the argument is in [-1.0, 1.0] and handle the error.

See examples of fixes below.

If you do not want to fix the issue, for instance, when you handle infinities in your code, add comments to your result or code to avoid another review. See:

By default, a Bug Finder analysis does not recognize infinities and NaNs. Operations that results in infinities and NaNs might be flagged as defects. To handle infinities and NaN values in your code, use the option Consider non finite floats (-allow-non-finite-floats).

Example – Domain Error
#include <math.h>

double arccosine(void) {
    double degree = 5.0;
    return acos(degree); //Noncompliant
}

The input value to acos must be in the interval [-1,1]. This input argument, degree, is outside this range.

Correction – Change Input Argument

One possible correction is to change the input value to fit the specified range. In this example, change the input value from degrees to radians to fix this defect.

#include <math.h>

double arccosine(void) {
    double degree = 5.0;
    double radian = degree * 3.14159 / 180.;
    return acos(radian);
}
Example – Range Error
#include <math.h>
#include <fenv.h>
#include <errno.h>

void calculate_sinh (double x)
{
    double result;
    result = sinh (x);   //Noncompliant
}

void call_sinh_calculator()
{
    double x = 10.e32;
    calculate_sinh(x);
}

The sinh function is called with a large argument that results in an overflow.

Correction – Handle Range Errors

You cannot prevent range errors but only handle them later.

For instance, if a range error occurs, the function sinh sets errno to nonzero values on certain implementations. In those implementations, you can check errno for non-zero values to handle error conditions.

The following function uses the error handling recommendations given in FLP32-C.

#include <math.h>
#include <fenv.h>
#include <errno.h>

void calculate_sinh (double x)
{
    double result;
    result = sinh (x);   //Noncompliant
    if ((math_errhandling & MATH_ERRNO) && errno != 0) {
        /* Handle range error */
    }
    else if ((math_errhandling & MATH_ERREXCEPT) && 
    fetestexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) != 0) {
        /* Handle range error */
    }
}

void call_sinh_calculator()
{
    double x = 10.e32;
    calculate_sinh(x);
}

Note that the rule checker continues to report the range error even if it is handled later. In this case, you can mark the error as justified. See:

Check Information

Group: Rule 05. Floating Point (FLP)

Version History

Introduced in R2019a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.