Our artifact is provided as a VirtualBox VM, which can be launched using a standard installation of VirtualBox (tested with VirtualBox 6.1 on Mac and Ubuntu).
On most Linux distributions, VirtualBox is available as a package through
standard tools apt-get
, yum
, etc..
On Mac, it is available through Homebrew.
Recent versions of Apple computers (with Apple M1) introduce restrictions around
Kernel Extensions (which VirtualBox uses), and may at present an error with code
-1908
.
The extension must be allowed in the "Security & Privacy" pane of the settings.
Upon launching the VM you may be asked to log in, in which case, the username and password are:
username: vagrant
password: vagrant
If you have a non-x86 computer, you may need to compile our artifact from sources. Among the provided files is a tar containing all the code needed to build and verify our proofs and benchmarks. At the bottom of this document is a section titled "Building from Sources" with detailed instructions.
The rest of this document will assume that you are using the provided VM image.
On the desktop is a folder the_artifact
, inside of which are further directories:
lambda_rust
directory contains the Coq development for our mechanization.rhb_specs
directory contains the code for all Creusot benchmarks of
the RustHornBelt paper.creusot
directory contains the code for Creusot, the tool used to
generate proof obligations for rhb_specs
.
(This directory is not a contribution of the paper but is provided for
reproducibility reasons.)Also, the artifact contains the walkthroughs for Coq (coq-walkthrough.md
)
and for Creusot (creusot-walkthrough.md
).
The lambda_rust
directory contains the Coq development for our mechanization.
README.md
in lambda_rust
has more information on it.
Provided in the VM is an installation of CoqIDE, which can be used to browse
the Coq proof files (*.v
).
A shortcut is provided on the desktop to launch it.
The Coq walkthrough coq-walkthrough.md
(in the_artifact
) explains in detail
how to verify integer addition, model Vec
, verify Vec::new
, and verify
mem::swap
(featuring mutable borrows).
In particular, it focuses on the things you need to know in extending
our Coq mechanization.
The rhb_specs
directory contains the code for all Creusot benchmarks of
the RustHornBelt paper.
These benchmarks are meant to demonstrate that specifications obtained from
RustHornBelt are well adapted to usage with automated verifiers.
A README file is provided with more information on the structure of the benchmarks.
The Creusot walkthrough why3-walkthrough.md
(in the_artifact
) explains
verification of all_zero
, featuring update through mutable borrows.
Our benchmarks are verified using the deductive verification tool Creusot.
Creusot is based on the same prophetic model of mutable borrows as our formalization,
making it well adapted as a benchmarking platform for our specifications.
Creusot takes as input a Rust crate and outputs a single mlcfg
file, containing
the translation of the crate into the functional language WhyML.
The benchmarks can then be verified using automated provers in Why3.
The compiled benchmarks are provided in the file ~/Desktop/rhb-specs/proofs.mlcfg
,
and the proof session in the accompanying folder ~/Desktop/rhb-specs/proofs
.
The source of the benchmarks is provided in the src
directory.
We recommend src/all_zero.rs
as a simple example to begin with.
The proofs can be browsed by launching the Why3IDE
shortcut on the desktop.
The left-hand pane contains the proof tree and can be expanded by clicking on the arrow next to each entry or by selecting an entry and hitting the '+' mark.
When an entry is selected, the right-hand pane will highlight relevant bits of the code.
To view the actual proof context, select the Task
tab in the right-hand pane.
A tutorial for Why3 can be found here: http://why3.lri.fr/doc/starting.html#sec-gui.
By expanding the RhbSpecs_IncVec_IncVec
node fully, we reveal a list
of subentries, selecting one of the [integer overflow]
entries and opening the
Tasks
tab should show something similar to:
goal inc_vec'vc : in_bounds5 (uint32'int ( * r_12) +' 5)
There are two key facets to verify within our artifact: the Coq proof of RustHornBelt showing that we proved our claims in section 3 and our benchmarks showing our specifications are adapted to automatic verification.
Our proposed method of evaluation would be:
We make these specific claims regarding our Coq development:
We do not make the following claims:
To rebuild all the Coq proofs from scratch:
~/Desktop/lambda-rust
directoryeval $(opam env)
make clean
make
The following table contains the location of every rule mentioned in our paper
in the Coq development.
The filenames are spread across theories/typing/examples
, theories/typing
,
theories/typing/lib
(and its subfolders), and theories/prophecy
.
Proof Rule | File | Lemma |
---|---|---|
Adequacy | soundness.v |
type_soundness |
Basic | ||
MUTBOR | derived_rules.v |
ty_uniq_bor |
MUTREF-WRITE | derived_rules.v |
ty_uniq_ref_write |
MUTREF-BYE | derived_rules.v |
ty_uniq_ref_bye |
ENDLFT | programs.v |
type_endlft |
Prophecies | ||
PROPH-INTRO | prophecy.v |
proph_intro |
PROPH-FRACT | prophecy.v |
proph_tok_fractional |
PROPH-IMPL | prophecy.v |
proph_obs_impl |
PROPH-MERGE | prophecy.v |
proph_obs_and |
PROPH-TRUE | prophecy.v |
proph_obs_true |
PROPH-RESOLVE | prophecy.v |
proph_resolve |
PROPH-SAT | prophecy.v |
proph_obs_sat |
Mutable Borrows | ||
MUT-AGREE | uniq_cmra.v |
uniq_agree |
MUT-UPDATE | uniq_cmra.v |
uniq_update |
MUT-INTRO | uniq_cmra.v |
uniq_intro |
MUT-RESOLVE | uniq_cmra.v |
uniq_resolve |
Vec |
||
push |
vec_pushpop.v |
vec_push_type |
pop |
vec_pushpop.v |
vec_pop_type |
index_mut |
vec_index.v |
vec_index_uniq_type |
IterMut |
||
iter_mut |
vec_slice.v |
vec_as_uniq_slice_type |
next |
iter.v |
iter_uniq_next_type |
inc_vec |
inc_vec.v |
inc_vec_type |
Cell |
||
new |
cell.v |
cell_new_type |
get |
cell.v |
cell_get_type |
set |
cell.v |
cell_set_type |
inc_cell |
inc_cell.v |
inc_cell_type |
Mutex |
||
new |
mutex.v |
mutex_new_type |
get_mut |
mutex.v |
mutex_get_uniq |
Mem |
||
swap |
swap.v |
swap_type |
We make these specific claims regarding our benchmarks:
The non-claims:
Our benchmarks are designed to provide evidence that the specifications derived from RustHornBelt are adapted to automatic verification. For this reason, we verify several examples using the semi-automatic tool Creusot, which internally is based on the RustHornBelt model. Creusot translates Rust code to "MLCFG", a functional language structured like a control-flow graph (CFG), which can then be fed into the tool Why3 and verified using off-the-shelf provers.
In the benchmarks we axiomatize specifications proved in Coq, and then verify
example code using them.
These axiomatizations can be found in the directory src/prelude
of rhb-specs
.
The actual examples are found at the top level of src/
.
Their correspondence to the paper is detailed in the table below.
To reproduce the proofs from scratch:
~/Desktop/rhb-specs
make clean
followed by make proofs
.
The resulting file should be approximately 3-4 thousand lines long.Why3IDE
shortcut to open the generated output in a fresh proof session.The specifications used during automatic verification can be found in the files
located in src/prelude/
.
The following table shows the correspondence between the automatic and Coq specs.
Type | Automatic Spec | Coq Spec |
---|---|---|
Vec |
vec.rs |
typing/lib/vec/\*.v |
Mutex |
mutex.rs |
typing/lib/mutex/\*.v |
Spawn |
thread.rs |
typing/lib/spawn.v |
Cell |
cell.rs |
typing/lib/cell.v |
IterMut |
iter_mut.rs |
typing/lib/slice/iter.v |
Box |
box.rs |
typing/examples/unbox.v |
Fn |
fn.rs |
typing/function.v |
The example benchmarks provided in the paper correspond to the code in the
following files, within the src
directory of rhb-specs
.
Paper Name | Rust File | RHB Specs used |
---|---|---|
List-Reversal |
reversal.rs |
mem::swap |
All-Zero |
all_zero.rs |
Vec::len , Vec::index_mut |
Go-IterMut |
inc_vec.rs |
Vec::iter_mut , IterMut::next |
Even-Cell |
even_cell.rs |
Cell::get , Cell::set |
Fib-Memo-Cell |
fib_cell.rs |
Vec::index , Cell::get , Cell::set |
Even-Mutex |
concurrent.rs |
thread::spawn , JoinHandle::join , Mutex::lock , Mutex::new , (Box::leak ) |
Knights-Tour |
knights_tour.rs |
Vec::push , Vec::index , Vec::index_mut , Vec::len |
"Paper Name": the name given to the function in the paper. "Rust File": the Rust file containing the benchmark equivalent. "RHB Specs": which functions are used with RustHornBelt proven specifications.
For those who either cannot or prefer not to use the virtual machine, we also provide instructions on how to build and verify our proofs and benchmarks.
Within the provided archive, there are three folders:
lambda-rust
containing our Coq developmentcreusot
containing the Rust sources to Creusotrhb-specs
containing the benchmarks for our papergmp
using your system package manager.opam
using your system package manager.opam
by running opam init
.lambda-rust
directory by running
opam switch create .
and eval $(opam env)
. This will avoid polluting your
global ocaml environment.opam repo add coq-released https://coq.inria.fr/opam/released
opam repo add iris-dev https://gitlab.mpi-sws.org/iris/opam.git
make build-dep
to install the latest dependenciesmake -j
to build the Coq proofs.rustup
, using the instructions at https://rustup.rs
.creusot
directory, and execute cargo install --path creusot
rhb-specs
directory and execute make clean
followed by
make proofs
.If you wish to modify the benchmarks, we recommend repeating steps 4 and 5 to
refresh the output.
Additionally, you may browse the test suite of Creusot (found at
creusot/creusot/tests/should_succeed
) for further examples.
The benchmarks can be evaluated using why3
, and its ide.
opam
using your system package manager.opam
by running opam init
.rhb-specs
directory by running
opam switch create .
and eval $(opam env)
.why3
:
opam pin add why3 https://gitlab.inria.fr/why3/why3.git#c7b727068874557c3cbf30f837fcd7e049a85848
.why3
by running opam install ocamlgraph why3 why3-ide
.z3
and cvc4
as backends to why3
using your system package
manager or installer of choice.why3
by running why3 config detect
. It should provide an output
stating which provers have been detected and configured.proofs.mlcfg
created in the previous subsection with the following
command:why3 ide -Lpath/to/creusot/prelude proofs.mlcfg