DBZ.ITERATOR.CALL

関数呼び出しでゼロによる除算が発生する可能性がある

ゼロを除数として除算やモジュロ演算に使用しようとすると、ランタイムエラーが発生します。ゼロによる除算の欠陥は、効果的でないエラー処理または競合状態のためにしばしば起こります。通常、プログラム終了の異常が発生します。値が C/C++ コードにおいて除算またはモジュロ演算の除数として使用される前に、ゼロに等しくないことを確認するためにチェックする必要があります。

DBZ チェッカーは、除算やモジュロ演算の除数としてゼロが使用されているインスタンスを検索します。

DBZ.ITERATOR.CALL チェッカーは、関数の呼び出しでループ反復子がゼロによる除算の演算で使用される可能性がある状況にフラグを立てます。

脆弱性とリスク

ゼロによる除算は通常、プログラムがクラッシュしないように慎重に回避されます。呼び出し元が提供する除算器により、関数にこの指摘を引き起こす可能性がある場合、関数のユーザーはゼロによる除算の条件をもたらす可能性があります。このケースは、ループによって除算器の条件が決まる場合に特に当てはまります。これは、予期すべきことを計算または知ることがより困難であるためです。

軽減と防止

ゼロによる除算の指摘は通常、効果的でない例外処理が原因で発生します。この脆弱性を回避するために、これを除算やモジュロ演算の除数として使用する前に、ゼロ値がないかを確認してください。

除算器の範囲を計算し、関数内と関数呼び出し元の両方でゼロの条件を回避するように設定する必要があります。

脆弱コード例 1

コピー
int foo(int a, int b)
{
    int x = 0;
    for (int i = a; i < b; i++) {
        x += 100/i;
    }
    return x;
}
void bar()
{
    int a = -3;
    int b = 2;
    foo(a, b);    // DBZ.ITERATOR.CALL
}

関数 'foo' では、for ループの条件はパラメーター 'a' と 'b' によって決まります。'bar' 関数はパラメーター -3 と 2 で 'foo' 関数を呼び出しており、その範囲には 0 が含まれます。Klocwork は、13 行目で DBZ.ITERATOR.CALL の指摘を報告します。

修正コード例 1

コピー
int foo(int a, int b)
{
    int x = 0;
    for (int i = a; i < b; i++) {
        x += 100/i;
    }
    return x;
}
void bar()
{
    int a = -3;
    int b = 0;
    foo(a, b);    // NO DBZ.ITERATOR.CALL
}

関数 bar で変数 'b' を 0 に調整すると、ループの条件は 0 に達しなくなります。

脆弱コード例 2

コピー
int foo(int a, int b)                                    
{                                                        
    int x = 0;                                           
    for (int i = a; i >= b; i--) {                        
        x += 100/i;                                      
    }                                                    
    return x;                                            
}                                                        
void bar()                                               
{                                                        
    foo(3,0);    // DBZ.ITERATOR.CALL                   
}

例 1 と同様に、関数 'foo' に for ループがありますが、この場合、ループの条件には最小値として 0 が含まれています。したがって、パラメーター 0 で foo を呼び出すと、11 行目で DBZ.ITERATOR.CALL の指摘を引き起こします。

修正コード例 2

コピー
int foo(int a, int b)                                    
{                                                        
    int x = 0;                                           
    for (int i = a; i >= b; i--) {                        
        x += 100/i;                                      
    }                                                    
    return x;                                            
}                                                        
void bar()                                               
{                                                        
    foo(3,1);    // NO DBZ.ITERATOR.CALL                   
}

修正されたこの例では、呼び出し元はパラメーター 3 と 1 を使用するため、ループで 0 の条件を回避しています。

セキュリティトレーニング

Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。

拡張機能

このチェッカーは、Klocwork knowledge base (ナレッジベース) を利用して拡張できます。詳細については、C/C++ 解析のチューニングを参照してください。