如何在 Frama-C 中证明整数是有限的

How to prove integers are finite in Frama-C

我有一小段 c 代码,如下所示:

double sum(double a, double b) {
return a+b; }

当我使用 eva-wp 运行 时,出现错误:

non-finite double value. assert \is_finite(\add_double(a, b));

但是当我添加时:

requires \is_finite(\add_double(a, b));

然后状态变为未知。

我觉得我犯了一个很简单的错误,但我不知道它是什么!

如果我们考虑file.c:

/*@ requires \is_finite(\add_double(a,b)); */
double sum(double a, double b) {
  return a+b;
}

并使用 frama-c -eva -main sum file.c 启动 Eva,我们确实处于未知状态,并且警报仍然存在。事实上,这是两个不同的问题。

首先,当主入口点中有一个 requires 子句时,Eva 尝试根据它计算的通用初始状态对其进行评估,其中 double 值可以是任何有限的double(甚至无限或 NaN,取决于内核选项 -warn-special-float 的值)。在此通用状态下,requires 不成立,因此 Unknown 状态。

其次,Eva 无法利用 requires 子句将此初始状态还原为 属性 成立的抽象状态:这将需要维持某种关系ab,这不在当前 Eva 中实现的抽象域的范围内。因此,分析是使用与没有 requires 完全相同的抽象状态完成的,并导致相同的警报。

为了验证requires(并使警报消失),您可以使用包装函数,它将构建更合适的初始状态并调用正在分析的函数,例如

#include <float.h>
#include "__fc_builtin.h"
/*@ requires \is_finite(\add_double(a,b)); */
double sum(double a, double b) {
  return a+b;
}

void wrapper() {
  double a = Frama_C_double_interval(-DBL_MAX/2, DBL_MAX/2);
  double b = Frama_C_double_interval(-DBL_MAX/2, DBL_MAX/2);
  double res = sum(a,b);
}

Frama_C_double_interval,在 $(frama-c -print-share-path)/libc 中的 __fc_builtin.h 中声明,连同其他标量类型的类似函数,returns 作为参数给出的边界之间的随机双精度值。因此,从 Eva 的角度来看,结果在相应的区间内。通过启动 frama-c -eva -main wrapper file.c,我们没有任何警报(并且 requires 有效)。更一般地说,此类包装器通常是构建用于使用 Eva 进行分析的初始状态的最简单方法。