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 将第 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)。
在此示例中,作者针对运算符的优先权做出错误假设。要修正该错误,请使用括号获取预期的优先权。