关于strstr的ACSL合同
我试图为一个C函数编写一个规范,该函数搜索另一个字符串中第一个出现的字符串(实际上是string.h的strstr函数) 我遇到的第一个问题是,我无法证明循环不变量,我认为我使用strlen(在u fc_string_axiomatic.h中定义的公理)的方式有问题关于strstr的ACSL合同,c,string,strstr,frama-c,C,String,Strstr,Frama C,我试图为一个C函数编写一个规范,该函数搜索另一个字符串中第一个出现的字符串(实际上是string.h的strstr函数) 我遇到的第一个问题是,我无法证明循环不变量,我认为我使用strlen(在u fc_string_axiomatic.h中定义的公理)的方式有问题 #包括 /*@ 需要有效的_字符串(s1); 需要有效的_字符串(s2); */ 字符*strfind(常量字符*s1,常量字符*s2){ 如果(*s2==0) 返回s1; /*@ 循环不变量0你的循环不变量是正确的(我成功地证
#包括
/*@
需要有效的_字符串(s1);
需要有效的_字符串(s2);
*/
字符*strfind(常量字符*s1,常量字符*s2){
如果(*s2==0)
返回s1;
/*@
循环不变量0你的循环不变量是正确的(我成功地证明了它们),但是它们太弱了,你应该加强它们。下面是我用Frama-C插件(Jessie的继任者)证明的函数的一个版本
/*@
requires valid_string(s1);
requires valid_string(s2);
*/
char *strfind (const char *s1, const char *s2) {
if (*s2 == 0)
return s1;
/*@
loop invariant valid_string(s1);
loop invariant strlen(\at(s1,Pre)) == (s1 - \at(s1,Pre)) + strlen(s1);
loop invariant 0 <= s1 - \at(s1,Pre) <= strlen(\at(s1,Pre));
loop assigns s1;
*/
while (*s1) {
const char *rs1 = s1;
const char *rs2 = s2;
/*@
loop invariant valid_string(rs1);
loop invariant valid_string(rs2);
loop invariant strlen(\at(s1,Pre)) == (rs1 - \at(s1,Pre)) + strlen(rs1);
loop invariant strlen(s2) == (rs2 - s2) + strlen(rs2);
loop invariant 0 <= rs1 - s1 <= strlen(s1);
loop invariant 0 <= rs2 - s2 <= strlen(s2);
loop assigns rs1, rs2;
*/
while (*rs1 && *rs2 && (*rs1 == *rs2)) {
rs1++;
rs2++;
}
if (*rs2 == 0)
return s1;
s1++;
}
return 0;
}
/*@
需要有效的_字符串(s1);
需要有效的_字符串(s2);
*/
字符*strfind(常量字符*s1,常量字符*s2){
如果(*s2==0)
返回s1;
/*@
循环不变有效_字符串(s1);
循环不变strlen(\at(s1,Pre))==(s1-\at(s1,Pre))+strlen(s1);
循环不变量0侧注:代码简化:while((*rs1==*rs2)和&*rs1){
。谢谢!如果我想指定两种行为(找到/未找到),我可以简单地检查(在假设子句中)在执行期间是否!*s1(即主循环到达末尾,因为没有找到模式)?否。假设在函数的预状态下对
子句进行求值,并且不能引用函数体内发生的情况。成功案例必须使用存在量化,失败案例必须使用forall/exists。要完成byako的注释(但如果您在行为方面有具体问题,您应该提出另一个问题),如果您有行为,您可以使用for bhv:assert…;
指示仅当bhv
处于活动状态时,断言才应保持。在您的情况下,主循环后的for found:assert\false
将指示当处于行为中时已找到
(如图所示,必须在pre状态上使用假设子句进行精确计算),函数不应达到返回0;
/*@
requires valid_string(s1);
requires valid_string(s2);
*/
char *strfind (const char *s1, const char *s2) {
if (*s2 == 0)
return s1;
/*@
loop invariant valid_string(s1);
loop invariant strlen(\at(s1,Pre)) == (s1 - \at(s1,Pre)) + strlen(s1);
loop invariant 0 <= s1 - \at(s1,Pre) <= strlen(\at(s1,Pre));
loop assigns s1;
*/
while (*s1) {
const char *rs1 = s1;
const char *rs2 = s2;
/*@
loop invariant valid_string(rs1);
loop invariant valid_string(rs2);
loop invariant strlen(\at(s1,Pre)) == (rs1 - \at(s1,Pre)) + strlen(rs1);
loop invariant strlen(s2) == (rs2 - s2) + strlen(rs2);
loop invariant 0 <= rs1 - s1 <= strlen(s1);
loop invariant 0 <= rs2 - s2 <= strlen(s2);
loop assigns rs1, rs2;
*/
while (*rs1 && *rs2 && (*rs1 == *rs2)) {
rs1++;
rs2++;
}
if (*rs2 == 0)
return s1;
s1++;
}
return 0;
}