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