INVARIANT_CONDITION.GEN

不変条件式

INVARIANT_CONDITION.GEN チェッカーは、選択または反復ステートメントで真偽条件を検索、あるいはブランチにおいて、到達不能なコード指摘を起こす、論理演算子の引数を検索します。INVARIANT_CONDITION.UNREACH と異なり、INVARIANT_CONDITION.GEN は、制御するブランチにおいて、到達不能コード指摘を生じない条件 (UNREACH.GEN または UNREACH.RETURN) に対してのみ報告されます。

脆弱性とリスク

到達不能条件は、記述されたコードとその設計意図との不一致により、意図しないプログラム動作を引き起こす可能性があります。到達不能条件は、コードのメンテナンスやレビュー時に混乱を引き起こすこともあります。

例 1

コピー
   extern void process_bytes(char bytes[], unsigned size);
   extern void set_err_flag();
  
   int foo(char bytes[], int size)
   {
       if (size > 0) {
           process_bytes(bytes, (unsigned)size);
       } else if (size == -1) {
           set_err_flag();
          if (size < 0) {    // <== invariant condition
              set_err_flag();
          }
          return -1;
      }
      return 0;
  }

Klocwork は、8 行目における前のチェックによるこのブランチの値である変数「サイズ」は -1 であることが知られているので、10 行目の「サイズ < 0」条件を INVARIANT_CONDITION.GEN 指摘として報告します。この場合、報告される条件は必ず「」となり、if ステートメントとして使用しても、到達不能コードを生じません。

この例では、サイズ変数の条件に間違いがある、または変数の 1 つが冗長である可能性があります。

例 2

コピー
   extern void execute_task();
   extern void submit_delay();
  
   const int KIND_X_MASK = 0x01;
  
   void checked_run(bool flag, int kind) {
       if (flag || (kind & KIND_X_MASK == 0)) {  // <== invariant condition 'kind & (KIND_X_MASK == 0)'
           execute_task();
       } else {
          submit_delay();
      }
  }

演算子 II の引数として使用され、演算子 & および == が先にあるので、「 KIND_X_MASK == 0」式の値が最初に 0(偽)と評価され、次に「kind & 0」の値が 0(偽)に評価されるため、Klockwork は 7 行目で使用されている、式「(kind & KIND_X_MASK == 0)」を INVARIANT_CONDITION.GEN 指摘として報告します。

この例では、作者は演算子の先行について、不適切な仮定をしました。修正するためには、括弧を使用して、予想される先行にします。

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

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