Prove Length函数计算char数组元素编号

时间:2015-07-18 21:06:10

标签: frama-c formal-verification

我试图在C中证明像strlen这样的函数,但是frama-c并不能证明 发布条件和loop variant len子句。我无法理解为什么!

我尝试过的事情:

/*@
    axiomatic elementNumber_axioms
    {
        logic unsigned elementNumber{L}(char *a);

        axiom elementNumber_base{L}:
            elementNumber(\null) == 0;

        axiom elementNumber_step{L}:
            \forall char *a;
            \valid(a) ==> elementNumber(a) == elementNumber(a+1) + 1;
    }
*/

/*@
    assigns \nothing;
    ensures \result == elementNumber(\old(s));
*/
unsigned stringlen(const char *s)
{
    unsigned len = 0;

/*@
    loop assigns len;
    loop assigns s;
    loop variant len;
*/
    while(*s)
    {
        ++s;
        ++len;
    }

    return len;
}

我做错了什么?

1 个答案:

答案 0 :(得分:3)

你写的内容有几个问题。一份非详尽的清单:

  • 你的stringlen()不处理s为NULL的情况。

    如果注释标准的C strlen()函数,则不需要处理这种情况,因为标准的C strlen()函数不允许参数为NULL。但是,elementNumber()逻辑函数的公理定义将elementNumber(\null)定义为0,而stringlen()的后置条件是结果等于elementNumber(s)。因此,您需要处理此案例。

  • stringlen()中的while循环在遇到nul字节时终止。但是,elementNumber()逻辑函数的定义仅取决于指针是否有效。

  • stringlen()没有关于ss + 1等是否有效的先决条件。

  • 您的elementNumber()逻辑函数未定义无效指针的值。

  • 您需要指定循环不变量。

我建议看看Frama-C如何注释strlen():

/*@ requires valid_string_src: valid_string(s);
  @ assigns \result \from s[0..];
  @ ensures \result == strlen(s);
  @*/
extern size_t strlen (const char *s);

strlen()逻辑函数和valid_string()谓词在源代码分发的share/libc/__fc_string_axiomatic.h中定义,在撰写本文时为Sodium-20150201。