Frama-c:无法理解 WP 内存模型

Frama-c : Trouble understanding WP memory models

我正在寻找可以让我证明基本的 C 内存操作的 WP options/model,例如:

我稍微看了看 WP 的文档,我使用的 frama-c 版本 (Magnesium-20151002) 似乎有几种内存模型(Hoare、Typed、+cast、+ref、.. .) 但给定示例的 none 已通过上述任何模型得到证明。文档中明确指出 Typed 模型不处理指向 int 的指针转换。我很难理解每个 wp-model 背后到底发生了什么。如果我能够验证至少 post-memcpy 函数的条件,那将对我有很大帮助。

此外,我已经看到 this 关于 void 指针的问题,至少在 Magnesium 版本中,WP 显然没有很好地处理这些问题。我还没有尝试过其他版本的 frama-c,但我认为较新的版本可以更好地处理 void 指针。

非常感谢您的建议!

我在最新版的Frama-C中试过这个例子(当然格式稍微修改了一下)

对于 memcpy 案例

断言 2 失败但断言 3 被成功证明(主要是因为断言 2 的失败导致错误假设,这证明了一切)。

所以其实这两个说法都无法证明,和你的问题一样。

这个结论是合理的,因为 wp 插件中使用的内存模型(据我所知)没有假设结构中字段之间的关系,即在 header_src 中第一个两个字段是 8 位字符,但它们可能不会像 char[2] 那样在物理内存中嵌套组织。相反,它们之间可能有填充(有关详细说明,请参阅 wiki)。因此,当您尝试将此类结构中的位复制到另一个结构时,Frama-C 变得完全混乱并且不知道您在做什么。

就我而言,Frama-C 不支持任何精确控制内存布局的方法,例如gcc 的 PACKED 强制编译器删除填充。

我面临同样的问题,(一点也不优雅)解决方案是,改用数组。数组总是嵌套的,所以如果你试图将一个char[4]复制到一个short[2],我认为这个断言是可以证明的。

对于 Cast pointer to int 案例

使用内存模型 Typed+cast,我使用的当前版本 (Chlorine-20180501) 支持指针和 uint64_t 之间的转换。您可能想试试这个版本。

另外,强烈建议通过why3调用Z3和CVC4,性能肯定比Alt-Ergo好

  • memcpy

    推理memcpy(或Frama_C_memcpy)的结果超出了当前WP插件的范围。唯一适用于您的情况的内存模型是 Bytes(氯手册第 13 页),但未实现。

    请注意,Frama_C_memcpy 中的后置条件 不是 您在这里想要的。您断言集合 dest[0..n]src[0..n] 相等。首先,您应该停在 n-1。其次,更重要的是,这太弱了,实际上不足以证明调用者的两个断言。你想要的是对所有字节的量化。参见例如Frama-C 的标准库中的谓词 memcmp,或变体 \forall int i; 0 <= i < n -> dest[i] == src[i];

    顺便说一句,只有当 destsrc 正确分开时,此后置条件才成立,而您的函数不需要这样做。否则,你应该写dest[i] == \at (src[i], Pre)。而且你的 requires 也因为另一个原因太弱了,因为你只要求第一个字符有效,而不是 n 第一个字符。

  • 将指针转换为 int

    基本上,当前在 WP 中实现的所有模型都无法推理使用多个不兼容类型(通过使用联合或指针转换)访问内存的代码。在某些情况下,比如Typed,会在语法上检测到强制转换,并发出警告,警告无法分析代码。 Typed+Cast 模型是 Typed 的变体,其中 一些 类型转换被接受。如果指针在使用前被重新转换为它的原始类型,分析是正确的只有。这个想法是允许使用一些需要转换为 void* 的 libc 函数,但仅此而已。

    你的例子又有点不同,因为 MEMORY_ADDR 很可能总是用类型 some_stuct 来寻址。稍微更改代码并将您的函数更改为采用指向此类型的指针是否可以接受?这样,您将在一个尚未证明的函数中 "hide" 转换为 MEMORY_ADDR