验证涉及数组

时间:2020-07-27 22:27:49

标签: dafny

首先,我要感谢Rustan和整个社区为您在Dafny上所做的工作。这是一种很棒的语言!

我正在研究硕士论文,该论文涉及使用Dafny对虚拟机进行形式验证。

这是我定义虚拟机(剥离后的版本)的方式:

class VM
{
    var v: array<bv8>;
    var I: bv16;
    var memory: array<bv8>;
    predicate Valid()
      reads this
    {
        v.Length == 16
        && memory.Length == 0x0FFF
    }

    constructor Init()
      ensures Valid()
    {
        v := new bv8[16];
        I := 0;
        memory := new bv8[0x0FFF];
    }
}

到目前为止一切顺利。我有几种方法可以改变此计算机的状态。特别是,这是一个:

method parse_opcode_registers(vm: VM, opcode: bv16)
  requires vm.Valid()
  modifies vm`I, vm.v
{
    var i: int := 0;
    var bound := ((opcode & 0x0F00) >> 8) as int;

    if opcode & 0xF0FF == 0xF065
    {
        while i < bound && vm.I as int < vm.memory.Length
          decreases bound - i
        {
            vm.v[i] := vm.memory[vm.I];
            i := i + 1;
            vm.I := vm.I + 1;
        }
    }
}

这通过了达芙妮的验证。但是,当存在此方法的调用方时,就会发生此问题。即,以下代码将产生错误call may violate context's modifies clause

method Main() {
    var vm := new VM.Init();
    parse_opcode_registers(vm, 0xF018);
}

任何提示将不胜感激。

1 个答案:

答案 0 :(得分:1)

您需要将ensures fresh(v)添加到Init的{​​{1}}构造函数中。

基本上,问题在于Dafny很担心,因为VM声称要修改parse_opcode_register,但是Dafny不确定vm.v的来源。请记住,Dafny一次只分析一种方法,因此在分析vm.v时它不会在构造函数Init内查看。相反,Dafny仅查看先决条件。这就是为什么在后置条件中添加Main可以解决问题的原因。

fresh(v)的含义是fresh(blah)是在方法执行期间重新分配的。

有关更多信息,请参见FAQ question about modifies clauses