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

Fix examples after en tree #1827

Open
wants to merge 53 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3a9c13b
add basic IDE logging, start error cleanup
Jun 28, 2021
bfd0566
clean up additional implication errors
Jun 28, 2021
49f72e4
add structure to stmt fail in line with impl fail
Jun 29, 2021
716a2e1
redesign error message types, pipe through to log
Jul 7, 2021
9283f0e
fix default heapster environments missing ioref
Jul 8, 2021
1e427a4
carry more information through on most common implication error
Jul 9, 2021
059ab7b
Merge branch 'heapster-ide-info' of github.com:GaloisInc/saw-script i…
Jul 9, 2021
6fef67a
remove Some from error constructor
Jul 9, 2021
f3b76bb
Merge branch 'master' into heapster-ide-info
glguy Jul 26, 2021
e2c9cd6
Export valueperms in full json detail
glguy Jul 28, 2021
b59adb9
Avoid generating orphan ToJSON instances and using Given
glguy Jul 28, 2021
65ae7dd
refine jsonexport instances
glguy Jul 28, 2021
931d802
Document JSONExport
glguy Jul 28, 2021
2ad2225
Remove need for passing undefined
glguy Jul 30, 2021
ce3313b
JSONExport support for PermImpls
glguy Jul 30, 2021
df114c1
export entrypoint and caller ID information
Aug 12, 2021
8875708
cleanup imports, 80 char columns
Aug 12, 2021
5f12cc4
heapster: export function name for IDE
Aug 12, 2021
cb7c57c
heapster-saw: LogEntry with names and structure
glguy Aug 19, 2021
e768f1f
Incorporate names from bindings in JsonExport
glguy Aug 20, 2021
f60affd
Merge remote-tracking branch 'origin/master' into heapster-ide-info
glguy Aug 20, 2021
51665d7
Update PPInfo while exporting
glguy Aug 23, 2021
dc70b93
checkpoint
glguy Aug 27, 2021
f0c7747
Use types to generate names for pretty permissions where possible
glguy Aug 27, 2021
45380a5
Merge branch 'master' into heapster-ide-info
scuellar Feb 3, 2023
6170858
WIP: fixing errors introduced by the merge.
scuellar Feb 3, 2023
7694e2f
got SAW to compile after the latest merge of master
Feb 6, 2023
009caf6
Merge branch 'master' into heapster-ide-info
Feb 7, 2023
8ac9eb5
Merge branch 'master' into heapster-ide-info
Feb 7, 2023
bb9c52d
Updtate deps
scuellar Feb 13, 2023
d0fe08e
Merge branch 'master' into heapster-ide-info
scuellar Feb 13, 2023
10aacd5
update proofs xor
scuellar Feb 16, 2023
1a6a03d
Fix xor proofs
scuellar Feb 16, 2023
b85f7b7
Add a file with generlalized tactics and definitions
scuellar Feb 16, 2023
c19c2ae
Quick fix.
scuellar Feb 16, 2023
4f04499
BROKEN: c_data_proofs.v is broken. pushing to get assitance.
scuellar Feb 17, 2023
2cadcbf
One more example fixed, more powerful automation to support it.
scuellar Feb 17, 2023
2cbf50d
Updating a couple more examples and some automation.
scuellar Feb 21, 2023
3d76821
Small clean
scuellar Feb 21, 2023
dd69d30
bumping the cryptol submodule to match master
Feb 28, 2023
dbc3ccf
moved nuMatching and Liftable instances to the top of the file in Nam…
Mar 1, 2023
1310346
GHC 9 fixes
Mar 1, 2023
599cf2a
renamed the Mb' datatype to the more accessible name NamedMb, and cha…
Mar 1, 2023
856e49b
Fix the tutorial proofs.
scuellar Mar 1, 2023
7d53a24
Update the tutorial text
scuellar Mar 1, 2023
defedde
Merge branch 'heapster-ide-info' into Fix-Examples-After-EnTree
scuellar Mar 1, 2023
013f9f9
Merge branch 'master' into Fix-Examples-After-EnTree
scuellar Mar 2, 2023
42981b1
Update heapster-saw/doc/tutorial/tutorial.md
scuellar Mar 7, 2023
b7ffbf3
Update heapster-saw/doc/tutorial/tutorial.md
scuellar Mar 7, 2023
45c6fcf
Update heapster-saw/doc/tutorial/tutorial.md
scuellar Mar 7, 2023
5615ae1
Update heapster-saw/doc/tutorial/tutorial.md
scuellar Mar 7, 2023
7a74d26
simple changes after review.
scuellar Mar 7, 2023
9e538c7
Merge branch 'Fix-Examples-After-EnTree' of https://github.com/Galois…
scuellar Mar 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 65 additions & 79 deletions heapster-saw/doc/tutorial/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -685,56 +685,56 @@ Open a new coq file `tutorial_c_proofs.v` in the same folder

```
From CryptolToCoq Require Import SAWCoreScaffolding.
From CryptolToCoq Require Import SAWCoreScaffolding.
From CryptolToCoq Require Import SAWCoreVectorsAsCoqVectors.
From CryptolToCoq Require Import SAWCoreBitvectors.
From CryptolToCoq Require Import SAWCorePrelude.
From CryptolToCoq Require Import CompMExtra.

(* The following line enables pretty printing*)
Import CompMExtraNotation. Open Scope fun_syntax.
(* The following 2 lines allows better automatio*)
scuellar marked this conversation as resolved.
Show resolved Hide resolved
Require Import Examples.common.
Require Import Coq.Program.Tactics. (* Great tacticals, move to automation. Perhaps `Require Export`? *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to read this comment. Does this belong in a tutorial?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess not.


(* Import our function definitions*)
Require Import Examples.tutorial_c_gen.
Import tutorial_c.
```

It first imports all the SAW functionality we need and enables pretty
printing. Then it imports our new definitions (e.g. `add`).
It first imports all the SAW functionality we need and some useful
tactics. Then it imports our new definitions (e.g. `add`).

Our first proof will claim that the function `add` produces no
errors. More specifically, it says that for all inputs (that's what
`refinesFun` quantifies) `add` always refines to `noErrorsSpec`. That
is, it returns a pure value.
`spec_refines_eq` quantifies) `add` always refines to `safety_spec`. That
is, it returns a pure value without errors.

```
Lemma no_errors_add
: refinesFun add (fun _ _ => noErrorsSpec).
Proof.
```

We will use our automation to quickly prove the lemma, but we must
first unfold those definitions the the automation is unfamiliar with.

```
unfold add, add__tuple_fun, noErrorsSpec.
Lemma no_errors_add (x y: bitvector 64) :
spec_refines_eq (add x y) (safety_spec (x,y)).
Proof.
```

Then our function `prove_refinement` will deal with the proof.
We will use our automation to quickly prove the lemma,

```
prove_refinement.
Qed.
solve_trivial_spec 0 0. Qed.
```

You can also attempt the same proof with `add_mistyped`, which
obviously will fail, since `add_mistyped` has an error.

```
Lemma no_errors_add_mistyped
: refinesFun add_mistyped (fun _ => noErrorsSpec).
Proof.
unfold add_mistyped, add_mistyped__tuple_fun, noErrorsSpec.
prove_refinement.
(* Fails to solve the goal. *)
obviously will fail, since `add_mistyped` has an error. First, you
will note that `add_mistyped` only takes one argument (since only one
was defined in it's signature)
scuellar marked this conversation as resolved.
Show resolved Hide resolved

Lemma no_errors_add_mistyped (x: bitvector 64) :
spec_refines_eq (add_mistyped x) (safety_spec (x)).
Proof. solve_trivial_spec 0 0.

(* After rewriting the terms for clarity, you can see the
remaining goal says that an `ErrorS` is a refinement of
`RetS`. In other words, it's trying to prove that a trivially
pure function has an error. That's obviously false. *)
clarify_goal_tutorial.
Abort.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be surrounded with code blocks ``` ... ```?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.

```

Congratulations you have written your first Coq proofs with Heapster!

Expand Down Expand Up @@ -792,15 +792,12 @@ You will have to generate the `.vo` again to write proofs about
`incr_ptr`. After you do so, we can easily prove that `incr_ptr`
produces no errors.

```
Lemma no_errors_incr_ptr
: refinesFun incr_ptr (fun _ => noErrorsSpec).
Proof.
unfold incr_ptr, incr_ptr__tuple_fun.
prove_refinement.
Qed.
```

Lemma no_errors_incr_ptr (x: bitvector 64) :
spec_refines_eq (incr_ptr x) (safety_spec x).
Proof. solve_trivial_spec 0 0. Qed.```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code block is missing a closing ```.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in latest commit.

### Structs

The next function we will type-check deals with structs. In our
Expand Down Expand Up @@ -963,64 +960,54 @@ adds dynamic checks on the extracted code which we will see in the Coq
code.

Let's go to `arrays_gen.v` (which has already been generated for you)
and look for the definition of `zero_array__tuple_fun`. You will
notice that it calls `errorM` twice but, in this case that's not a
and look for the definition of `zero_array__bodies`. You will
notice that it calls `errorS` twice but, in this case that's not a
scuellar marked this conversation as resolved.
Show resolved Hide resolved
sign of a typing error! Heapster includes these errors to catch
out-of-bounds array accesses and unrepresentable indices (i.e. index
that can't be written as a machine integer). The code below is a
simplification of the `zero_array__tuple_fun` with some notation for
simplification of the `zero_array__bodies` with some notation for
readability (see below for how to enable such pritty printing).

```
zero_array__tuple_fun =
(* ... Some ommited code ... *)
LetRec f:=
(fun (e1 e2 : int64) (p1 : Vector int64 e1)
(_ _ _ : unit : Type) =>
(* ... Some ommited code ... *)
let var__4 := (0)[1] in
let var__6 := e2 < e1 in
(*... Some ommited code ...*)
if
not
((if var__6 then 1 else var__4) ==
var__4)
then
if
((17293822569102704640)[64] <= e2) &&
(e2 <= (1152921504606846975)[64])
then
If e2 <P e1
Then f e1 (e2 + (1)[64])
(p1 [e2 <- (0)[64]]) tt tt tt
Else errorM "ghost_bv <u top_bv"
else
errorM "Failed Assert at arrays.c:61:5"
else returnM p1, tt)
InBody (f e0 (0)[64] p0 tt tt tt), tt))
(fun (e0 : int64) (p0 : Vector int64 e0) =>
CallS VoidEv emptyFunStack zero_array__frame
(mkFrameCall zero_array__frame 1 e0 (0)[64] p0 tt tt tt),
(fun (e0 e1 : int64) (p0 : Vector int64 e0) (_ _ _ : unit) =>
if negb ((if e1 < e0 then (-1)[1] else (0)[1]) == (0)[1])
then
if ((17293822569102704640)[64] <= e1) && (e1 <= (1152921504606846975)[64])
then
If e1 <P e0
Then CallS VoidEv emptyFunStack zero_array__frame
(mkFrameCall zero_array__frame 1 e0 (e1 + (1)[64])
(p0 [e1 <- (0)[64]]) tt tt tt)
Else ErrorS (Vector int64 e0) "ghost_bv <u top_bv"
else ErrorS (Vector int64 e0) "Failed Assert at arrays.c:61:5"
else RetS p0, tt))
```

The arguments `e1`, `e2` and `p1` correspond to the length `len`, the
The arguments `e0`, `e1` and `p1` correspond to the length `len`, the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be careful here, because there are two distinct e0 arguments in the code above, one in each fun. I think you are referring to the second fun in that code, so it would be good to clarify this, along with some exposition about why there are two funs in the first place. (It doesn't have to be super detailed for tutorial purposes, but readers will want some kind of explanation of what is going on here.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Added some text.

offset `i`, and the array `arr`. Notice most of that the function
performs several tests before executing any computation. The first two
tests, which are within `if then else` blocks, check that the offset
is less than the array length `e2 < e1`, and that the index `i` is
is less than the array length `e1 < e0`, and that the index `i` is
within the bounds of machine integers. The former is part of the loop
condition, the second is added by Heapster to ensure the ghost
variable represents a machine integer.

The last check, which is within uppercase `If Then Else` (which
handles option types) is not part of the original function but
inserted by Heapster. It checks that the array access is within bounds
`e2 <P e1`. The operator `<P` returns an optional proof of the array
`e1 <P e0`. The operator `<P` returns an optional proof of the array
access being safe. If the check fails, the function reports a runtime
error `errorM "ghost_bv <u top_bv"`.
error `errorS _ "ghost_bv <u top_bv"`.
scuellar marked this conversation as resolved.
Show resolved Hide resolved

If all the checks pass, then the function simply calls
itself recursively, with the next index and array with a new entry zeroed out.

```
f e1 (e2 + (1)[64]) (p1 [e2 <- (0)[64]]) tt tt tt
(mkFrameCall zero_array__frame 1 e0 (e1 + (1)[64])
(p0 [e1 <- (0)[64]]) tt tt tt)
```

The extra `tt` are artifacts that get inserted by Heapster, but you
Expand All @@ -1040,9 +1027,10 @@ We shall now prove that this function in fact should never return an
error if the inputs are correct. Go to `array_proofs.v` and look at the proof

```
Lemma no_errors_zero_array
: refinesFun zero_array (fun x _ => assumingM (zero_array_precond x) noErrorsSpec).
Proof
Lemma no_errors_zero_array x y:
spec_refines_eq (zero_array x y)
(total_spec (fun '(len, vec, dec) => zero_array_precond len) (fun _ _ => True) (x,y, bvAdd _ x (intToBv _ 1))).
Proof.
```

It claims that, assuming the precondition `zero_array_precond` is
Expand All @@ -1057,12 +1045,10 @@ Definition zero_array_precond x


We will not go into detail about the proof, but notice that the
important steps are handled by custom automation. Namely we use the
commands `prove_refinement_match_letRecM_l` and `prove_refinement` to
handle refinements with and without recursion (respectively). The rest
of the proof, consists of discharging simple inequalities and a couple
of trivial entailments, where the left hand side is an error (and thus
entails anything).
important steps are handled by custom automation.

TODO: This proof is involved. Perhaps add some more details?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I definitely think so! Are you planning to resolve this TODO in this PR, or are you leaving this as future work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good point. The description more or less gets to the limit of what I understand, without going into technical details. Do you have any suggestion of how to improve this section?

We can also just commit the comment and leave it super high level at this point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we would include a more detailed tutorial that goes into the nuances of spec_refines proofs involving loops. But writing such a tutorial would take a fair bit of effort, so I can understand if you don't want to do that here. My recommendation would be to:

  1. Remove this TODO (since TODOs in a tutorial look out of place), and
  2. Open an issue as a reminder to write this more detailed tutorial.



### Recursive data structures

Expand Down
5 changes: 3 additions & 2 deletions heapster-saw/examples/_CoqProject
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
linked_list_gen.v
linked_list_proofs.v
xor_swap_gen.v
#xor_swap_proofs.v
xor_swap_proofs.v
xor_swap_rust_gen.v
#xor_swap_rust_proofs.v
c_data_gen.v
#c_data_proofs.v
c_data_proofs.v
Comment on lines -9 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that this isn't adding back more of the _proofs.v files that you've changed in this PR, such as arrays_proofs.v. Any reason not to?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't finished the proofs in arrays_proofs.v, I only fixed the first one which is the one mentioned in the tutorial.

string_set_gen.v
#string_set_proofs.v
loops_gen.v
Expand Down Expand Up @@ -39,3 +39,4 @@ sha512_gen.v
#sha512_proofs.v
io_gen.v
#io_proofs.v
common.v
Loading