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 が提供しているアプリケーションセキュリティトレーニング教材。