Frama-C行为和价值分析

Frama-C behaviors and value analysis

我想用Frama-C分析一个包含 一个类似于 read 的函数:给定缓冲区 buf 及其长度 len,该函数在 buf 中准确写入 len 个字节(除非出现错误) .

我是用ACSL指定的,但是值分析是给的 我的结果很奇怪。

这是我的规范,加上一个 main 测试函数:

/*@
  assigns \result \from \nothing;
  assigns *(buf+(0..len-1)) \from \nothing;
  behavior ok:
    requires \valid(buf+(0..len-1));
    ensures  \result == 0;
    ensures  \initialized(buf+(0..len-1));
  behavior error:
    ensures  \result == -1;
 */
int read(char *buf, int len);

int main() {
  char buf[10];
  read(buf, 10);
  return 0;
}

当运行 frama-c -val test.c(我使用的是Frama-C Neon)时,我得到了这个结果:

[value] Analyzing a complete application starting at main
[value] Computing initial state
[value] Initial state computed
[value] Values of globals at initialization

[value] computing for function read <- main.
        Called from test.c:16.
[value] using specification for function read
test.c:6:[value] Function read, behavior ok: precondition got status valid.
test.c:10:[value] Function read, behavior error: this postcondition evaluates to false in this
        context. If it is valid, either a precondition was not verified for this
        call, or some assigns/from clauses are incomplete (or incorrect).
[value] Done for function read
[value] Recording results for main
[value] done for function main
[value] ====== VALUES COMPUTED ======
[value] Values at end of function main:
  NON TERMINATING FUNCTION

我确实放置了 assigns/from 子句,error 行为没有先决条件(因此,默认情况下,它们是经过验证的)。

这是怎么回事?在这种情况下如何进行分析?

尽管有消息,但实际问题是 read 函数的规范中存在错误:两种行为在 同时 处于活动状态,因为它们不包含 assumes 子句(隐含地,两者都有 assumes \true)。因此,两个 ensures 子句都为真,这意味着 \result == 0 && \result == 1.

这个错误导致了一个矛盾的状态,其中 function 既是 0 又是 1(同时),因此不能返回任何结果, 因此该函数被认为是非终止的。

这里有几种可能的解决方案之一是添加一个 非确定性幽灵变量,比如 _read_state,表示 函数的内部状态,然后使用这个变量来定义 不同行为的不相交 assumes 子句:

//@ ghost volatile int _read_state;
/*@
  assigns \result \from \nothing;
  assigns *(buf+(0..len-1)) \from \nothing;
  behavior ok:
    assumes _read_state == 0;
    requires \valid(buf+(0..len-1));
    ensures  \result == 0;
    ensures  \initialized(buf+(0..len-1));
  behavior error:
    assumes _read_state != 0;
    ensures  \result == -1;
 */

注意 == 0!= 0 比较是任意的;任何一组可能不相交的值都可以在这里工作。

使用这个规范,我们得到这个程序的预期结果:

[value] Analyzing a complete application starting at main
[value] Computing initial state
[value] Initial state computed
[value] Values of globals at initialization
  _read_state ∈ [--..--]
[value] computing for function read <- main.
        Called from test.c:18.
[value] using specification for function read
tread.c:7:[value] Function read, behavior ok: 
    precondition got status valid. 
    (Behavior may be inactive, no reduction performed.)
[value] Done for function read
[value] Recording results for main
[value] done for function main
[value] ====== VALUES COMPUTED ======
[value] Values at end of function main:
  buf[0..9] ∈ [--..--] or UNINITIALIZED
  __retres ∈ {0}