在Z3中表示内存缓冲区的最有效方法

时间:2014-06-05 14:01:52

标签: z3 formal-verification

我想在Z3中为固定大小的内存缓冲区及其访问操作建模。缓冲区的大小可以是从几个字节到几百个字节的任何位置。几种现有工具(例如,KLEE)采用的标准方法是在域和比特矢量范围上创建数组变量。每个内存缓冲区都有这样一个数组,内存读/写使用select / store操作进行编码。

唉,在我的基准测试中,使用这种方法时,Z3(*)似乎始终比STP慢。在更详细地分析查询以弄清楚发生了什么之前,我想确保我使用"对"在Z3中编码内存操作的方法(因为,诚然,STP专门设计用于数组和位向量)。

那么在Z3中表示内存缓冲区的最有效方法是什么?到目前为止,我正在考虑几种替代方案:

  1. Use assertions指定内存缓冲区的初始值,而不是使用嵌套的store - s。但是,在我的初步测试中,这似乎会进一步减慢Z3的速度。
  2. 使用bitvectors对缓冲区进行编码。但是,得到的位向量可能会变得非常大(大约1000位),而且我不确定Z3或任何其他解算器是否能够有效地处理它。
  3. 为每个内存字节和use nested ite expressions创建单独的位向量变量,以将内存访问路由到相应的变量。但是,我担心这会使模型复杂化并引入量词的需要。
  4. 使用未解释的函数而不是数组,但这需要重新定义数组公理,其方式可能不如Z3自带的内置数组理论。
  5. 我还缺少哪些更好的方法吗?

    (*)默认的非增量求解器,Z3分支unstable@aba79802cfb5

1 个答案:

答案 0 :(得分:3)

关于在KLEE样式应用程序中使用数组有一点意见。 如果使用等式初始化数组,Z3将无法正常工作:

  (assert (= A (store (store (store .. (store A0 i1 v1) ..) i4 v4) i5 v5)))

制定以下约束的效率要高得多:

  (assert (= (select A i1) v1))
  (assert (= (select A i2) v2))

(当索引是不同的常数或已知不同时,它可以工作)

您还可以关闭数组的扩展性。默认情况下,数组被视为扩展。 对于KLEE样式应用程序而言无关紧要。