EN JP CN

DBZ.ITERATOR

DBZ.ITERATOR

ループ反復子がゼロ除算で使用される可能性があります

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

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

DBZ.ITERATOR チェッカーは、ゼロ値を確認せずに、ループの実行でゼロ定数値を割り当てられたループ反復子が明示的に使用されるか、除算やモジュロ演算の除数としてこれを使用する可能性がある関数に渡される状況にフラグを立てます。

脆弱性とリスク

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

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

脆弱コード例

1  int count_sum_of_custom_arithmetic_series()
2  {    
3      int sum = 0;
4      for (int i = -10; i < 10; ++i) {
5          sum += 3628800 / i;
6      }    
7      return sum;
8  }

Klocwork は5 行目で指摘レポートを生成し、ループ反復子 ‘i’ がループ反復中に0を割り当てられ、この値が除算の除数として使用されていることを示します。ゼロで除算することにより、予期しない結果や意図しない結果となる可能性があります。

修正コード例

1  int count_sum_of_custom_arithmetic_series()
2  {    
3      int sum = 0;
4      for (int i = -10; i < 10; ++i) {
5          if (i != 0) {
6              sum += 3628800 / i;
7          }
8      }
9      return sum;
10  }   

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

関連チェッカー

外部参考資料

拡張機能

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

制限事項

このチェッカーは、整数型でのみ動作します。浮動小数点型では動作しません。つまり、浮動小数点型の関連する欠陥はこのチェッカーでは検出されません。たとえば、次のようになります。
1  double count_sum_of_custom_arithmetic_series()
2  {
3      double sum = 0;
4      for (double i = -10.0; i < 10.0; ++i) {
5          sum += 3628800 / i;   // Divide by zero will not be detected here since it is a floating-point type.
6      }
7      return sum;
8  }
このチェッカーはゼロと評価する抽象的(象徴的)表現では動作しません。つまり、この種の理由の関連する欠陥はこのチェッカーでは検出されない可能性があります。たとえば、次のようになります。
1  int count_sum_of_custom_arithmetic_series()
2  {
3      int sum = 0;
4      for (int i = -10; i < 10; ++i) {
5          sum += 3628800 / (i - i);   // Divide by zero will happen here since i - i = 0. Not detected by this checker.
6      }
7      return sum;
8  }
このチェッカーは、+1 または -1 のステップ(または間隔)のあるループ反復子でのみ動作します。つまり、+1 または -1 以外のステップのあるループ反復子の関連する欠陥はこのチェッカーでは検出されません。たとえば、次のようになります。
1  intcount_sum_of_custom_arithmetic_series_with_step_of_two()
2  {
3      int sum = 0;
4      for (int i = -10; i < 10; i += 2) {
5          sum += 3628800 / i;            // Divide by zero will not be detected here since it the step of i is +2.
6      }
7      return sum;
8  }