满足memcpy的证明义务? [Frama-C]

时间:2018-12-12 05:59:34

标签: frama-c

我们一直在使用Frama-C在一个商业项目上进行“实验”静态分析(集成到我们的CI中,并在整个代码库的一小部分中进行了“少量”的选择性拦截检查)

出现的障碍之一与满足wp插件在遇到memcpy调用时生成的证明义务有关。具体来说,以下三项义务: memcpy_proof_obligations

从“目标”说明中看来,Frama-C试图证明目标内存和源内存有效。

我尝试添加requires \valid()前提条件,但这似乎无济于事。在这些情况下,被测函数中的memcpy调用是将数据从输入参数复制到函数中,并将该数据放入局部变量中(作用域内)。

更复杂的是,要复制数据的局部变量是打包结构中的一个属性。

我确实希望人们能够分享一些memcpy用法的真实示例,这些示例可以满足wp引入的目标(例如,我必须添加哪些先决条件才能实现该目标可证明的?)

如果有关系,我正在运行Frama-C Magnesium-20151002(根据Ubuntu 16上的apt-get,这是“最新的”),并使用以下参数进行调用:

frama-c -wp -wp-split -wp-dynamic -lib-entry -wp-proof alt-ergo -wp-report

也相关,但缺少一个清晰的示例:Frama-c : Trouble understanding WP memory models

1 个答案:

答案 0 :(得分:4)

正如您在评论中提到的那样,正确的解决方案是使用-wp-model "Typed+Cast",以使WP接受往来于void*的强制转换(更确切地说,它将考虑p(void*)p对于任何指针都是相同的,足以证明requires的{​​{1}})。现在,如您所链接的问题的the answer中所述,此内存模型的主要问题(以及它不是默认值的原因)是它本质上不安全:根据假设,WP本身无法评估。这是一个突出此问题的小示例:

memcpy

基本上,默认的int x; char* c; /*@ assigns c; ensures c == ((char *)&x); */ void g(void) { c = &x; } /*@ assigns \nothing; ensures \separated(&x,c); */ void f() { } void main () { g(); f(); //@ assert \false; } 内存模型可确保Typedc所指向的位置(即x的后置条件)之间的分隔,因为{ {1}}和f不同,您既不能证明int的后置条件,也不能将其用作在char中推导g的假设,因为完全无法在模型中表达平等。

现在,如果您使用\false,则现在可以正确理解main的后置条件,并且证明起来很简单。 WP不会让您同时证明Typed+Castg是分开的,因为它们是一起分配的。但是,在&x中不存在这样的赋值,并且后置条件也很容易得到证明,因为我们有关于cf的两个矛盾陈述,因此证明了\false中的main &x。更一般而言,WP依赖于本地别名分析来跟踪不同类型的指针之间的潜在别名(全局分析会破坏使用模块化分析器的目的)。因此,将传递选项c视为告诉WP“信任我,该程序将不会创建缺少类型的别名”。但是,可以手动传递别名信息(或在尚未编写的全局别名检测插件的帮助下)传递别名信息。例如,使用选项-wp-model +Cast-wp-alias-vars x,c的后置条件变为f(即Unknown&x之间的分隔不再是假设,即使对于c