Skip to content

Commit 61b69a8

Browse files
committed
Draft of initial RMC documentation (rust-lang#471)
* Draft of initial RMC documentation * revisions in response to feedback
1 parent d0f082e commit 61b69a8

File tree

7 files changed

+174
-11
lines changed

7 files changed

+174
-11
lines changed

rmc-docs/book.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,4 @@ multilingual = false
1111
[output.html]
1212
site-url = "/rmc/"
1313
git-repository-url = "https://github.com/model-checking/rmc"
14-
# If we get a stable default branch, we can use this feature, but HEAD doesn't work
15-
#edit-url-template = "https://github.com/model-checking/rmc/edit/HEAD/rmc-docs/{path}"
14+
edit-url-template = "https://github.com/model-checking/rmc/edit/main/rmc-docs/{path}"

rmc-docs/src/SUMMARY.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# The Rust Model Checker
22

33
- [Getting started with RMC](./getting-started.md)
4-
- [Installation]()
5-
- [Comparison with other tools]()
4+
- [Installation](./install-guide.md)
5+
- [Comparison with other tools](./tool-comparison.md)
66
- [RMC on a single file]()
77
- [RMC on a crate]()
88
- [Debugging failures]()
99

10-
- [RMC tutorial]()
10+
- [RMC tutorial](./rmc-tutorial.md)
1111

1212
- [RMC developer documentation]()

rmc-docs/src/getting-started.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
# Getting started with RMC
22

3-
Hello, World!
3+
RMC is a Rust verification tool based on _model checking_.
4+
With RMC, you can ensure that broad classes of problems are absent from your Rust code by writing _proof harnesses_, which are broadly similar to tests (especially property tests.)
5+
RMC is especially useful for verifying unsafe code in Rust, where many of the language's usual guarantees can no longer be checked by the compiler.
6+
But RMC is also useful for finding panics in safe Rust, and it can check user-defined assertions.
47

5-
```rust
6-
fn main() {
7-
assert!(1 == 1);
8-
}
9-
```
8+
## Project Status
9+
10+
RMC is currently in the initial development phase, and has not yet made an official release.
11+
It is under active development, but it does not yet support all Rust language features.
12+
If you encounter issues when using RMC we encourage you to [report them to us](https://github.com/model-checking/rmc/issues/new/choose).
13+
14+
## Getting started
15+
16+
1. [Begin with the RMC installation guide.](./install-guide.md) Currently, this means checking out and building RMC.
17+
2. [Understand how RMC compares to other potential tools for verifying Rust code.](./tool-comparison.md)
18+
3. [Try following the RMC tutorial to get a feel for how RMC can be applied.](./rmc-tutorial.md)

rmc-docs/src/install-guide.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# RMC Installation Guide
2+
3+
RMC must currently be built from source.
4+
5+
In general, the following dependencies are required:
6+
7+
1. The dependencies needed to built `rustc`. RMC is a fork of the Rust compiler, and so we have the same minimum requirements.
8+
2. [CBMC](https://github.com/diffblue/cbmc) (>= 5.30.1)
9+
3. [CBMC Viewer](https://github.com/awslabs/aws-viewer-for-cbmc) (>= 2.6)
10+
11+
## Installing on Ubuntu 20.04
12+
13+
The simplest way to install (especially if you're using a fresh VM) is following our CI scripts:
14+
15+
```
16+
# git clone [email protected]:model-checking/rmc.git
17+
git clone https://github.com/model-checking/rmc.git
18+
cd rmc
19+
git submodule update --init
20+
./scripts/setup/ubuntu-20.04/install_deps.sh
21+
./scripts/setup/ubuntu-20.04/install_cbmc.sh
22+
./scripts/setup/install_viewer.sh 2.6
23+
./scripts/setup/install_rustup.sh
24+
```
25+
26+
## Installing on Mac OS
27+
28+
You need to have [Homebrew](https://brew.sh/) installed already.
29+
30+
```
31+
# git clone [email protected]:model-checking/rmc.git
32+
git clone https://github.com/model-checking/rmc.git
33+
cd rmc
34+
git submodule update --init
35+
./scripts/setup/macos-10.15/install_deps.sh
36+
./scripts/setup/macos-10.15/install_cbmc.sh
37+
./scripts/setup/install_viewer.sh 2.6
38+
./scripts/setup/install_rustup.sh
39+
```
40+
41+
## Building and testing RMC
42+
43+
Perform one-time build configuration:
44+
45+
```
46+
./configure \
47+
--enable-debug \
48+
--set=llvm.download-ci-llvm=true \
49+
--set=rust.debug-assertions-std=false \
50+
--set=rust.deny-warnings=false
51+
```
52+
53+
**NOTE: If you skip the above (`llvm.download-ci-llvm=true` specifically), builds may take a long time as all of LLVM would need to be built from scratch.**
54+
55+
Then build RMC:
56+
57+
```
58+
./x.py build -i --stage 1 library/std
59+
```
60+
61+
Then, optionally, run the regression tests:
62+
63+
```
64+
./scripts/rmc-regression.sh
65+
```
66+
67+
This script has a lot of noisy output, but on a successful run you will see:
68+
69+
```
70+
All RMC regression tests completed successfully.
71+
```
72+
73+
## Try running RMC
74+
75+
Get the RMC script in your path:
76+
77+
```bash
78+
export PATH=$(pwd)/scripts:$PATH
79+
```
80+
81+
Create a test file:
82+
83+
```rust
84+
// File: test.rs
85+
fn main() {
86+
assert!(1 == 2);
87+
}
88+
```
89+
90+
Run RMC on the single file:
91+
92+
```
93+
rmc test.rs
94+
```
95+
96+
You should get a result like this one:
97+
98+
```
99+
[snipped output]
100+
** Results:
101+
test.rs function main
102+
[main.assertion.1] line 2 assertion failed: 1 == 2: FAILURE
103+
104+
** 1 of 1 failed (2 iterations)
105+
VERIFICATION FAILED
106+
```
107+
108+
Fix the test and you should see `rmc` succeed.

rmc-docs/src/rmc-tutorial.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# RMC tutorial
2+
3+
If you're interested in applying RMC, then you're probably in this situation:
4+
5+
1. You're working on a moderately important project in Rust.
6+
2. You've already invested heavily in testing to ensure correctness, and possibly fuzzing to ensure the absence of shallow security issues.
7+
3. You want to invest further, to gain a much higher degree of assurance.
8+
9+
> If you haven't already, we recommend techniques like property testing (e.g. with [`proptest`](https://github.com/AltSysrq/proptest)) before attempting model checking.
10+
> These yield good results, are very cheap to apply, and are often easier to adopt and debug.
11+
> Refactoring work to make your code more property-testable will generally also make the code more model-checkable as well.
12+
> RMC is a next step: a tool that can be applied once cheaper tactics are no longer yielding results, or once the easier to detect issues have already been dealt with.
13+
14+
This tutorial will step you through a progression from simple to moderately complex tasks with RMC.
15+
It's meant to ensure you can get started, and see at least some simple examples of how typical proofs are structured.
16+
It will also teach you the basics of "debugging" proof harnesses, which mainly consists of diagnosing and resolving non-termination issues with the solver.
17+
18+
1. [Begin with RMC installation.](./install-guide.md) This will take through to running `rmc` on your first Rust program.
19+
2. Consider reading our [tool comparison](./tool-comparison.md) to understand what RMC is.
20+
3. Coming soon: the tutorial.
21+
4. Consider returning to the [tool comparison](./tool-comparison.md) after trying the tutorial to see if any of the abstract ideas have become more concrete.

rmc-docs/src/tool-comparison.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Comparison with other tools
2+
3+
**Fuzzing** (for example, with [`cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz)) is a unguided approach to random testing.
4+
A fuzzer generally provides an input of random bytes, and then examines fairly generic properties ("doesn't crash or commit undefined behavior") about the behavior of the resulting program.
5+
Fuzzers generally get their power through a kind of evolutionary algorithm that rewards new mutant inputs that "discover" new branches of the program under test.
6+
Fuzzers are excellent for testing security boundaries, precisely because they make no validity assumptions (hence "unguided") when generating the input.
7+
8+
**Property testing** (for example, with [`proptest`](https://github.com/AltSysrq/proptest)) is a guided approach to random testing.
9+
"Guided" in the sense that the test generally provides a strategy (for generating random values) that constrains their range.
10+
The purpose of this is to either focus on interesting values, or because the assertions in the test will only hold for a constrained set of inputs.
11+
This generator is sampled several times, and the test's assertions are checked for each sample.
12+
Tests in this style do actually state properties: "forall inputs (of some constrained kind), this condition should hold."
13+
Property testing is often quite effective, but the engine can't fully prove the property, it can only sample randomly a few of those values to test (though property testing libraries frequently give interesting "edge cases" higher probability, making them more effective at bug-finding).
14+
15+
**Model checking** is similar to these techniques in how you use them, but model checking is non-random and exhaustive (though often only up to some bound on input or problem size).
16+
Thus, properties checked with a model checker are effectively proofs.
17+
Instead of naively trying all possible _concrete_ inputs (which could be infeasible and blow up exponentially), model checkers like RMC will cleverly encode program traces as _symbolic_ "[SAT](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem)/[SMT](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories)" problems, and hand them off to SAT/SMT solvers.
18+
Again, SAT/SMT solving is an [NP-complete](https://en.wikipedia.org/wiki/NP-completeness) problem, but most practical programs can be model checked within milliseconds to seconds (with notable exceptions: you can easily try to reverse a cryptographic hash with a model checker, but good luck getting it to terminate!)
19+
20+
Model checking allows you to prove non-trivial properties about programs, and check those proofs in roughly the same amount of time as a traditional test suite would take to run.
21+
The downside is many types of properties can quickly become "too large" to practically model check, and so writing "proof harnesses" (very similar to property tests and fuzzer harnesses) requires some skill to understand why the solver is not terminating and fix the structure of the problem you're giving it so that it does.
22+
This process basically boils down to "debugging" the proof.

scripts/rmc-regression.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ $SCRIPT_DIR/codegen-firecracker.sh
4040
# \ / v0.1.1
4141
# dependency2
4242
./src/test/rmc-dependency-test/diamond-dependency/run-dependency-test.sh
43+
44+
echo
45+
echo "All RMC regression tests completed successfully."
46+
echo

0 commit comments

Comments
 (0)