NUM08-J. 浮動小数点数入力が例外値でないかを検査する
浮動小数点数は3つの例外値、infinity、-infinity、NaN (not-a-number) をとることがある。これらの値は、ゼロ除算のような例外的あるいは解決不能な浮動小数点数演算の結果として生成されることもあれば、Double.valueOf(String s)メソッドなどを通じて直接ユーザ入力から取得されることもある。これらの例外値を検出し処理しないと、プログラムの不安定な動作につながる。
Double.valueOf(String s)メソッドは、NaN、infinity、あるいは-infinityを返すことがある。プログラムは、すべての浮動小数点数の入力値 (特にユーザから取得する値) にこれらの例外値が含まれないことを確認しなくてはならない。Double.isNaN(double d)やDouble.isInfinite(double d)メソッドをこの確認のために利用することができる。
NaN値は順序付けされない (unordered) ため、特に問題となりやすい。たとえば、式NaN == NaNは常にfalseを返す (「NUM07-J. NaNとの比較を行わない」を参照)。
違反コード
以下の違反コードはユーザデータを検証せずに受け取っている。
double currentBalance; // ユーザの預金残高
void doDeposit(String userInput) {
double val = 0;
try {
val = Double.valueOf(userInput);
} catch (NumberFormatException e) {
// 入力フォーマットエラーの処理
}
if (val >= Double.MAX_VALUE - currentBalance) {
// 範囲エラーの処理
}
currentBalance += val;
}
valに例外値が代入され、その値が後に演算や制御値として使用される場合、このコードは予期せぬ結果をもたらす。たとえば、ユーザはinfinityやNaNといった文字列をコマンドラインに入力することができるが、これはDouble.valueOf(String s)によって浮動小数点数表現であるinfinityやNaNとして解釈される。後でこれらの値を使う演算は無効になり、場合によっては実行時例外を引き起こしたり、サービス運用妨害 (DoS) 攻撃を可能にするであろう。
前述の違反コード例では、valにNaNが代入されるとcurrentBalanceの値もNaNになり、不正な値となる。この値が別の式で使われると、その式の結果の値もNaNになり、これは重要なデータを破壊することになるかもしれない。
適合コード
以下の適合コードでは、浮動小数点数の入力値を検査してから使用している。値はinfinity、-infinity、NaNでないことが確認されている。
double currentBalance; // ユーザの預金残高
void doDeposit(String userInput){
double val = 0;
try {
val = Double.valueOf(userInput);
} catch (NumberFormatException e) {
// 入力フォーマットエラーの処理
}
if (Double.isInfinite(val)){
// infinityエラーの処理
}
if (Double.isNaN(val)) {
// NaNエラーの処理
}
if (val >= Double.MAX_VALUE - currentBalance) {
// 範囲エラーの処理
}
currentBalance += val;
}
例外
NUM08-J-EX0: NaN、infinity、-infinityはプログラムが予期する入力として受け取られる場合もあるだろう。その場合、明示的なチェックは必要ないかもしれないが、これらの例外値を適切に処理し、例外値を処理できない別のコードに値を渡さないようにしなくてはならない。また、例外値をプログラムの通常動作時の入力として認める選択をしたことを明文化すべきである。
リスク評価
浮動小数点数入力の検査が間違っていたりそもそも検査しないと、計算間違いや予期せぬ結果につながり、結果的にプログラムの誤動作やサービス運用妨害 (DoS) が起こる恐れがある。
|
ルール |
深刻度 |
可能性 |
自動検出 |
自動修正 |
優先度 |
レベル |
|---|---|---|---|---|---|---|
|
NUM08-J |
低 |
中 |
不可 |
可 |
P4 |
L3 |
自動検出
一般に自動検出は不可能である。汚染解析のような手法を使うことで、危険なケースを多数検出できるであろう。
| ツール | バージョン | チェッカー | 説明 |
|---|---|---|---|
| Parasoft Jtest |
2024.2 |
CERT.NUM08.FPEXC | Check floating-point inputs for exceptional values |
関連ガイドライン
|
VOID FLP04-CPP. Check floating point inputs for exceptional values |
参考文献
|
[IEEE 754] |
|
|
|
|
| [Seacord 2015] |
|
翻訳元
これは以下のページを翻訳したものです。
NUM08-J. Check floating-point inputs for exceptional values (revision 96)
