EN JP CN

DBZ.CONST.CALL

DBZ.CONST.CALL

ゼロ定数値が関数に渡され、ゼロによる除算で使用される可能性があります。

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

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

DBZ.CONST.CALL チェッカーは、ゼロ値を確認せずに、明示的なゼロ定数値が関数呼び出しに直接渡され、除算やモジュロ演算の除数として使用される可能性がある状況にフラグを立てます。

脆弱性とリスク

通常、整数のゼロによる除算は、プロセスの失敗や例外を引き起こします。また、演算は成功するかもしれませんが、結果に誤りとなります。浮動小数のゼロでの除算は、より分かりにくくなります。これは、コンパイラの実装に依存しています。コンパイラが IEEE 浮動小数点標準規格 (IEEE 754) に従う場合、浮動小数をゼロで除算した結果は明確なものとなります。しかし、C および C++ 標準規格は IEEE 754 規格への準拠を強制しません。従って、浮動小数のゼロでの除算の結果は、C および C++ では明確ではなく、従って、プロセスが失敗したり例外が発生したりする可能性があります。

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

脆弱コード例

1  int compute_mean(int array[], size_t size)
2  {
3      int sum = 0;
4      for (size_t i = 0; i < size; ++i) {
5          sum += array[i];
6      }
7      return sum / size;
8  }
9
10 void use_mean()
11 {     
12     int mean = compute_mean(0, 0);
13 }

Klocwork は 11 行目で指摘レポートを生成し、ゼロ定数値が関数 ‘compute_mean’ に直接渡され、7 行目の除算の除数としてこの関数で使用されていることを示します。ゼロで除算することにより、予期しない結果や意図しない結果となる可能性があります。

修正コード例

1  int compute_mean(int array[], size_t size)
2  {
3      if (size == 0) {
4          return 0;   // or exceptional case.
5      }
6
7      int sum = 0;
8      for (size_t i = 0; i < size; ++i) {
9          sum += array[i];
10     }    
11     return sum / size;
12 } 
13
14 void use_mean()
15 {
16     int mean = compute_mean(0, 0);
17 } 

前のスニペットからの問題が修正されました:これにより、入力変数 ‘size’ が3行目にゼロ定数値の例外ケースがないかをチェックし、この特定ケースで除算が行われないようにします。

関連チェッカー

外部参考資料

拡張機能

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

制限事項

このチェッカーは、整数型でのみ動作します。浮動小数点型では動作しません。つまり、浮動小数点型の関連する欠陥はこのチェッカーでは検出されません。たとえば、次のようになります。
1  void do_dbz(double divisor)
2  {    
3      double doit = 23 / divisor;     // Divide by zero will not be detected here since it is a floating-point type.
4  }
5
6  void call_do_dbz()
7  {   
8      do_dbz(0.0);    // Divide by zero not detected by this checker.
9  }