Skip to content

Commit

Permalink
fix: Use the right bitvector comparison in ComputeLessEq
Browse files Browse the repository at this point in the history
Dafny adds a free invariant on each loops that states that the loop variable is
smaller than or equal to its initial value.  For bitvectors, Dafny produced ≥
instead of ≤, possibly due to a typo?

Specifically, the issue was:

- In `Translator.TrStatement.cs` (`TrLoop`):

  ```
  // include a free invariant that says that all completed iterations so far have only decreased the termination metric
  …
  Bpl.Expr decrCheck = DecreasesCheck(toks, types, types, decrs, initDecr, null, null, true, false);
  ```

- In `Translator.cs` (`DecreasesCheck`):

  ```
  Bpl.Expr less, atmost, eq;
  ComputeLessEq(toks[i], types0[i], types1[i], ee0[i], ee1[i], out less, out atmost, out eq, includeLowerBound);
  ```

- In `Translator.cs` (`ComputeLessEq`):

  ```
  } else if (ty0 is BitvectorType) {
    BitvectorType bv = (BitvectorType)ty0;
    eq = Bpl.Expr.Eq(e0, e1);
    less = FunctionCall(tok, "lt_bv" + bv.Width, Bpl.Type.Bool, e0, e1);
    atmost = FunctionCall(tok, "ge_bv" + bv.Width, Bpl.Type.Bool, e0, e1);
  ```

  `"ge_bv"` is wrong.

* `Source/Dafny/Verifier/Translator.cs`
  (`ComputeLessEq`): Change `ge` into `le`.
* `Test/git-issues/git-issue-2511.dfy`:
  New file, showing the issue in all places where `ComputeLessEq` was used.

Introduced in 3f899b9.

Closes #2511.
  • Loading branch information
cpitclaudel committed Jul 28, 2022
1 parent afd3138 commit c787bd5
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Source/Dafny/Verifier/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9287,7 +9287,7 @@ void ComputeLessEq(IToken tok, Type ty0, Type ty1, Bpl.Expr e0, Bpl.Expr e1, out
BitvectorType bv = (BitvectorType)ty0;
eq = Bpl.Expr.Eq(e0, e1);
less = FunctionCall(tok, "lt_bv" + bv.Width, Bpl.Type.Bool, e0, e1);
atmost = FunctionCall(tok, "ge_bv" + bv.Width, Bpl.Type.Bool, e0, e1);
atmost = FunctionCall(tok, "le_bv" + bv.Width, Bpl.Type.Bool, e0, e1);

} else if (ty0 is BigOrdinalType) {
eq = Bpl.Expr.Eq(e0, e1);
Expand Down
59 changes: 59 additions & 0 deletions Test/git-issues/git-issue-2511.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// RUN: %dafny /compile:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"

module WhileLoops {
lemma false_lemma()
ensures false
{
var tmp: bv64 := 1;
while tmp != 0
decreases tmp
{
tmp := tmp >> 1;
}
assert false; // Assertion failure
}
}

module Recursion {
method Infloop(b: bv8)
requires b == 3
ensures false
decreases b
{
Infloop'(b + 1); // decreases clause might not decrease
}

method Infloop'(b: bv8)
requires b == 4
decreases b, 0
ensures false
{
Infloop(b - 1);
}

method Boom()
ensures false
{
Infloop(3);
}
}

module Traits {
trait T {
method Infloop(b: bv8)
requires b == 3
ensures false
decreases b
}

class C extends T {
method Infloop(b: bv8) // method's decreases clause must be below or equal to that in the trait
requires b == 3
ensures false
decreases b + 1, 0
{
(this as T).Infloop(b);
}
}
}
5 changes: 5 additions & 0 deletions Test/git-issues/git-issue-2511.dfy.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
git-issue-2511.dfy(14,11): Error: assertion might not hold
git-issue-2511.dfy(24,12): Error: decreases clause might not decrease
git-issue-2511.dfy(51,11): Error: method's decreases clause must be below or equal to that in the trait

Dafny program verifier finished with 3 verified, 3 errors

0 comments on commit c787bd5

Please sign in to comment.