CERT.MATH.RANGE.CHECK
範囲エラーを発生させる可能性のあるライブラリ数学関数の呼び出し後にエラー条件をチェックする必要がある
CERT.MATH.RANGE.CHECK チェッカーは、標準ライブラリの数学関数によって範囲エラーがトリガーされる可能性があるが、エラー条件の検証または処理が失敗するという、潜在的な欠陥を識別します。
脆弱性とリスク
範囲エラーは、計算結果がオーバーフローまたはアンダーフローになった場合にのみ発生します。以下の表に、標準数学関数の倍精度バリアントの概要と共に、C 標準で指定されている範囲エラーをトリガーできるかどうかを示します。
| 関数 | 範囲エラーの可能性 |
|---|---|
| acos(x) | いいえ |
| asin(x) | はい |
| atan(x) | はい |
| atan2(y, x) | いいえ |
| acosh(x) | はい |
| asinh(x) | はい |
| atanh(x) | はい |
| cosh(x),sinh(x) | はい |
| exp(x),exp2(x),expm1(x) | はい |
| ldexp(x, exp) | はい |
| log(x),log10(x),log2(x) | いいえ |
| log1p(x) | いいえ |
| ilogb(x) | はい |
| logb(x) | はい |
| scalbn(x, n),scalbln(x, n) | はい |
| hypot(x, y) | はい |
| pow(x,y) | はい |
| sqrt(x) | いいえ |
| erf(x) | はい |
| erfc(x) | はい |
| lgamma(x),tgamma(x) | はい |
| lrint(x), lround(x) | はい |
| fmod(x, y),remainder(x, y), remquo(x, y, quo) | はい |
| nextafter(x, y), nexttoward(x, y) | はい |
| fdim(x,y) | はい |
| fma(x,y,z) | はい |
このようなエラーは、通常は防ぐことができないため、確実に検出することが重要です。これには、errno、math_errhandling、浮動小数点例外など、複数のエラーインジケーターのチェックが含まれます。
これらの条件を調べることで、プログラムは範囲エラーを識別し、適切に対応することができます。
軽減と防止
準拠アプローチには、範囲エラーを引き起こす可能性のある標準ライブラリ数学関数を呼び出した後に発生する場合があるエラー条件を検証および処理することが含まれます。
脆弱コード例
コピー
void func(double x)
{
double res = sinh(x);
}
sinh(x) 関数呼び出しの結果として範囲エラーが発生する可能性があるため Klocwork で CERT.MATH.RANGE.CHECK が報告されますが、エラー条件がチェックされません。
修正コード例
コピー
void func1(double x) {
double result;
#pragma STDC FENV_ACCESS ON
if (math_errhandling & MATH_ERREXCEPT) {
feclearexcept(FE_ALL_EXCEPT);
}
errno = 0;
result = sinh(x);
if ((math_errhandling & MATH_ERRNO) && errno != 0) {
// Handle range error via errno
}
if ((math_errhandling & MATH_ERREXCEPT) &&
fetestexcept(FE_INVALID | FE_DIVBYZERO |
FE_OVERFLOW | FE_UNDERFLOW)) {
// Handle range error via floating-point exceptions
}
// Use result...
result = 89.67;
}
11 行目で sinh(x) の呼び出し後にエラー条件が適切にチェックされるので、この場合、CERT.MATH.RANGE.CHECK が報告される可能性はありません。