如何证明 Frama-C + EVA 中非确定性值的简单等式?
How does one prove simple equalities of non-deterministic values in Frama-C + EVA?
我对 Frama-C 18.0 版(Argon)的行为有点困惑。
给定以下程序:
#include <assert.h>
#include <limits.h>
/*@ requires order: min <= max;
assigns \result \from min, max;
ensures result_bounded: min <= \result <= max ;
*/
extern int Frama_C_interval(int min, int max);
int main() {
int i,j;
i = Frama_C_interval(INT_MIN, INT_MAX);
j = i;
assert(j == i);
return 0;
}
我希望使用任何跟踪相等性的抽象域都能很容易地证明该断言。然而,调用
frama-c -eva -eva-equality-domain -eva-polka-equalities foo.c
给出:
[eva] Warning: The Apron domains binding is experimental.
[kernel] Parsing stupid_test.c (with preprocessing)
[eva] Analyzing a complete application starting at main
[eva] Computing initial state
[eva] Initial state computed
[eva:initial-state] Values of globals at initialization
[eva] using specification for function Frama_C_interval
[eva] using specification for function __FC_assert
[eva:alarm] foo.c:20: Warning:
function __FC_assert: precondition 'nonnull_c' got status unknown.
[eva] done for function main
[eva] ====== VALUES COMPUTED ======
[eva:final-states] Values at end of function main:
i ∈ [--..--]
j ∈ [--..--]
__retres ∈ {0}
我是不是漏掉了什么?
有意思。 -eva -eva-equality-domain
未处理您的示例,它是为其他目的而编写的。因此,当 x
和 y
已知相等时 x == y
的特殊情况尚未写入。这将很容易添加。
(考虑到域的名称,这可能会令人惊讶。当我们有无趣的别名(例如内核添加的临时别名)时,相等域更适合启用更多的反向传播。)
关于来自 Apron 的域名,这更令人惊讶。我修改了你的例子:
j = i;
int b = j - i;
int c = j == i;
Frama_C_dump_each_domain();
运行 frama-c -eva -eva-polka-equalities foo.c -value-msg-key d-apron
给出以下结果:
[eva] c/eq.c:23:
Frama_C_dump_each_domain:
# Cvalue domain:
i ∈ [--..--]
j ∈ [--..--]
b ∈ {0}
c ∈ {0; 1}
__retres ∈ UNINITIALIZED
# Polka linear equalities domain:
[|-i_44+j_45=0; b_46=0|]
可以看到,Apron已经推断出i
和j
之间的关系(后缀是行号),将b
简化为0,但并没有简化c
到 1。这让我感到惊讶,但解释了您观察到的不精确性。它不适用于八边形域。
我不太熟悉关系域上的抽象转换器,所以这可能是预料之中的,但这确实令人费解。处理关系运算符的代码存在于 Frama-C/Eva/Apron 中,但部分是 home-written(它不仅仅是对 Apron 原语的简单调用)。特别是调用减法运算符,分析结果与0是否相等。很难理解为什么b
会精确而c
.
我对 Frama-C 18.0 版(Argon)的行为有点困惑。
给定以下程序:
#include <assert.h>
#include <limits.h>
/*@ requires order: min <= max;
assigns \result \from min, max;
ensures result_bounded: min <= \result <= max ;
*/
extern int Frama_C_interval(int min, int max);
int main() {
int i,j;
i = Frama_C_interval(INT_MIN, INT_MAX);
j = i;
assert(j == i);
return 0;
}
我希望使用任何跟踪相等性的抽象域都能很容易地证明该断言。然而,调用
frama-c -eva -eva-equality-domain -eva-polka-equalities foo.c
给出:
[eva] Warning: The Apron domains binding is experimental.
[kernel] Parsing stupid_test.c (with preprocessing)
[eva] Analyzing a complete application starting at main
[eva] Computing initial state
[eva] Initial state computed
[eva:initial-state] Values of globals at initialization
[eva] using specification for function Frama_C_interval
[eva] using specification for function __FC_assert
[eva:alarm] foo.c:20: Warning:
function __FC_assert: precondition 'nonnull_c' got status unknown.
[eva] done for function main
[eva] ====== VALUES COMPUTED ======
[eva:final-states] Values at end of function main:
i ∈ [--..--]
j ∈ [--..--]
__retres ∈ {0}
我是不是漏掉了什么?
有意思。 -eva -eva-equality-domain
未处理您的示例,它是为其他目的而编写的。因此,当 x
和 y
已知相等时 x == y
的特殊情况尚未写入。这将很容易添加。
(考虑到域的名称,这可能会令人惊讶。当我们有无趣的别名(例如内核添加的临时别名)时,相等域更适合启用更多的反向传播。)
关于来自 Apron 的域名,这更令人惊讶。我修改了你的例子:
j = i;
int b = j - i;
int c = j == i;
Frama_C_dump_each_domain();
运行 frama-c -eva -eva-polka-equalities foo.c -value-msg-key d-apron
给出以下结果:
[eva] c/eq.c:23:
Frama_C_dump_each_domain:
# Cvalue domain:
i ∈ [--..--]
j ∈ [--..--]
b ∈ {0}
c ∈ {0; 1}
__retres ∈ UNINITIALIZED
# Polka linear equalities domain:
[|-i_44+j_45=0; b_46=0|]
可以看到,Apron已经推断出i
和j
之间的关系(后缀是行号),将b
简化为0,但并没有简化c
到 1。这让我感到惊讶,但解释了您观察到的不精确性。它不适用于八边形域。
我不太熟悉关系域上的抽象转换器,所以这可能是预料之中的,但这确实令人费解。处理关系运算符的代码存在于 Frama-C/Eva/Apron 中,但部分是 home-written(它不仅仅是对 Apron 原语的简单调用)。特别是调用减法运算符,分析结果与0是否相等。很难理解为什么b
会精确而c
.