INVARIANT_CONDITION.GEN

不変条件式

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

脆弱性とリスク

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

例 1

  1 extern void process_bytes(char bytes[], unsigned size);
  2 extern void set_err_flag();
  3
  4 int foo(char bytes[], int size)
  5 {
  6     if (size > 0) {
  7         process_bytes(bytes, (unsigned)size);
  8     } else if (size == -1) {
  9         set_err_flag();
 10         if (size < 0) {    // <== invariant condition
 11             set_err_flag();
 12         }
 13         return -1;
 14     }
 15     return 0;
 16 }

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

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

例 2

  1 extern void execute_task();
  2 extern void submit_delay();
  3
  4 const int KIND_X_MASK = 0x01;
  5
  6 void checked_run(bool flag, int kind) {
  7     if (flag || (kind & KIND_X_MASK == 0)) {  // <== invariant condition 'kind & (KIND_X_MASK == 0)'
  8         execute_task();
  9     } else {
 10         submit_delay();
 11     }
 12 }

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

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

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

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