INVARIANT_CONDITION.GEN

Invariant expression in a condition

The INVARIANT_CONDITION.GEN checker searches for true/false conditions in selection or iteration statements or as an argument of a logic operator, that cause unreachable code issues in their branches. Unlike INVARIANT_CONDITION.UNREACH, INVARIANT_CONDITION.GEN is reported only for the conditions that don't cause an unreachable code issue (UNREACH.GEN or UNREACH.RETURN) at the branches they control.

Vulnerability and risk

Invariant conditions can cause unintended program behavior due to a mismatch between the code as written and the intended design. Invariant conditions can also cause confusion during code maintenance or code review.

Example 1

Copy
   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 reports 'size < 0' condition at line 10 as an INVARIANT_CONDITION.GEN issue, since the value of variable 'size' is known to be -1 on this branch by a previous check at line 8. In this case, the reported condition always yields 'true', and its use as an if statement condition does not cause unreachable code.

In this example, there is likely either a mistake in the conditions on the size variable or one of the variables is redundant.

Example 2

Copy
   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();
      }
  }

Klocwork reports the expression '(kind & KIND_X_MASK == 0)' used at line 7 as an INVARIANT_CONDITION.GEN issue, since it is used as an argument of operator ||, and, because of the precendence of operators & and == , the value of the 'KIND_X_MASK == 0' expression is evaluated first to 0 (false), and, second the value of 'kind & 0' is evaluated to 0 (false).

In this example, the author made an incorrect assumption regarding operator precedence. To fix it, use parentheses to get the expected precedence.

Security training

Application security training materials provided by Secure Code Warrior.