CERT.MATH.DOMAIN.CHECK
標準ライブラリ数学関数に渡される 1 つ以上の引数が有効なドメイン外にある
CERT.MATH.DOMAIN.CHECK チェッカーは、標準ライブラリの数学関数が定義されているドメイン外に数学関数の入力引数があるという潜在的な欠陥を識別します。
脆弱性とリスク
数学的に有効な範囲外の入力が関数に与えられた場合、ドメインエラーが発生します。以下の表に、標準数学関数の倍精度バリアントの概要と共に、定義されたドメイン内に入力が収まっていることを検証するために必要なチェックを示します。
| 関数 | 有効なドメイン |
|---|---|
| acos(x) | -1 <= x && x <= 1 |
| asin(x) | -1 <= x && x <= 1 |
| atan(x) | なし |
| atan2(y, x) | なし |
| acosh(x) | x >= 1 |
| asinh(x) | なし |
| atanh(x) | -1 <= x && x <= 1 |
| cosh(x),sinh(x) | なし |
| exp(x),exp2(x),expm1(x) | なし |
| ldexp(x, exp) | なし |
| log(x),log10(x),log2(x) | x >= 0 |
| log1p(x) | x >= -1 |
| ilogb(x) | x != 0 && !isinf(x) && !isnan(x) |
| logb(x) | x != 0 |
| scalbn(x, n),scalbln(x, n) | なし |
| hypot(x, y) | なし |
| pow(x,y) | x > 0 || ( x == 0 && y > 0) || (x < 0 && y は整数) |
| sqrt(x) | x >= 0 |
| erf(x) | なし |
| erfc(x) | なし |
| lgamma(x),tgamma(x) | x != 0 && !(x < 0 && x は整数) |
| lrint(x), lround(x) | なし |
| fmod(x, y),remainder(x, y), remquo(x, y, quo) | y != 0 |
| nextafter(x, y), nexttoward(x, y) | なし |
| fdim(x,y) | なし |
| fma(x,y,z) | なし |
ドメインエラーの例として、実数演算では意味を持たない sqrt(-1.0) などの負の数の平方根が挙げられます。
軽減と防止
プログラマーは、数学関数を呼び出す前に引数の境界を慎重にチェックし、境界違反の場合は代替策を講じることによってドメインエラーを防止することができます。
脆弱コード例
コピー
#include <math.h>
void func() {
double x = -1.0;
double result;
result = sqrt(x);
}
Klocwork は、5 行目で CERT.MATH.DOMAIN.CHECKを報告し、定義されているドメイン外の負の引数で sqrt が呼び出されていることを示します。
修正コード例
コピー
#include <math.h>
void func() {
double x = -1.0;
double result;
if (x < 0.0)
{
//handle domain error
}
result = sqrt(x);
}
9 行目で sqrt が呼び出される前に 7 行目でエラー条件が適切に処理されるので、この場合、CERT.MATH.DOMAIN.CHECK が報告される可能性はありません。