Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verification behavior changes when making unrelated changes #1585

Closed
keyboardDrummer opened this issue Nov 11, 2021 · 1 comment
Closed

Verification behavior changes when making unrelated changes #1585

keyboardDrummer opened this issue Nov 11, 2021 · 1 comment
Assignees
Labels
part: verifier Translation from Dafny to Boogie (translator)

Comments

@keyboardDrummer
Copy link
Member

keyboardDrummer commented Nov 11, 2021

Due to the way the Dafny verification pipeline currently works, the runtime or success of a proof verification may change when changes unrelated to that proof are made to a Dafny program.

An example of this was shown in #1570, where using Dafny 3.2, the program verifies, but no longer verifies when some commented lines are uncommented. This behavior is surprising since the commented lines are unused type definitions so they should not influence the program.

module foo {
   newtype uint128 = i:int | 0 <= i < 0x1_0000_0000_0000_0000_0000_0000_0000_0000
   const MAX_UINT8 : int := 0x100 - 1
  //  type uint = uint128 
}

import opened foo

//datatype Status = Success(uint: uint) | Failure(error: string)

method bar(a: uint128, b: uint128) 
{ 
    var a1: nat := a as nat;
    var b1: nat := b as nat; 
    if (a1 >= 0 && b1 >= 0) {
      assert (a1 * b1) >= 0;  //    <------------------------- FAILS
    } 
}

Implementation

To resolve this issue, the Dafny verification pipeline must, for each proof it sends to the SMT solver, ensure that the sent SMT commands remain exactly the same when changes unrelated to the proof are made to the Dafny program.

Related PRs:

@keyboardDrummer keyboardDrummer added the part: verifier Translation from Dafny to Boogie (translator) label Nov 11, 2021
@keyboardDrummer keyboardDrummer self-assigned this Nov 11, 2021
keyboardDrummer added a commit to boogie-org/boogie that referenced this issue Nov 22, 2021
…med (#452)

Related Dafny issue: dafny-lang/dafny#1585

This PR includes changes #453

SMT solvers in practice can show significantly different behavior in terms of total runtime and `check-sat` result when identifiers in the input are renamed. Such changes in solver output are often surprising to the Boogie programmer, so this PR introduces an option to normalize names in the Boogie program.

### Changes
- Enables normalizing any names that occur in the Boogie program when translating it into SMT commands.
- Remove unused code that was in SMTLibNamer and UniqueNamer

### Testing
- Add a test that checks that renaming various elements in a Boogie program does not effect the solver input.
- Add the `/normalizeNames:1` option to all tests that inspect the SMT model, to verify that names in the parsed SMT model are correctly translated back to their original name.

Co-authored-by: Remy Willems <>
keyboardDrummer added a commit to boogie-org/boogie that referenced this issue Nov 24, 2021
…ants and functions (#450)

Related Dafny issue: dafny-lang/dafny#1585

Introduce the aggressive pruning option `/prune:2`, which will remove any axioms that aren't reachable as a definition axiom. To prevent removing most axioms, the keyword `uses` is introduced that can be used to provide, for functions and constants, a definition axiom that only partially defines the definition, and it can be used to define multiple definition axioms. Here's an example:

```
const unique fourOrThree : int uses {
    axiom four == 4 || four == 3;
}

function returnsThree(x: int): int uses {
    axiom (forall x: int :: x != 0 ==> returnsThree(x) == 3);
    axiom (forall x: int :: x == 0 ==> returnsThree(x) == 3);
}

procedure validates()
  requires fourOrThree != 3
  ensures returnsThree(4) == 3;
  ensures fourOrThree == 4;
{
  
}
```

The `uses` keyword can also be used to handle situation where automatic pruning and `exclude_dep` would otherwise incorrectly remove an axiom.

An example is the following:
```
function {:exclude_dep} $Box<T>(T): Box;
function {:identity} {:exclude_dep} Lit<T>(x: T): T { x } uses {
  axiom (forall<T> x: T :: { $Box(Lit(x)) } $Box(Lit(x)) == Lit($Box(x)) );
}
```

Without the `uses` keyword, the axiom would be pruned since $Box and Lit are marked as `{:exclude_dep}`.



Co-authored-by: Remy Willems <>
@keyboardDrummer
Copy link
Member Author

Resolved by #1612

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
part: verifier Translation from Dafny to Boogie (translator)
Projects
None yet
Development

No branches or pull requests

1 participant