INVARIANT_CONDITION.GEN

条件中的不变表达式

INVARIANT_CONDITION.GEN 检查器会搜索选择或迭代语句中的真/假条件或者作为逻辑运算符的自变量的真/假条件,这些条件会导致其分支中出现无法访问的代码问题。与 INVARIANT_CONDITION.UNREACH 不同,INVARIANT_CONDITION.GEN 报告仅针对在其控制的分支处不会导致不可访问的代码问题的条件(UNREACH.GENUNREACH.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 将第 10 行的 size < 0 条件报告为 INVARIANT_CONDITION.GEN 问题,因为通过之前在第 8 行进行的检查已知,此分支上的变量 size 的值为 -1。在此情况中,报告的条件会始终产生“true”且将其用作 if 语句条件不会导致不可访问的代码。

在此示例中,size 变量上的条件中可能存在错误,或者其中一个变量是冗余的。

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

Klocwork 将在第 7 行使用的表达式 (kind & KIND_X_MASK == 0) 报告为 INVARIANT_CONDITION.GEN 问题,由于将其用作运算符 || 的参数,且因为运算符 & 和 == 的优先级较高。首先,KIND_X_MASK == 0 表达式的值计算为 0 (false);其次,kind & 0 的值计算为 0 (false)。

在此示例中,作者针对运算符的优先权做出错误假设。要修正该错误,请使用括号获取预期的优先权。

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。