静态分析检查无法发现C++的小问题

3okqufwl  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(151)

我在我们的C++静态分析工具中遇到了一个令人惊讶的假阴性。
我们使用Klocwork(当前为2021.1),
几个同事报告发现KW应该发现的问题。
我举了个简单的例子:

int theIndex = 40;

int main()
{
  int arr[10] = {0,1,2,3,4,5,6,7,8,9};
  return arr[theIndex];
}

任何一个业余爱好者都可以看到我肯定是在访问数组[0..9]的越界数组成员[40]。
但是KW没有报告明显的缺陷!
TBH,我也用过CppCheck和SonarQube,那些也失败了!
测试更直接的流程,如:

int main()
{
  int theIndex = 40;
  int arr[10] = {0,1,2,3,4,5,6,7,8,9};
  return arr[theIndex];
}

确实找到了丰富的素材。
我的猜测是KW没有将main()视为入口点,因此假设theIndex可能在调用之前被更改。
我还厌倦了一个"可能工作"的版本(如果有另一个任务完美同步的话)

int theIndex;

int foo() {
  const int arr[10] = {0,1,2,3,4,5,6,7,8,9};
  return arr[theIndex];
}

int main()
{
  theIndex = 40;
  return foo();
}

CppCheck发现它"没有bug"。
我的问题是:

  • 我是否错误配置了工具?
  • 我该怎么办?
  • KW应该发现这个问题吗?或者它是SA工具的一个限制?
  • 有没有一个好的工具能够捕捉到这些问题?
    • 编辑:**

由于@RichardCritten假设SA工具意识到其他编译单元可以更改theIndex的值,因此未指出问题。
这在声明static int theIndex = 40确实指示问题时成立。
现在我想知道:
KW得到了完整的建造规范
因此,理论上,该工具可以跟踪软件的所有分支,并跟踪theIndex的可能值(可能是计算限制)。

  • 是否有方法指示该工具执行此操作?
  • 有点像"链接"阶段?
lmvvr0a8

lmvvr0a81#

我的猜测是KW没有将main()视为入口点,因此假设索引可能在调用之前被更改。
theIndex实际上可以在输入main之前被改变。程序中任何地方的全局变量的初始化器都可以执行任意代码并访问所有全局变量。因此,如果假设全局变量的所有初始值在输入main之前保持不变,则该工具可能会产生大量误报。
当然,这并不意味着该工具无论如何都不能决定发出警告,冒着误报的风险,我不知道上面提到的工具是否可以配置为这样做。
如果这是一个常量,请将其标记为constexpr。然后我希望工具能够识别这个问题。
如果它不应该是一个常量,尝试摆脱它。全局变量不是常量会导致很多问题。因为它们可能会被任何一个未知函数体的调用所修改(在进入main或线程之前),所以对于人类、静态分析器和优化器来说,很难跟踪它们。
赋予变量内部链接 * 可以 * 简化分析,因为工具可能能够证明给定翻译单元中没有任何东西可以从另一个翻译单元访问以设置变量的值。则另一个单元中的全局初始化器仍然可以在输入main之前修改它。如果不是这种情况,并且变量的翻译单元中也没有修改它的全局初始化器,那么该工具可以确保该值在main之前保持不变。
外部链接不起作用,因为任何翻译单元都可以简单地通过声明变量来访问它。
从技术上讲,我认为一个足够复杂的工具可以进行全程序分析,以验证全局变量是否在main之前被修改过。然而,如果涉及动态库,这在理论上已经是有问题的,我不认为这是静态分析器所采取的典型方法。(在这一点上我可能是错误的。)

相关问题