切片器:读取不确定值后继续探索路径

时间:2014-05-07 09:03:16

标签: c frama-c

我想切片以下程序:

int main() {
  int j;
  if (j) {
ERROR:
    /*@ slice pragma ctrl; */
    goto ERROR;
  }
  return 0;
}

目前,Frama-C在阅读j后停止探索路径,导致ERROR标签被切掉:

$ frama-c test.c -slice-pragma main -then-on 'Slicing export' -print
[...]
test.c:3:[kernel] warning: accessing uninitialized left-value: assert \initialized(&j);
test.c:3:[kernel] warning: completely indeterminate value in j.
[...]

有没有办法将阅读j视为读取未指定的值? 我更愿意以编程方式(在Frama-C内部)执行此操作,而无需修改分析的源代码。

我正在运行Frama-C Neon。

1 个答案:

答案 0 :(得分:1)

在执行C程序期间读取未初始化(不确定)的内存是未定义的行为or might as well be treated as such。 C程序的切片器不需要保留执行导致未定义的行为。因此,由于程序的所有执行都会导致未定义的行为,因此几乎Frama-C的切片插件生成的任何切片都是正确的切片。如果你写了if (1 / 0) {,你可能会获得相同的行为。由于我链接到的博客文章中给出的原因,两者之间没有那么大的区别。


作为解决方案,只需使用j内置的Frama_C_interval()初始化__fc_builtin.h,其中的规范在文件#include <__fc_builtin.h> ... int j = Frama_C_interval(0, 1); 中提供:

j

如果这对您来说更简单,举个简短示例,您可以将volatile int u; int main() { int j = u; ... 设置为未知值,如下所示:

Frama_C_make_unknown(&x, sizeof x);

修改

在与托马斯私下讨论之后,我添加了以下建议:

您可以编写一个Frama-C插件,将C程序转换为等效的C程序,其中每个局部变量都被初始化。我建议使用语句进行其他初始化:

Frama_C_make_unknown

其中extern int Frama_C_entropy_source; /*@ requires \valid(p + (0 .. l-1)); assigns p[0 .. l-1] \from Frama_C_entropy_source; assigns Frama_C_entropy_source \from Frama_C_entropy_source; ensures \initialized(p + (0 .. l-1)); */ void Frama_C_make_unknown(char *p, size_t l); 是一个函数,你可以设法在原始源代码中包含规范的原型(因此必须避免添加它的困难:)

{{1}}

经过这样的转换后,切片插件可以按预期工作。如果你在制作这样一个变形插件时遇到困难,你可以在frama-c-discuss或StackOverflow中提出相关问题(后者更好,因为Google没有以任何有用的方式对frama-c-discuss进行索引)。