diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e38339a462..fb18350bc8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,7 @@ The top-level repository directories are: * `saw` - Source for the `saw` executable interpreter for SAWScript. -* `doc` - A tutorial and manual for SAWScript. +* `doc` - A manual and tutorials for SAWScript. * `examples` - Various examples of using SAWScript. diff --git a/README.md b/README.md index fb1c06b9e6..e0781394ae 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,17 @@ incomplete support for the Rust language. ## Documentation -The [SAWScript tutorial](https://saw.galois.com/tutorial.html) gives an -introduction to using the SAWScript interpreter. A longer +There are two SAWScript tutorials that give an introduction to using the +SAWScript interpreter: + +* [This tutorial](https://saw.galois.com/tutorial.html) gives an + introduction to verifying C code (using LLVM) and Java code (using JVM). +* [This tutorial](https://github.com/GaloisInc/saw-script/blob/master/doc/rust-tutorial/rust-tutorial.md) + gives an introduction to verifying Rust code (using MIR). + +There is also a longer [manual](https://github.com/GaloisInc/saw-script/blob/master/doc/manual/manual.md) -describes the breadth of SAWScript's features. +that describes the breadth of SAWScript's features. ## Precompiled Binaries diff --git a/doc/rust-tutorial/Makefile b/doc/rust-tutorial/Makefile new file mode 100644 index 0000000000..32ec78184d --- /dev/null +++ b/doc/rust-tutorial/Makefile @@ -0,0 +1,66 @@ +TARGET = tmp/sawScriptRustTutorial +SRCS = ${TARGET}.md ${wildcard *.bib} ${wildcard *.cls} ${wildcard *.sty} +CODE = ${wildcard code/*.c} \ + ${wildcard code/*.cry} \ + ${wildcard code/*.java} \ + ${wildcard code/*.saw} +TARBALL = tmp/saw-rust-tutorial-code.tar.gz +SPELLSRC = ${TARGET}.tex +NEWSPELL = ${TARGET}.SPELLNEW +OLDSPELL = ${TARGET}.SPELLOLD +SPELL = aspell -t -l +AUX = ${wildcard *.blg} ${wildcard *.bbl} ${wildcard *.aux} \ + ${wildcard *.eps} ${wildcard *.log} ${wildcard *.toc} \ + ${TARGET}.md +PDFARGS = -H rust-tutorial-head.tex \ + -B rust-tutorial-before.tex \ + -A rust-tutorial-after.tex \ + --toc \ + --listings \ + -V documentclass:galois-whitepaper \ + -V fontsize:12 \ + --pdf-engine=xelatex +HTMLARGS = --css doc.css \ + -B rust-tutorial-before.html \ + --toc \ + --standalone \ + --metadata title="SAWScript Rust Tutorial" \ + --self-contained + +all: ${TARGET}.pdf ${TARGET}.html ${TARBALL} + +${TARGET}.pdf: ${SRCS} Makefile | tmp + pandoc ${PDFARGS} -o $@ ${TARGET}.md + +${TARGET}.html: ${SRCS} Makefile | tmp + pandoc ${HTMLARGS} -o $@ ${TARGET}.md + +${TARBALL}: ${CODE} + tar czf ${TARBALL} code + +# Pre-processing step. Right now, does nothing. +${TARGET}.md: rust-tutorial.md docode.hs ${CODE} | tmp + runhaskell docode.hs < $< > $@ + +docode: ${TARGET}.md | tmp + +.PHONY: spellClean superClean clean quickSpell + +tmp: + mkdir -p tmp + +clean: + -rm -f ${AUX} + +superClean: clean + -rm -f ${TARGET}.pdf ${TARGET}.html ${TARGET}.md tmp + +spellClean: + rm -f ${NEWSPELL} ${OLDSPELL} + +quickSpell: + @touch ${NEWSPELL} + @mv -f ${NEWSPELL} ${OLDSPELL} + @cat ${SPELLSRC} | ${SPELL} | tr "A-Z" "a-z" | sort | uniq | less > ${NEWSPELL} + @echo '(The ones marked with < are new.)' + @diff ${NEWSPELL} ${OLDSPELL} diff --git a/doc/rust-tutorial/README.md b/doc/rust-tutorial/README.md new file mode 100644 index 0000000000..c3c5147261 --- /dev/null +++ b/doc/rust-tutorial/README.md @@ -0,0 +1,8 @@ +To update the tutorial, edit `rust-tutorial.md` and then run `make`. The output +is generated in `./tmp`. If you want to version a new copy of the tutorial, +copy `./tmp/sawScriptRustTutorial.pdf` to `./sawScriptRustTutorial.pdf` and +commit. + +Note that some uses of the `^` character in this tutorial cause problems with +especially old versions of `pandoc`. I have confirmed that the tutorial builds +successfully with `pandoc 2.17.1.1` or later. diff --git a/doc/rust-tutorial/code/.gitignore b/doc/rust-tutorial/code/.gitignore new file mode 100644 index 0000000000..eaaa55339f --- /dev/null +++ b/doc/rust-tutorial/code/.gitignore @@ -0,0 +1,10 @@ +tmp + +*.exe +*.mir +*.rlib + +first-example +generics-take-1 +generics-take-2 +saw-basics diff --git a/doc/rust-tutorial/code/Makefile b/doc/rust-tutorial/code/Makefile new file mode 100644 index 0000000000..7e9c7b2569 --- /dev/null +++ b/doc/rust-tutorial/code/Makefile @@ -0,0 +1,17 @@ +RS_FILES := $(wildcard *.rs) +JSON_FILES := $(RS_FILES:.rs=.linked-mir.json) +EXE_FILES := $(RS_FILES:.rs=) + +all: $(JSON_FILES) + +%.linked-mir.json: %.rs + saw-rustc $< + $(MAKE) remove-unused-build-artifacts + +.PHONY: remove-unused-build-artifacts +remove-unused-build-artifacts: + rm -f test lib*.mir lib*.rlib $(EXE_FILES) + +.PHONY: clean +clean: remove-unused-build-artifacts + rm -f *.linked-mir.json diff --git a/doc/rust-tutorial/code/arrays-fail.saw b/doc/rust-tutorial/code/arrays-fail.saw new file mode 100644 index 0000000000..3d0d32e185 --- /dev/null +++ b/doc/rust-tutorial/code/arrays-fail.saw @@ -0,0 +1,14 @@ +enable_experimental; + +let index_fail_spec = do { + arr <- mir_fresh_var "arr" (mir_array 3 mir_u32); + idx <- mir_fresh_var "idx" mir_usize; + + mir_execute_func [mir_term arr, mir_term idx]; + + mir_return (mir_term {{ arr @ idx }}); +}; + +m <- mir_load_module "arrays.linked-mir.json"; + +mir_verify m "arrays::index" [] false index_fail_spec z3; diff --git a/doc/rust-tutorial/code/arrays.linked-mir.json b/doc/rust-tutorial/code/arrays.linked-mir.json new file mode 100644 index 0000000000..558f4d49dc --- /dev/null +++ b/doc/rust-tutorial/code/arrays.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::d8c12f833d14aeb7"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::usize"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}},"pos":"arrays.rs:6:10: 6:13","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::usize"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"pos":"arrays.rs:6:6: 6:14","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"usize","size":8,"val":"3"},"ty":"ty::usize"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}},"pos":"arrays.rs:6:6: 6:14","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}},"kind":"Copy"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"kind":"Copy"},"kind":"BinaryOp","op":{"kind":"Lt"}}}],"terminator":{"cleanup":null,"cond":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}},"kind":"Move"},"expected":true,"kind":"Assert","msg":"index out of bounds: the length is move _4 but the index is _3","pos":"arrays.rs:6:6: 6:14","target":"bb1"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Ref::e028c0f25e8b6323"}},"pos":"arrays.rs:6:5: 6:14","rhs":{"kind":"CopyForDeref","place":{"data":[{"kind":"Index","op":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::d8c12f833d14aeb7"}}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"arrays.rs:6:5: 6:14","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Ref::e028c0f25e8b6323"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"arrays.rs:7:2: 7:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Ref::e028c0f25e8b6323"}]},"name":"arrays/f3339ccb::index_ref_arr","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::30b61a0858282572"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::usize"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}},"pos":"arrays.rs:2:9: 2:12","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::usize"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"pos":"arrays.rs:2:5: 2:13","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"usize","size":8,"val":"3"},"ty":"ty::usize"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}},"pos":"arrays.rs:2:5: 2:13","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}},"kind":"Copy"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"kind":"Copy"},"kind":"BinaryOp","op":{"kind":"Lt"}}}],"terminator":{"cleanup":null,"cond":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}},"kind":"Move"},"expected":true,"kind":"Assert","msg":"index out of bounds: the length is move _4 but the index is _3","pos":"arrays.rs:2:5: 2:13","target":"bb1"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"arrays.rs:2:5: 2:13","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Index","op":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::30b61a0858282572"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"arrays.rs:3:2: 3:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}]},"name":"arrays/f3339ccb::index","return_ty":"ty::u32","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"arrays/f3339ccb::index_ref_arr","kind":"Item","substs":[]},"name":"arrays/f3339ccb::index_ref_arr"},{"inst":{"def_id":"arrays/f3339ccb::index","kind":"Item","substs":[]},"name":"arrays/f3339ccb::index"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::Ref::e028c0f25e8b6323","ty":{"kind":"Ref","mutability":{"kind":"Not"},"ty":"ty::u32"}},{"name":"ty::usize","ty":{"kind":"Uint","uintkind":{"kind":"Usize"}}},{"name":"ty::Array::d8c12f833d14aeb7","ty":{"kind":"Array","size":{"rendered":{"kind":"usize","size":8,"val":"3"},"ty":"ty::usize"},"ty":"ty::Ref::e028c0f25e8b6323"}},{"name":"ty::bool","ty":{"kind":"Bool"}},{"name":"ty::Array::30b61a0858282572","ty":{"kind":"Array","size":{"rendered":{"kind":"usize","size":8,"val":"3"},"ty":"ty::usize"},"ty":"ty::u32"}}],"roots":["arrays/f3339ccb::index","arrays/f3339ccb::index_ref_arr"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/arrays.rs b/doc/rust-tutorial/code/arrays.rs new file mode 100644 index 0000000000..360289561f --- /dev/null +++ b/doc/rust-tutorial/code/arrays.rs @@ -0,0 +1,7 @@ +pub fn index(arr: [u32; 3], idx: usize) -> u32 { + arr[idx] +} + +pub fn index_ref_arr(arr: [&u32; 3], idx: usize) -> u32 { + *arr[idx] +} diff --git a/doc/rust-tutorial/code/arrays.saw b/doc/rust-tutorial/code/arrays.saw new file mode 100644 index 0000000000..8e3b5c449a --- /dev/null +++ b/doc/rust-tutorial/code/arrays.saw @@ -0,0 +1,33 @@ +enable_experimental; + +let index_spec = do { + arr <- mir_fresh_var "arr" (mir_array 3 mir_u32); + idx <- mir_fresh_var "idx" mir_usize; + mir_precond {{ 0 <= idx }}; // Lower bound of idx + mir_precond {{ idx <= 2 }}; // Upper bound of idx + + mir_execute_func [mir_term arr, mir_term idx]; + + mir_return (mir_term {{ arr @ idx }}); +}; + +m <- mir_load_module "arrays.linked-mir.json"; + +mir_verify m "arrays::index" [] false index_spec z3; + +let index_alt_spec = do { + arr0 <- mir_fresh_var "arr0" mir_u32; + arr1 <- mir_fresh_var "arr1" mir_u32; + arr2 <- mir_fresh_var "arr2" mir_u32; + let arr = mir_array_value mir_u32 [mir_term arr0, mir_term arr1, mir_term arr2]; + + idx <- mir_fresh_var "idx" mir_usize; + mir_precond {{ 0 <= idx }}; // Lower bound of idx + mir_precond {{ idx <= 2 }}; // Upper bound of idx + + mir_execute_func [arr, mir_term idx]; + + mir_return (mir_term {{ [arr0, arr1, arr2] @ idx }}); +}; + +mir_verify m "arrays::index" [] false index_alt_spec z3; diff --git a/doc/rust-tutorial/code/enums.linked-mir.json b/doc/rust-tutorial/code/enums.linked-mir.json new file mode 100644 index 0000000000..d6b54669f8 --- /dev/null +++ b/doc/rust-tutorial/code/enums.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Deinit","pos":"enums.rs:6:5: 6:9"},{"kind":"SetDiscriminant","lvalue":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::3fa7c2d95c7fce06"}},"pos":"enums.rs:6:5: 6:9","variant_index":0}],"terminator":{"kind":"Return","pos":"enums.rs:7:2: 7:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::3fa7c2d95c7fce06"}]},"name":"enums/caeb2906::i_got_nothing","return_ty":"ty::Adt::3fa7c2d95c7fce06","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::3fa7c2d95c7fce06"}],"body":{"blocks":[{"block":{"data":[],"terminator":{"kind":"Return","pos":"enums.rs:11:2: 11:2"}},"blockid":"bb0"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"}]},"name":"enums/caeb2906::do_stuff_with_option","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"pos":"enums.rs:2:10: 2:11","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Deinit","pos":"enums.rs:2:5: 2:12"},{"kind":"Assign","lhs":{"data":[{"kind":"Downcast","variant":1},{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::3fa7c2d95c7fce06"}},"pos":"enums.rs:2:5: 2:12","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"kind":"Move"}}},{"kind":"SetDiscriminant","lvalue":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::3fa7c2d95c7fce06"}},"pos":"enums.rs:2:5: 2:12","variant_index":1}],"terminator":{"kind":"Return","pos":"enums.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::3fa7c2d95c7fce06"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}]},"name":"enums/caeb2906::i_found_something","return_ty":"ty::Adt::3fa7c2d95c7fce06","spread_arg":null}],"adts":[{"kind":{"discr_ty":"ty::isize","kind":"Enum"},"name":"core/73237d41::option::Option::_adtc5e93708b8ca6e2a[0]","orig_def_id":"core/73237d41::option::Option","orig_substs":["ty::u32"],"repr_transparent":false,"size":8,"variants":[{"ctor_kind":{"kind":"Const"},"discr":{"index":0,"kind":"Relative"},"discr_value":"0","fields":[],"inhabited":true,"name":"core/73237d41::option::Option::None"},{"ctor_kind":{"kind":"Fn"},"discr":{"index":1,"kind":"Relative"},"discr_value":"1","fields":[{"name":"core/73237d41::option::Option::Some::0","ty":"ty::u32"}],"inhabited":true,"name":"core/73237d41::option::Option::Some"}]}],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"enums/caeb2906::i_got_nothing","kind":"Item","substs":[]},"name":"enums/caeb2906::i_got_nothing"},{"inst":{"def_id":"enums/caeb2906::do_stuff_with_option","kind":"Item","substs":[]},"name":"enums/caeb2906::do_stuff_with_option"},{"inst":{"def_id":"enums/caeb2906::i_found_something","kind":"Item","substs":[]},"name":"enums/caeb2906::i_found_something"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::Adt::3fa7c2d95c7fce06","ty":{"kind":"Adt","name":"core/73237d41::option::Option::_adtc5e93708b8ca6e2a[0]","orig_def_id":"core/73237d41::option::Option","substs":["ty::u32"]}},{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}},{"name":"ty::isize","ty":{"intkind":{"kind":"Isize"},"kind":"Int"}}],"roots":["enums/caeb2906::i_found_something","enums/caeb2906::i_got_nothing","enums/caeb2906::do_stuff_with_option"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/enums.rs b/doc/rust-tutorial/code/enums.rs new file mode 100644 index 0000000000..49beea990a --- /dev/null +++ b/doc/rust-tutorial/code/enums.rs @@ -0,0 +1,11 @@ +pub fn i_found_something(x: u32) -> Option { + Some(x) +} + +pub fn i_got_nothing() -> Option { + None +} + +pub fn do_stuff_with_option(o: Option) { + // ... +} diff --git a/doc/rust-tutorial/code/enums.saw b/doc/rust-tutorial/code/enums.saw new file mode 100644 index 0000000000..c45c4b67f5 --- /dev/null +++ b/doc/rust-tutorial/code/enums.saw @@ -0,0 +1,35 @@ +enable_experimental; + +m <- mir_load_module "enums.linked-mir.json"; + +option_u32 <- mir_find_adt m "core::option::Option" [mir_u32]; + +let i_found_something_spec = do { + x <- mir_fresh_var "x" mir_u32; + + mir_execute_func [mir_term x]; + + let ret = mir_enum_value option_u32 "Some" [mir_term x]; + mir_return ret; +}; + +mir_verify m "enums::i_found_something" [] false i_found_something_spec z3; + +let i_got_nothing_spec = do { + mir_execute_func []; + + let ret = mir_enum_value option_u32 "None" []; + mir_return ret; +}; + +mir_verify m "enums::i_got_nothing" [] false i_got_nothing_spec z3; + +let do_stuff_with_option_spec = do { + o <- mir_fresh_expanded_value "o" (mir_adt option_u32); + + mir_execute_func [o]; + + // ... +}; + +mir_verify m "enums::do_stuff_with_option" [] false do_stuff_with_option_spec z3; diff --git a/doc/rust-tutorial/code/first-example.linked-mir.json b/doc/rust-tutorial/code/first-example.linked-mir.json new file mode 100644 index 0000000000..c843812c0c --- /dev/null +++ b/doc/rust-tutorial/code/first-example.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}},"pos":"first-example.rs:2:5: 2:6","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"first-example.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}]},"name":"first_example/abef32c5::id_u8","return_ty":"ty::u8","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"first_example/abef32c5::id_u8","kind":"Item","substs":[]},"name":"first_example/abef32c5::id_u8"}],"tys":[{"name":"ty::u8","ty":{"kind":"Uint","uintkind":{"kind":"U8"}}}],"roots":["first_example/abef32c5::id_u8"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/first-example.rs b/doc/rust-tutorial/code/first-example.rs new file mode 100644 index 0000000000..4f28dec065 --- /dev/null +++ b/doc/rust-tutorial/code/first-example.rs @@ -0,0 +1,3 @@ +pub fn id_u8(x: u8) -> u8 { + x +} diff --git a/doc/rust-tutorial/code/generics-take-1.linked-mir.json b/doc/rust-tutorial/code/generics-take-1.linked-mir.json new file mode 100644 index 0000000000..0d38b2aef4 --- /dev/null +++ b/doc/rust-tutorial/code/generics-take-1.linked-mir.json @@ -0,0 +1 @@ +{"fns":[],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[],"tys":[],"roots":[]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/generics-take-1.rs b/doc/rust-tutorial/code/generics-take-1.rs new file mode 100644 index 0000000000..fd0906f024 --- /dev/null +++ b/doc/rust-tutorial/code/generics-take-1.rs @@ -0,0 +1,3 @@ +pub fn id(x: A) -> A { + x +} diff --git a/doc/rust-tutorial/code/generics-take-2.linked-mir.json b/doc/rust-tutorial/code/generics-take-2.linked-mir.json new file mode 100644 index 0000000000..e4804c4a99 --- /dev/null +++ b/doc/rust-tutorial/code/generics-take-2.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u8"}},"pos":"generics-take-2.rs:6:8: 6:9","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u8"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::e7e83e5417e656c7"},"kind":"Constant"},"kind":"Call","pos":"generics-take-2.rs:6:5: 6:10"}},"blockid":"bb0"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"generics-take-2.rs:7:2: 7:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u8"}]},"name":"generics_take_2/8b1bf337::id_u8","return_ty":"ty::u8","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}},"pos":"generics-take-2.rs:2:5: 2:6","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}},"kind":"Move"}}}],"terminator":{"kind":"Return","pos":"generics-take-2.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}]},"name":"generics_take_2/8b1bf337::id::_instaddce72e1232152c[0]","return_ty":"ty::u8","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"generics_take_2/8b1bf337::id_u8","kind":"Item","substs":[]},"name":"generics_take_2/8b1bf337::id_u8"},{"inst":{"def_id":"generics_take_2/8b1bf337::id","kind":"Item","substs":["ty::u8"]},"name":"generics_take_2/8b1bf337::id::_instaddce72e1232152c[0]"}],"tys":[{"name":"ty::u8","ty":{"kind":"Uint","uintkind":{"kind":"U8"}}},{"name":"ty::FnDef::e7e83e5417e656c7","ty":{"defid":"generics_take_2/8b1bf337::id::_instaddce72e1232152c[0]","kind":"FnDef"}}],"roots":["generics_take_2/8b1bf337::id_u8"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/generics-take-2.rs b/doc/rust-tutorial/code/generics-take-2.rs new file mode 100644 index 0000000000..31df101083 --- /dev/null +++ b/doc/rust-tutorial/code/generics-take-2.rs @@ -0,0 +1,7 @@ +pub fn id(x: A) -> A { + x +} + +pub fn id_u8(x: u8) -> u8 { + id(x) +} diff --git a/doc/rust-tutorial/code/overrides-fail.saw b/doc/rust-tutorial/code/overrides-fail.saw new file mode 100644 index 0000000000..03f4464aa4 --- /dev/null +++ b/doc/rust-tutorial/code/overrides-fail.saw @@ -0,0 +1,33 @@ +enable_experimental; + +m <- mir_load_module "overrides.linked-mir.json"; + +let g_even_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ x % 2 == 0 }}; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 1 }}); +}; + +let g_odd_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ x % 2 == 1 }}; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 1 }}); +}; + +let f_spec = do { + x <- mir_fresh_var "x" mir_u32; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 3 }}); +}; + +g_even_ov <- mir_verify m "overrides::g" [] false g_even_spec z3; +// g_odd_ov <- mir_verify m "overrides::g" [] false g_odd_spec z3; +mir_verify m "overrides::f" [g_even_ov] false f_spec z3; diff --git a/doc/rust-tutorial/code/overrides-mut-fail.saw b/doc/rust-tutorial/code/overrides-mut-fail.saw new file mode 100644 index 0000000000..c6dbbeab4d --- /dev/null +++ b/doc/rust-tutorial/code/overrides-mut-fail.saw @@ -0,0 +1,19 @@ +enable_experimental; + +m <- mir_load_module "overrides-mut.linked-mir.json"; + +let side_effect_spec = do { + a_ref <- mir_alloc_mut mir_u32; + a_val <- mir_fresh_var "a_val" mir_u32; + mir_points_to a_ref (mir_term a_val); + mir_execute_func [a_ref]; +}; + +let foo_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_execute_func [mir_term x]; + mir_return (mir_term {{ x }}); +}; + +side_effect_ov <- mir_verify m "overrides_mut::side_effect" [] false side_effect_spec z3; +mir_verify m "overrides_mut::foo" [side_effect_ov] false foo_spec z3; diff --git a/doc/rust-tutorial/code/overrides-mut.linked-mir.json b/doc/rust-tutorial/code/overrides-mut.linked-mir.json new file mode 100644 index 0000000000..eddb933b34 --- /dev/null +++ b/doc/rust-tutorial/code/overrides-mut.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"overrides-mut.rs:6:22: 6:23","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::953fce25114368d0"}},"pos":"overrides-mut.rs:7:17: 7:23","rhs":{"borrowkind":"Mut","kind":"Ref","refvar":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"region":"unimplement"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::953fce25114368d0"}},"pos":"overrides-mut.rs:7:17: 7:23","rhs":{"borrowkind":"Mut","kind":"Ref","refvar":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::953fce25114368d0"}},"region":"unimplement"}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::953fce25114368d0"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Tuple::e93222e871854c41"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::9f9f50dc48be7f4d"},"kind":"Constant"},"kind":"Call","pos":"overrides-mut.rs:7:5: 7:24"}},"blockid":"bb0"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"overrides-mut.rs:9:2: 9:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Tuple::e93222e871854c41"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::953fce25114368d0"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::953fce25114368d0"}]},"name":"overrides_mut/11e47708::foo","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::953fce25114368d0"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::953fce25114368d0"}},"pos":"overrides-mut.rs:2:5: 2:11","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"0"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"overrides-mut.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"}]},"name":"overrides_mut/11e47708::side_effect","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"overrides_mut/11e47708::foo","kind":"Item","substs":[]},"name":"overrides_mut/11e47708::foo"},{"inst":{"def_id":"overrides_mut/11e47708::side_effect","kind":"Item","substs":[]},"name":"overrides_mut/11e47708::side_effect"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}},{"name":"ty::Ref::953fce25114368d0","ty":{"kind":"Ref","mutability":{"kind":"Mut"},"ty":"ty::u32"}},{"name":"ty::FnDef::9f9f50dc48be7f4d","ty":{"defid":"overrides_mut/11e47708::side_effect","kind":"FnDef"}}],"roots":["overrides_mut/11e47708::side_effect","overrides_mut/11e47708::foo"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/overrides-mut.rs b/doc/rust-tutorial/code/overrides-mut.rs new file mode 100644 index 0000000000..bd8baa58fb --- /dev/null +++ b/doc/rust-tutorial/code/overrides-mut.rs @@ -0,0 +1,9 @@ +pub fn side_effect(a: &mut u32) { + *a = 0; +} + +pub fn foo(x: u32) -> u32 { + let mut b: u32 = x; + side_effect(&mut b); + b +} diff --git a/doc/rust-tutorial/code/overrides-mut.saw b/doc/rust-tutorial/code/overrides-mut.saw new file mode 100644 index 0000000000..e568a9dc2e --- /dev/null +++ b/doc/rust-tutorial/code/overrides-mut.saw @@ -0,0 +1,24 @@ +enable_experimental; + +m <- mir_load_module "overrides-mut.linked-mir.json"; + +let side_effect_spec = do { + a_ref <- mir_alloc_mut mir_u32; + a_val <- mir_fresh_var "a_val" mir_u32; + mir_points_to a_ref (mir_term a_val); + mir_execute_func [a_ref]; + + // This is new + mir_points_to a_ref (mir_term {{ 0 : [32] }}); +}; + +let foo_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_execute_func [mir_term x]; + + // This is new + mir_return (mir_term {{ 0 : [32] }}); +}; + +side_effect_ov <- mir_verify m "overrides_mut::side_effect" [] false side_effect_spec z3; +mir_verify m "overrides_mut::foo" [side_effect_ov] false foo_spec z3; diff --git a/doc/rust-tutorial/code/overrides-unsafe.saw b/doc/rust-tutorial/code/overrides-unsafe.saw new file mode 100644 index 0000000000..08886035bd --- /dev/null +++ b/doc/rust-tutorial/code/overrides-unsafe.saw @@ -0,0 +1,22 @@ +enable_experimental; + +m <- mir_load_module "overrides.linked-mir.json"; + +let g_spec = do { + x <- mir_fresh_var "x" mir_u32; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 1 }}); +}; + +let f_spec = do { + x <- mir_fresh_var "x" mir_u32; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 3 }}); +}; + +g_ov <- mir_unsafe_assume_spec m "overrides::g" g_spec; +mir_verify m "overrides::f" [g_ov] false f_spec z3; diff --git a/doc/rust-tutorial/code/overrides.linked-mir.json b/doc/rust-tutorial/code/overrides.linked-mir.json new file mode 100644 index 0000000000..a3b6ddba39 --- /dev/null +++ b/doc/rust-tutorial/code/overrides.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"pos":"overrides.rs:6:16: 6:17","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::2e21eec932e1b02a"},"kind":"Constant"},"kind":"Call","pos":"overrides.rs:6:14: 6:18"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::u32"}},"pos":"overrides.rs:7:16: 7:18","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::u32"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::u32"}},"bb2"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::2e21eec932e1b02a"},"kind":"Constant"},"kind":"Call","pos":"overrides.rs:7:14: 7:19"}},"blockid":"bb1"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}},"pos":"overrides.rs:8:7: 8:9","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::u32"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"bb3"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::2e21eec932e1b02a"},"kind":"Constant"},"kind":"Call","pos":"overrides.rs:8:5: 8:10"}},"blockid":"bb2"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"overrides.rs:9:2: 9:2"}},"blockid":"bb3"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}]},"name":"overrides/96c5af24::f","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"pos":"overrides.rs:2:5: 2:6","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"kind":"Move"},{"data":{"rendered":{"kind":"uint","size":4,"val":"1"},"ty":"ty::u32"},"kind":"Constant"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::f55acdef755f1aaa"},"kind":"Constant"},"kind":"Call","pos":"overrides.rs:2:5: 2:22"}},"blockid":"bb0"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"overrides.rs:3:2: 3:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}]},"name":"overrides/96c5af24::g","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:38: 1162:42 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:38: 1162:42 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:44: 1162:47 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:44: 1162:47 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:13: 1162:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"kind":"Move"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},"kind":"Move"},"kind":"BinaryOp","op":{"kind":"Add"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:47: 1162:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:47: 1162:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1163:10: 1163:10 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}]},"name":"core/73237d41::num::{impl#9}::wrapping_add","return_ty":"ty::u32","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"overrides/96c5af24::f","kind":"Item","substs":[]},"name":"overrides/96c5af24::f"},{"inst":{"def_id":"overrides/96c5af24::g","kind":"Item","substs":[]},"name":"overrides/96c5af24::g"},{"inst":{"def_id":"core/73237d41::num::{impl#9}::wrapping_add","kind":"Item","substs":[]},"name":"core/73237d41::num::{impl#9}::wrapping_add"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::FnDef::2e21eec932e1b02a","ty":{"defid":"overrides/96c5af24::g","kind":"FnDef"}},{"name":"ty::FnDef::f55acdef755f1aaa","ty":{"defid":"core/73237d41::num::{impl#9}::wrapping_add","kind":"FnDef"}}],"roots":["overrides/96c5af24::g","overrides/96c5af24::f"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/overrides.rs b/doc/rust-tutorial/code/overrides.rs new file mode 100644 index 0000000000..166f0adbd8 --- /dev/null +++ b/doc/rust-tutorial/code/overrides.rs @@ -0,0 +1,9 @@ +pub fn g(x: u32) -> u32 { + x.wrapping_add(1) +} + +pub fn f(x: u32) -> u32 { + let x1 = g(x); + let x2 = g(x1); + g(x2) +} diff --git a/doc/rust-tutorial/code/overrides.saw b/doc/rust-tutorial/code/overrides.saw new file mode 100644 index 0000000000..9a9b20673d --- /dev/null +++ b/doc/rust-tutorial/code/overrides.saw @@ -0,0 +1,45 @@ +enable_experimental; + +m <- mir_load_module "overrides.linked-mir.json"; + +let g_spec = do { + x <- mir_fresh_var "x" mir_u32; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 1 }}); +}; + +g_ov <- mir_verify m "overrides::g" [] false g_spec z3; + +let f_spec = do { + x <- mir_fresh_var "x" mir_u32; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 3 }}); +}; + +mir_verify m "overrides::f" [g_ov] false f_spec z3; + +let g_even_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ x % 2 == 0 }}; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 1 }}); +}; + +let g_odd_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ x % 2 == 1 }}; + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ x + 1 }}); +}; + +g_even_ov <- mir_verify m "overrides::g" [] false g_even_spec z3; +g_odd_ov <- mir_verify m "overrides::g" [] false g_odd_spec z3; +mir_verify m "overrides::f" [g_even_ov, g_odd_ov] false f_spec z3; diff --git a/doc/rust-tutorial/code/ref-basics-fail.saw b/doc/rust-tutorial/code/ref-basics-fail.saw new file mode 100644 index 0000000000..fa9f160659 --- /dev/null +++ b/doc/rust-tutorial/code/ref-basics-fail.saw @@ -0,0 +1,11 @@ +enable_experimental; + +let read_ref_fail_spec = do { + r <- mir_alloc mir_u32; + mir_execute_func [r]; + // mir_return ??; +}; + +m <- mir_load_module "ref-basics.linked-mir.json"; + +mir_verify m "ref_basics::read_ref" [] false read_ref_fail_spec z3; diff --git a/doc/rust-tutorial/code/ref-basics.linked-mir.json b/doc/rust-tutorial/code/ref-basics.linked-mir.json new file mode 100644 index 0000000000..fb9f879b17 --- /dev/null +++ b/doc/rust-tutorial/code/ref-basics.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::953fce25114368d0"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::953fce25114368d0"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::u32"}},"pos":"ref-basics.rs:6:22: 6:24","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::953fce25114368d0"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::u32"}},"pos":"ref-basics.rs:7:22: 7:24","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::953fce25114368d0"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::u32"}},"pos":"ref-basics.rs:9:10: 9:15","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::953fce25114368d0"}},"pos":"ref-basics.rs:9:5: 9:15","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::u32"}},"kind":"Move"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}},"pos":"ref-basics.rs:10:10: 10:15","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::953fce25114368d0"}},"pos":"ref-basics.rs:10:5: 10:15","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}},"kind":"Move"}}}],"terminator":{"kind":"Return","pos":"ref-basics.rs:11:2: 11:2"}},"blockid":"bb0"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}]},"name":"ref_basics/64014e3b::swap","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::e028c0f25e8b6323"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"ref-basics.rs:2:5: 2:7","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::e028c0f25e8b6323"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"ref-basics.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}]},"name":"ref_basics/64014e3b::read_ref","return_ty":"ty::u32","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"ref_basics/64014e3b::swap","kind":"Item","substs":[]},"name":"ref_basics/64014e3b::swap"},{"inst":{"def_id":"ref_basics/64014e3b::read_ref","kind":"Item","substs":[]},"name":"ref_basics/64014e3b::read_ref"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::Ref::953fce25114368d0","ty":{"kind":"Ref","mutability":{"kind":"Mut"},"ty":"ty::u32"}},{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}},{"name":"ty::Ref::e028c0f25e8b6323","ty":{"kind":"Ref","mutability":{"kind":"Not"},"ty":"ty::u32"}}],"roots":["ref_basics/64014e3b::read_ref","ref_basics/64014e3b::swap"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/ref-basics.rs b/doc/rust-tutorial/code/ref-basics.rs new file mode 100644 index 0000000000..9eb23bbe4d --- /dev/null +++ b/doc/rust-tutorial/code/ref-basics.rs @@ -0,0 +1,11 @@ +pub fn read_ref(r: &u32) -> u32 { + *r +} + +pub fn swap(a: &mut u32, b: &mut u32) { + let a_tmp: u32 = *a; + let b_tmp: u32 = *b; + + *a = b_tmp; + *b = a_tmp; +} diff --git a/doc/rust-tutorial/code/ref-basics.saw b/doc/rust-tutorial/code/ref-basics.saw new file mode 100644 index 0000000000..88d56c1ba0 --- /dev/null +++ b/doc/rust-tutorial/code/ref-basics.saw @@ -0,0 +1,30 @@ +enable_experimental; + +let read_ref_spec = do { + r_ref <- mir_alloc mir_u32; + r_val <- mir_fresh_var "r_val" mir_u32; + mir_points_to r_ref (mir_term r_val); + mir_execute_func [r_ref]; + mir_return (mir_term r_val); +}; + +m <- mir_load_module "ref-basics.linked-mir.json"; + +mir_verify m "ref_basics::read_ref" [] false read_ref_spec z3; + +let swap_spec = do { + a_ref <- mir_alloc_mut mir_u32; + a_val <- mir_fresh_var "a_val" mir_u32; + mir_points_to a_ref (mir_term a_val); + + b_ref <- mir_alloc_mut mir_u32; + b_val <- mir_fresh_var "b_val" mir_u32; + mir_points_to b_ref (mir_term b_val); + + mir_execute_func [a_ref, b_ref]; + + mir_points_to a_ref (mir_term b_val); + mir_points_to b_ref (mir_term a_val); +}; + +mir_verify m "ref_basics::swap" [] false swap_spec z3; diff --git a/doc/rust-tutorial/code/salsa20/.gitignore b/doc/rust-tutorial/code/salsa20/.gitignore new file mode 100644 index 0000000000..99bab5766f --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/.gitignore @@ -0,0 +1,3 @@ +target/ +benches/Cargo.lock +salsa20.linked-mir.json diff --git a/doc/rust-tutorial/code/salsa20/CHANGELOG.md b/doc/rust-tutorial/code/salsa20/CHANGELOG.md new file mode 100644 index 0000000000..b6dc591165 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/CHANGELOG.md @@ -0,0 +1,111 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.7.2 (2020-11-11) +### Fixed +- `no_std` builds with `zeroize` feature enabled ([#189]) + +[#189]: https://github.com/RustCrypto/stream-ciphers/pull/189 + +## 0.7.1 (2020-10-18) +### Added +- `expose-core` feature ([#180]) + +[#180]: https://github.com/RustCrypto/stream-ciphers/pull/180 + +## 0.7.0 (2020-10-16) +### Changed +- Replace `block-cipher`/`stream-cipher` with `cipher` crate ([#177]) +- Renamed `Cipher` to `Salsa` ([#177]) + +[#177]: https://github.com/RustCrypto/stream-ciphers/pull/177 + +## 0.6.0 (2020-08-25) +### Changed +- Bump `stream-cipher` dependency to v0.7 ([#161], [#164]) + +[#161]: https://github.com/RustCrypto/stream-ciphers/pull/161 +[#164]: https://github.com/RustCrypto/stream-ciphers/pull/164 + +## 0.5.2 (2020-06-11) +### Changed +- Use `Key` and `Nonce` in usage docs ([#155]) + +### Fixed +- `stream-cipher` version requirement ([#152]) + +[#155]: https://github.com/RustCrypto/stream-ciphers/pull/155 +[#152]: https://github.com/RustCrypto/stream-ciphers/pull/152 + +## 0.5.1 (2020-06-11) +### Added +- Documentation improvements ([#149]) +- `Key`, `Nonce`, and `XNonce` type aliases ([#146]) + +### Changed +- Bump `stream-cipher` to v0.4.1 ([#148]) + +[#149]: https://github.com/RustCrypto/stream-ciphers/pull/149 +[#148]: https://github.com/RustCrypto/stream-ciphers/pull/148 +[#146]: https://github.com/RustCrypto/stream-ciphers/pull/146 + +## 0.5.0 (2020-06-06) +### Added +- `Salsa8` and `Salsa12` variants ([#133]) + +### Changed +- Upgrade to the `stream-cipher` v0.4 crate ([#125], [#138]) + +[#138]: https://github.com/RustCrypto/stream-ciphers/pull/138 +[#133]: https://github.com/RustCrypto/stream-ciphers/pull/133 +[#125]: https://github.com/RustCrypto/stream-ciphers/pull/125 + +## 0.4.1 (2020-02-25) +### Added +- `hsalsa20` feature ([#103]) + +[#103]: https://github.com/RustCrypto/stream-ciphers/pull/103 + +## 0.4.0 (2020-01-17) +### Changed +- Replace `salsa20-core` with `ctr`-derived buffering; MSRV 1.34+ ([#94]) + +[#94]: https://github.com/RustCrypto/stream-ciphers/pull/94 + +## 0.3.0 (2019-10-01) +### Added +- XSalsa20 ([#54]) + +[#54]: https://github.com/RustCrypto/stream-ciphers/pull/44 + +## 0.2.0 (2019-08-18) +### Added +- Improve documentation ([#17]) +- Impl `SyncStreamCipher` ([#39]) + +### Changed +- Refactoring ([#38], [#44]) + +### Fixed +- Fix broken Cargo feature attributes ([#21]) + +[#44]: https://github.com/RustCrypto/stream-ciphers/pull/44 +[#39]: https://github.com/RustCrypto/stream-ciphers/pull/39 +[#38]: https://github.com/RustCrypto/stream-ciphers/pull/38 +[#21]: https://github.com/RustCrypto/stream-ciphers/pull/21 +[#17]: https://github.com/RustCrypto/stream-ciphers/pull/17 + +## 0.1.1 (2019-06-30) + +### Added +- `#![no_std]` support + +[#19]: https://github.com/RustCrypto/stream-ciphers/pull/19 + +## 0.1.0 (2019-06-24) + +- Initial release diff --git a/doc/rust-tutorial/code/salsa20/Cargo.lock b/doc/rust-tutorial/code/salsa20/Cargo.lock new file mode 100644 index 0000000000..1f8747c4e3 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/Cargo.lock @@ -0,0 +1,55 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "blobby" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "847495c209977a90e8aad588b959d0ca9f5dc228096d29a6bd3defd53f35eaec" + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "blobby", + "generic-array", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "salsa20" +version = "0.8.0-pre" +dependencies = [ + "cipher", + "zeroize", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/doc/rust-tutorial/code/salsa20/Cargo.toml b/doc/rust-tutorial/code/salsa20/Cargo.toml new file mode 100644 index 0000000000..2fa4c2e669 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "salsa20" +version = "0.8.0-pre" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +description = "Salsa20 Stream Cipher" +repository = "https://github.com/RustCrypto/stream-ciphers" +keywords = ["crypto", "stream-cipher", "trait", "xsalsa20"] +categories = ["cryptography", "no-std"] +readme = "README.md" +edition = "2018" + +[dependencies] +cipher = "=0.3.0" +zeroize = { version = "1", optional = true, default-features = false } + +[dev-dependencies] +cipher = { version = "=0.3.0", features = ["dev"] } + +[features] +default = ["xsalsa20"] +expose-core = [] +hsalsa20 = ["xsalsa20"] +xsalsa20 = [] + +[package.metadata.docs.rs] +features = ["hsalsa20", "xsalsa20"] +rustdoc-args = ["--cfg", "docsrs"] diff --git a/doc/rust-tutorial/code/salsa20/LICENSE-APACHE b/doc/rust-tutorial/code/salsa20/LICENSE-APACHE new file mode 100644 index 0000000000..78173fa2e7 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/doc/rust-tutorial/code/salsa20/LICENSE-MIT b/doc/rust-tutorial/code/salsa20/LICENSE-MIT new file mode 100644 index 0000000000..af9093e4eb --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2019 Eric McCorkle + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/doc/rust-tutorial/code/salsa20/README.md b/doc/rust-tutorial/code/salsa20/README.md new file mode 100644 index 0000000000..e50dc62350 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/README.md @@ -0,0 +1,85 @@ +# RustCrypto: Salsa20 Stream Cipher + +[![Crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] +[![HAZMAT][hazmat-image]][hazmat-link] + +Pure Rust implementation of the [Salsa20 Stream Cipher][1]. + +[Documentation][docs-link] + + + +## About + +[Salsa20][1] is a [stream cipher][2] which is designed to support +high-performance software implementations. + +This crate also contains an implementation of [XSalsa20][3]: a variant +of Salsa20 with an extended 192-bit (24-byte) nonce, gated under the +`xsalsa20` Cargo feature (on-by-default). + +## ⚠️ Security Warning: [Hazmat!][hazmat-link] + +This crate does not ensure ciphertexts are authentic (i.e. by using a MAC to +verify ciphertext integrity), which can lead to serious vulnerabilities +if used incorrectly! + +No security audits of this crate have ever been performed, and it has not been +thoroughly assessed to ensure its operation is constant-time on common CPU +architectures. + +USE AT YOUR OWN RISK! + +## Minimum Supported Rust Version + +Rust **1.41** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/salsa20.svg +[crate-link]: https://crates.io/crates/salsa20 +[docs-image]: https://docs.rs/salsa20/badge.svg +[docs-link]: https://docs.rs/salsa20/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260049-stream-ciphers +[hazmat-image]: https://img.shields.io/badge/crypto-hazmat%E2%9A%A0-red.svg +[hazmat-link]: https://github.com/RustCrypto/meta/blob/master/HAZMAT.md +[build-image]: https://github.com/RustCrypto/stream-ciphers/workflows/salsa20/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/stream-ciphers/actions?query=workflow%3Asalsa20 + +[//]: # (footnotes) + +[1]: https://en.wikipedia.org/wiki/Salsa20 +[2]: https://en.wikipedia.org/wiki/Stream_cipher +[3]: https://cr.yp.to/snuffle/xsalsa-20081128.pdf +[4]: https://github.com/RustCrypto/AEADs/tree/master/xsalsa20poly1305 diff --git a/doc/rust-tutorial/code/salsa20/Salsa20.cry b/doc/rust-tutorial/code/salsa20/Salsa20.cry new file mode 100644 index 0000000000..197aec55f8 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/Salsa20.cry @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013-2023 Galois, Inc. + * Distributed under the terms of the BSD3 license (see LICENSE file) + */ + +// see http://cr.yp.to/snuffle/spec.pdf + +module Salsa20 where + +quarterround : [4][32] -> [4][32] +quarterround [y0, y1, y2, y3] = [z0, z1, z2, z3] + where + z1 = y1 ^ ((y0 + y3) <<< 0x7) + z2 = y2 ^ ((z1 + y0) <<< 0x9) + z3 = y3 ^ ((z2 + z1) <<< 0xd) + z0 = y0 ^ ((z3 + z2) <<< 0x12) + +property quarterround_passes_tests = + (quarterround [0x00000000, 0x00000000, 0x00000000, 0x00000000] == [0x00000000, 0x00000000, 0x00000000, 0x00000000]) /\ + (quarterround [0x00000001, 0x00000000, 0x00000000, 0x00000000] == [0x08008145, 0x00000080, 0x00010200, 0x20500000]) /\ + (quarterround [0x00000000, 0x00000001, 0x00000000, 0x00000000] == [0x88000100, 0x00000001, 0x00000200, 0x00402000]) /\ + (quarterround [0x00000000, 0x00000000, 0x00000001, 0x00000000] == [0x80040000, 0x00000000, 0x00000001, 0x00002000]) /\ + (quarterround [0x00000000, 0x00000000, 0x00000000, 0x00000001] == [0x00048044, 0x00000080, 0x00010000, 0x20100001]) /\ + (quarterround [0xe7e8c006, 0xc4f9417d, 0x6479b4b2, 0x68c67137] == [0xe876d72b, 0x9361dfd5, 0xf1460244, 0x948541a3]) /\ + (quarterround [0xd3917c5b, 0x55f1c407, 0x52a58a7a, 0x8f887a3b] == [0x3e2f308c, 0xd90a8f36, 0x6ab2a923, 0x2883524c]) + +rowround : [16][32] -> [16][32] +rowround [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15] = + [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15] + where + [ z0, z1, z2, z3] = quarterround [ y0, y1, y2, y3] + [ z5, z6, z7, z4] = quarterround [ y5, y6, y7, y4] + [z10, z11, z8, z9] = quarterround [y10, y11, y8, y9] + [z15, z12, z13, z14] = quarterround [y15, y12, y13, y14] + +property rowround_passes_tests = + (rowround [0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000] == + [0x08008145, 0x00000080, 0x00010200, 0x20500000, + 0x20100001, 0x00048044, 0x00000080, 0x00010000, + 0x00000001, 0x00002000, 0x80040000, 0x00000000, + 0x00000001, 0x00000200, 0x00402000, 0x88000100]) /\ + (rowround [0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365, + 0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6, + 0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e, + 0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a] == + [0xa890d39d, 0x65d71596, 0xe9487daa, 0xc8ca6a86, + 0x949d2192, 0x764b7754, 0xe408d9b9, 0x7a41b4d1, + 0x3402e183, 0x3c3af432, 0x50669f96, 0xd89ef0a8, + 0x0040ede5, 0xb545fbce, 0xd257ed4f, 0x1818882d]) + + +rowround_opt : [16][32] -> [16][32] +rowround_opt ys = join [ (quarterround (yi<<>>i | yi <- split ys | i <- [0 .. 3] ] + +property rowround_opt_is_rowround ys = rowround ys == rowround_opt ys + +columnround : [16][32] -> [16][32] +columnround [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15] = + [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15] + where + [ y0, y4, y8, y12] = quarterround [ x0, x4, x8, x12] + [ y5, y9, y13, y1] = quarterround [ x5, x9, x13, x1] + [y10, y14, y2, y6] = quarterround [x10, x14, x2, x6] + [y15, y3, y7, y11] = quarterround [x15, x3, x7, x11] + +property columnround_passes_tests = + (columnround [0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000] == + [0x10090288, 0x00000000, 0x00000000, 0x00000000, + 0x00000101, 0x00000000, 0x00000000, 0x00000000, + 0x00020401, 0x00000000, 0x00000000, 0x00000000, + 0x40a04001, 0x00000000, 0x00000000, 0x00000000]) /\ + (columnround [0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365, + 0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6, + 0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e, + 0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a] == + [0x8c9d190a, 0xce8e4c90, 0x1ef8e9d3, 0x1326a71a, + 0x90a20123, 0xead3c4f3, 0x63a091a0, 0xf0708d69, + 0x789b010c, 0xd195a681, 0xeb7d5504, 0xa774135c, + 0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8]) + + +columnround_opt : [16][32] -> [16][32] +columnround_opt xs = join (transpose [ (quarterround (xi<<>>i | xi <- transpose(split xs) | i <- [0 .. 3] ]) + +columnround_opt_is_columnround xs = columnround xs == columnround_opt xs + +property columnround_is_transpose_of_rowround ys = + rowround ys == join(transpose(split`{4}(columnround xs))) + where xs = join(transpose(split`{4} ys)) + +doubleround : [16][32] -> [16][32] +doubleround(xs) = rowround(columnround(xs)) + +property doubleround_passes_tests = + (doubleround [0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000] == + [0x8186a22d, 0x0040a284, 0x82479210, 0x06929051, + 0x08000090, 0x02402200, 0x00004000, 0x00800000, + 0x00010200, 0x20400000, 0x08008104, 0x00000000, + 0x20500000, 0xa0000040, 0x0008180a, 0x612a8020]) /\ + (doubleround [0xde501066, 0x6f9eb8f7, 0xe4fbbd9b, 0x454e3f57, + 0xb75540d3, 0x43e93a4c, 0x3a6f2aa0, 0x726d6b36, + 0x9243f484, 0x9145d1e8, 0x4fa9d247, 0xdc8dee11, + 0x054bf545, 0x254dd653, 0xd9421b6d, 0x67b276c1] == + [0xccaaf672, 0x23d960f7, 0x9153e63a, 0xcd9a60d0, + 0x50440492, 0xf07cad19, 0xae344aa0, 0xdf4cfdfc, + 0xca531c29, 0x8e7943db, 0xac1680cd, 0xd503ca00, + 0xa74b2ad6, 0xbc331c5c, 0x1dda24c7, 0xee928277]) + +littleendian : [4][8] -> [32] +littleendian b = join(reverse b) + +property littleendian_passes_tests = + (littleendian [ 0, 0, 0, 0] == 0x00000000) /\ + (littleendian [ 86, 75, 30, 9] == 0x091e4b56) /\ + (littleendian [255, 255, 255, 250] == 0xfaffffff) + +littleendian_inverse : {n} (fin n) => [8 * n] -> [n][8] +littleendian_inverse b = reverse(split b) + +property littleendian_is_invertable b = littleendian_inverse(littleendian b) == b + +littleendian_state : [64][8] -> [16][32] +littleendian_state b = [littleendian xi | xi <- split b] + +littleendian_state_inverse : [16][32] -> [64][8] +littleendian_state_inverse w = join (map littleendian_inverse w) + +property littleendian_state_is_invertable b = littleendian_state_inverse(littleendian_state b) == b + +Salsa20 : [32] -> [64][8] -> [64][8] +Salsa20 count xs = littleendian_state_inverse (Salsa20_rounds count xw xw) + where + xw = littleendian_state xs + +Salsa20_rounds : [32] -> [16][32] -> [16][32] -> [16][32] +Salsa20_rounds count xw xw' = xw + zs@(count/2) + where + zs = [xw'] # [ doubleround zi | zi <- zs ] + +property Salsa20_passes_tests = + (Salsa20 20 [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] == + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) /\ + (Salsa20 20 [211, 159, 13, 115, 76, 55, 82, 183, 3, 117, 222, 37, 191, 187, 234, 136, + 49, 237, 179, 48, 1, 106, 178, 219, 175, 199, 166, 48, 86, 16, 179, 207, + 31, 240, 32, 63, 15, 83, 93, 161, 116, 147, 48, 113, 238, 55, 204, 36, + 79, 201, 235, 79, 3, 81, 156, 47, 203, 26, 244, 243, 88, 118, 104, 54] == + [109, 42, 178, 168, 156, 240, 248, 238, 168, 196, 190, 203, 26, 110, 170, 154, + 29, 29, 150, 26, 150, 30, 235, 249, 190, 163, 251, 48, 69, 144, 51, 57, + 118, 40, 152, 157, 180, 57, 27, 94, 107, 42, 236, 35, 27, 111, 114, 114, + 219, 236, 232, 135, 111, 155, 110, 18, 24, 232, 95, 158, 179, 19, 48, 202]) /\ + (Salsa20 20 [ 88, 118, 104, 54, 79, 201, 235, 79, 3, 81, 156, 47, 203, 26, 244, 243, + 191, 187, 234, 136, 211, 159, 13, 115, 76, 55, 82, 183, 3, 117, 222, 37, + 86, 16, 179, 207, 49, 237, 179, 48, 1, 106, 178, 219, 175, 199, 166, 48, + 238, 55, 204, 36, 31, 240, 32, 63, 15, 83, 93, 161, 116, 147, 48, 113] == + [179, 19, 48, 202, 219, 236, 232, 135, 111, 155, 110, 18, 24, 232, 95, 158, + 26, 110, 170, 154, 109, 42, 178, 168, 156, 240, 248, 238, 168, 196, 190, 203, + 69, 144, 51, 57, 29, 29, 150, 26, 150, 30, 235, 249, 190, 163, 251, 48, + 27, 111, 114, 114, 118, 40, 152, 157, 180, 57, 27, 94, 107, 42, 236, 35]) + +property Salsa20_has_no_collisions x1 x2 = + if(x1 != x2) then (doubleround x1) != (doubleround x2) else True + +// Salsa 20 supports two key sizes, [16][8] and [32][8] +Salsa20_expansion : {a} (a >= 1, 2 >= a) => ([32], [16*a][8], [16][8]) -> [64][8] +Salsa20_expansion(count, k, n) = Salsa20 count (Salsa20_init(k, n)) + +Salsa20_init : {a} (a >= 1, 2 >= a) => ([16*a][8], [16][8]) -> [64][8] +Salsa20_init(k, n) = x + where + [s0, s1, s2, s3] = split "expand 32-byte k" : [4][4][8] + [t0, t1, t2, t3] = split "expand 16-byte k" : [4][4][8] + x = if(`a == 2) then s0 # k0 # s1 # n # s2 # k1 # s3 + else t0 # k0 # t1 # n # t2 # k0 # t3 + [k0, k1] = (split(k#zero)):[2][16][8] + +Salsa20_encrypt_with_offset : {a, l} (a >= 1, 2 >= a, l <= 2^^70) => + ([32], [16*a][8], [8][8], [64], [l][8]) -> [l][8] +Salsa20_encrypt_with_offset(count, k, v, o, m) = c + where + salsa = take (join [ Salsa20_expansion(count, k, v#(littleendian_inverse (o + i))) | i <- [0, 1 ... ] ]) + c = m ^ salsa + +Salsa20_encrypt : {a, l} (a >= 1, 2 >= a, l <= 2^^70) => ([32], [16*a][8], [8][8], [l][8]) -> [l][8] +Salsa20_encrypt(count, k, v, m) = c + where + salsa = take (join [ Salsa20_expansion(count, k, v#(littleendian_inverse i)) | i <- [0, 1 ... ] ]) + c = m ^ salsa diff --git a/doc/rust-tutorial/code/salsa20/Salsa20Extras.cry b/doc/rust-tutorial/code/salsa20/Salsa20Extras.cry new file mode 100644 index 0000000000..fd5ff69b72 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/Salsa20Extras.cry @@ -0,0 +1,17 @@ +module Salsa20Extras where + +import Salsa20 + +type STATE_WORDS = 16 +type BLOCK_SIZE = 64 + +counter_setup : [STATE_WORDS][32] -> [64] -> [STATE_WORDS][32] +counter_setup state counter = + updates state [8, 9] [drop counter, drop (counter >> 32)] + +apply_keystream : [32] -> [STATE_WORDS][32] -> [64] -> [BLOCK_SIZE][8] -> [BLOCK_SIZE][8] +apply_keystream count state0 counter output = + output ^ littleendian_state_inverse state2 + where + state1 = counter_setup state0 counter + state2 = Salsa20_rounds count state1 state1 diff --git a/doc/rust-tutorial/code/salsa20/salsa20-apply_keystream_alt-fail1.saw b/doc/rust-tutorial/code/salsa20/salsa20-apply_keystream_alt-fail1.saw new file mode 100644 index 0000000000..9a9eb4aab7 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-apply_keystream_alt-fail1.saw @@ -0,0 +1,178 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt num_rounds = mir_find_adt m (str_concat "salsa20::rounds::R" (show num_rounds)) []; +let phantom_data_adt r = mir_find_adt m "core::marker::PhantomData" [mir_adt r]; +let core_adt r = mir_find_adt m "salsa20::core#1::Core" [mir_adt r]; + +let rounds_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; + + mir_points_to self_ref self_val; + mir_points_to state_ref (mir_term {{ Salsa20_rounds `num_rounds self_state state_arr }}); +}; + +rounds_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false (rounds_spec 8) z3; +rounds_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_instfa33e77d840484a0" [quarter_round_ov] false (rounds_spec 20) z3; + +let counter_setup_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + counter <- mir_fresh_var "counter" mir_u64; + + mir_execute_func [self_ref, mir_term counter]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; +}; + +counter_setup_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_inst6e4a2d7250998ef7" [] false (counter_setup_spec 8) z3; +counter_setup_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_instfa33e77d840484a0" [] false (counter_setup_spec 20) z3; + +let new_raw_spec num_rounds = do { + key_ref <- mir_alloc (mir_array 32 mir_u8); + key_arr <- mir_fresh_var "key_arr" (mir_array 32 mir_u8); + mir_points_to key_ref (mir_term key_arr); + + nonce_ref <- mir_alloc (mir_array 8 mir_u8); + nonce_arr <- mir_fresh_var "nonce" (mir_array 8 mir_u8); + mir_points_to nonce_ref (mir_term nonce_arr); + + mir_execute_func [key_ref, nonce_ref]; + + let r = r_adt num_rounds; + let self_state = {{ littleendian_state (Salsa20_init(key_arr, nonce_arr # zero)) }}; + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value (core_adt r) [mir_term self_state, self_rounds]; + mir_return self_val; +}; + +new_raw_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_inst6e4a2d7250998ef7" [] false (new_raw_spec 8) z3; +new_raw_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_instfa33e77d840484a0" [] false (new_raw_spec 20) z3; + +let apply_keystream_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + counter <- mir_fresh_var "counter" mir_u64; + + output_arr <- mir_fresh_var "output_arr" (mir_array BLOCK_SIZE mir_u8); + output_ref <- mir_alloc_mut (mir_array BLOCK_SIZE mir_u8); + mir_points_to output_ref (mir_term output_arr); + let output = mir_slice_value output_ref; + + mir_execute_func [self_ref, mir_term counter, output]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; + mir_points_to output_ref (mir_term {{ apply_keystream `num_rounds self_state counter output_arr }}); +}; + +apply_keystream_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_inst6e4a2d7250998ef7" [counter_setup_8_spec_ov, rounds_8_spec_ov] false (apply_keystream_spec 8) z3; +apply_keystream_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_instfa33e77d840484a0" [counter_setup_20_spec_ov, rounds_20_spec_ov] false (apply_keystream_spec 20) z3; + +let apply_keystream_alt_spec num_rounds = do { + key <- mir_fresh_var "key" (mir_array 32 mir_u8); + nonce <- mir_fresh_var "nonce" (mir_array 8 mir_u8); + counter <- mir_fresh_var "counter" mir_u64; + + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + let self_state = {{ littleendian_state (Salsa20_init(key, nonce # littleendian_inverse counter)) }}; + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + output_arr <- mir_fresh_var "output_arr" (mir_array BLOCK_SIZE mir_u8); + output_ref <- mir_alloc_mut (mir_array BLOCK_SIZE mir_u8); + mir_points_to output_ref (mir_term output_arr); + let output = mir_slice_value output_ref; + + mir_execute_func [self_ref, mir_term counter, output]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; + mir_points_to output_ref (mir_term {{ Salsa20_encrypt_with_offset(`num_rounds, key, nonce, counter, output_arr) }}); +}; + +apply_keystream_alt_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_inst6e4a2d7250998ef7" [counter_setup_8_spec_ov, rounds_8_spec_ov] false (apply_keystream_alt_spec 8) z3; +apply_keystream_alt_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_instfa33e77d840484a0" [counter_setup_20_spec_ov, rounds_20_spec_ov] false (apply_keystream_alt_spec 20) z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-new_raw-fail1.saw b/doc/rust-tutorial/code/salsa20/salsa20-new_raw-fail1.saw new file mode 100644 index 0000000000..5d16d975d1 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-new_raw-fail1.saw @@ -0,0 +1,118 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt num_rounds = mir_find_adt m (str_concat "salsa20::rounds::R" (show num_rounds)) []; +let phantom_data_adt r = mir_find_adt m "core::marker::PhantomData" [mir_adt r]; +let core_adt r = mir_find_adt m "salsa20::core#1::Core" [mir_adt r]; + +let rounds_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; + + mir_points_to self_ref self_val; + mir_points_to state_ref (mir_term {{ Salsa20_rounds `num_rounds self_state state_arr }}); +}; + +rounds_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false (rounds_spec 8) z3; +rounds_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_instfa33e77d840484a0" [quarter_round_ov] false (rounds_spec 20) z3; + +let counter_setup_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + counter <- mir_fresh_var "counter" mir_u64; + + mir_execute_func [self_ref, mir_term counter]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; +}; + +counter_setup_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_inst6e4a2d7250998ef7" [] false (counter_setup_spec 8) z3; +counter_setup_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_instfa33e77d840484a0" [] false (counter_setup_spec 20) z3; + +let new_raw_spec num_rounds = do { + key_ref <- mir_alloc (mir_array 32 mir_u8); + key_arr <- mir_fresh_var "key_arr" (mir_array 32 mir_u8); + mir_points_to key_ref (mir_term key_arr); + + nonce_ref <- mir_alloc (mir_array 8 mir_u8); + nonce_arr <- mir_fresh_var "nonce" (mir_array 8 mir_u8); + mir_points_to nonce_ref (mir_term nonce_arr); + + mir_execute_func [key_ref, nonce_ref]; + + let r = r_adt num_rounds; + let self_state = {{ Salsa20_init(key_arr, nonce_arr) }}; + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value (core_adt r) [mir_term self_state, self_rounds]; + mir_return self_val; +}; + +new_raw_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_inst6e4a2d7250998ef7" [] false (new_raw_spec 8) z3; +new_raw_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_instfa33e77d840484a0" [] false (new_raw_spec 20) z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-new_raw-fail2.saw b/doc/rust-tutorial/code/salsa20/salsa20-new_raw-fail2.saw new file mode 100644 index 0000000000..84e93ea1c2 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-new_raw-fail2.saw @@ -0,0 +1,118 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt num_rounds = mir_find_adt m (str_concat "salsa20::rounds::R" (show num_rounds)) []; +let phantom_data_adt r = mir_find_adt m "core::marker::PhantomData" [mir_adt r]; +let core_adt r = mir_find_adt m "salsa20::core#1::Core" [mir_adt r]; + +let rounds_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; + + mir_points_to self_ref self_val; + mir_points_to state_ref (mir_term {{ Salsa20_rounds `num_rounds self_state state_arr }}); +}; + +rounds_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false (rounds_spec 8) z3; +rounds_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_instfa33e77d840484a0" [quarter_round_ov] false (rounds_spec 20) z3; + +let counter_setup_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + counter <- mir_fresh_var "counter" mir_u64; + + mir_execute_func [self_ref, mir_term counter]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; +}; + +counter_setup_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_inst6e4a2d7250998ef7" [] false (counter_setup_spec 8) z3; +counter_setup_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_instfa33e77d840484a0" [] false (counter_setup_spec 20) z3; + +let new_raw_spec num_rounds = do { + key_ref <- mir_alloc (mir_array 32 mir_u8); + key_arr <- mir_fresh_var "key_arr" (mir_array 32 mir_u8); + mir_points_to key_ref (mir_term key_arr); + + nonce_ref <- mir_alloc (mir_array 8 mir_u8); + nonce_arr <- mir_fresh_var "nonce" (mir_array 8 mir_u8); + mir_points_to nonce_ref (mir_term nonce_arr); + + mir_execute_func [key_ref, nonce_ref]; + + let r = r_adt num_rounds; + let self_state = {{ Salsa20_init(key_arr, nonce_arr # zero) }}; + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value (core_adt r) [mir_term self_state, self_rounds]; + mir_return self_val; +}; + +new_raw_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_inst6e4a2d7250998ef7" [] false (new_raw_spec 8) z3; +new_raw_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_instfa33e77d840484a0" [] false (new_raw_spec 20) z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail1.saw b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail1.saw new file mode 100644 index 0000000000..f2c2dbb6b6 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail1.saw @@ -0,0 +1,21 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; +}; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail2.saw b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail2.saw new file mode 100644 index 0000000000..b614c28bc0 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail2.saw @@ -0,0 +1,26 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; + +let STATE_WORDS = 16; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; +}; + +quarter_round_ov <- + mir_verify m "salsa20::core::quarter_round" [] false quarter_round_spec z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail3.saw b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail3.saw new file mode 100644 index 0000000000..facb344d20 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail3.saw @@ -0,0 +1,26 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; + +let STATE_WORDS = 16; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; +}; + +quarter_round_ov <- + mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail4.saw b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail4.saw new file mode 100644 index 0000000000..9c5fda59a8 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-quarter_round-fail4.saw @@ -0,0 +1,34 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; + +let STATE_WORDS = 16; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + mir_precond {{ a < `STATE_WORDS /\ + b < `STATE_WORDS /\ + c < `STATE_WORDS /\ + d < `STATE_WORDS }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let indices = {{ [a, b, c, d] }}; + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-reference.saw b/doc/rust-tutorial/code/salsa20/salsa20-reference.saw new file mode 100644 index 0000000000..83b6d027ac --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-reference.saw @@ -0,0 +1,178 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt num_rounds = mir_find_adt m (str_concat "salsa20::rounds::R" (show num_rounds)) []; +let phantom_data_adt r = mir_find_adt m "core::marker::PhantomData" [mir_adt r]; +let core_adt r = mir_find_adt m "salsa20::core#1::Core" [mir_adt r]; + +let rounds_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; + + mir_points_to self_ref self_val; + mir_points_to state_ref (mir_term {{ Salsa20_rounds `num_rounds self_state state_arr }}); +}; + +rounds_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false (rounds_spec 8) z3; +rounds_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_instfa33e77d840484a0" [quarter_round_ov] false (rounds_spec 20) z3; + +let counter_setup_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + counter <- mir_fresh_var "counter" mir_u64; + + mir_execute_func [self_ref, mir_term counter]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; +}; + +counter_setup_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_inst6e4a2d7250998ef7" [] false (counter_setup_spec 8) z3; +counter_setup_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::counter_setup::_instfa33e77d840484a0" [] false (counter_setup_spec 20) z3; + +let new_raw_spec num_rounds = do { + key_ref <- mir_alloc (mir_array 32 mir_u8); + key_arr <- mir_fresh_var "key_arr" (mir_array 32 mir_u8); + mir_points_to key_ref (mir_term key_arr); + + nonce_ref <- mir_alloc (mir_array 8 mir_u8); + nonce_arr <- mir_fresh_var "nonce" (mir_array 8 mir_u8); + mir_points_to nonce_ref (mir_term nonce_arr); + + mir_execute_func [key_ref, nonce_ref]; + + let r = r_adt num_rounds; + let self_state = {{ littleendian_state (Salsa20_init(key_arr, nonce_arr # zero)) }}; + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value (core_adt r) [mir_term self_state, self_rounds]; + mir_return self_val; +}; + +new_raw_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_inst6e4a2d7250998ef7" [] false (new_raw_spec 8) z3; +new_raw_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::new_raw::_instfa33e77d840484a0" [] false (new_raw_spec 20) z3; + +let apply_keystream_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + counter <- mir_fresh_var "counter" mir_u64; + + output_arr <- mir_fresh_var "output_arr" (mir_array BLOCK_SIZE mir_u8); + output_ref <- mir_alloc_mut (mir_array BLOCK_SIZE mir_u8); + mir_points_to output_ref (mir_term output_arr); + let output = mir_slice_value output_ref; + + mir_execute_func [self_ref, mir_term counter, output]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; + mir_points_to output_ref (mir_term {{ apply_keystream `num_rounds self_state counter output_arr }}); +}; + +apply_keystream_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_inst6e4a2d7250998ef7" [counter_setup_8_spec_ov, rounds_8_spec_ov] false (apply_keystream_spec 8) z3; +apply_keystream_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_instfa33e77d840484a0" [counter_setup_20_spec_ov, rounds_20_spec_ov] false (apply_keystream_spec 20) z3; + +let apply_keystream_alt_spec num_rounds = do { + key <- mir_fresh_var "key" (mir_array 32 mir_u8); + nonce <- mir_fresh_var "nonce" (mir_array 8 mir_u8); + counter <- mir_fresh_var "counter" mir_u64; + + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + let self_state = {{ littleendian_state (Salsa20_init(key, nonce # littleendian_inverse counter)) }}; + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + output_arr <- mir_fresh_var "output_arr" (mir_array BLOCK_SIZE mir_u8); + output_ref <- mir_alloc_mut (mir_array BLOCK_SIZE mir_u8); + mir_points_to output_ref (mir_term output_arr); + let output = mir_slice_value output_ref; + + mir_execute_func [self_ref, mir_term counter, output]; + + let self_state' = {{ counter_setup self_state counter }}; + let self_val' = mir_struct_value core_adt_inst [mir_term self_state', self_rounds]; + mir_points_to self_ref self_val'; + mir_points_to output_ref (mir_term {{ Salsa20_encrypt_with_offset(`num_rounds, key, nonce, counter, output_arr) }}); +}; + +apply_keystream_alt_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_inst6e4a2d7250998ef7" [counter_setup_8_spec_ov, rounds_8_spec_ov] false (apply_keystream_alt_spec 8) yices; +apply_keystream_alt_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::apply_keystream::_instfa33e77d840484a0" [counter_setup_20_spec_ov, rounds_20_spec_ov] false (apply_keystream_alt_spec 20) yices; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-1.saw b/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-1.saw new file mode 100644 index 0000000000..d94bb10179 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-1.saw @@ -0,0 +1,65 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt = mir_find_adt m "salsa20::rounds::R8" []; +let phantom_data_adt = mir_find_adt m "core::marker::PhantomData" [mir_adt r_adt]; +let core_adt = mir_find_adt m "salsa20::core#1::Core" [mir_adt r_adt]; + +let rounds_spec = do { + self_ref <- mir_alloc_mut (mir_adt core_adt); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value phantom_data_adt []; + let self_val = mir_struct_value core_adt [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; +}; + +rounds_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false rounds_spec z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-2.saw b/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-2.saw new file mode 100644 index 0000000000..84a4ec6ad0 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-2.saw @@ -0,0 +1,68 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt = mir_find_adt m "salsa20::rounds::R8" []; +let phantom_data_adt = mir_find_adt m "core::marker::PhantomData" [mir_adt r_adt]; +let core_adt = mir_find_adt m "salsa20::core#1::Core" [mir_adt r_adt]; + +let rounds_spec = do { + self_ref <- mir_alloc_mut (mir_adt core_adt); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value phantom_data_adt []; + let self_val = mir_struct_value core_adt [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; + + mir_points_to self_ref self_val; + mir_points_to state_ref (mir_term {{ Salsa20_rounds 8 self_state state_arr }}); +}; + +rounds_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false rounds_spec z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-3.saw b/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-3.saw new file mode 100644 index 0000000000..e608c8c1fd --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/salsa20-rounds-take-3.saw @@ -0,0 +1,72 @@ +enable_experimental; + +m <- mir_load_module "salsa20.linked-mir.json"; +import "Salsa20.cry"; +import "Salsa20Extras.cry"; + +let STATE_WORDS = 16; +let BLOCK_SIZE = 64; + +let quarter_round_spec = do { + a <- mir_fresh_var "a" mir_usize; + b <- mir_fresh_var "b" mir_usize; + c <- mir_fresh_var "c" mir_usize; + d <- mir_fresh_var "d" mir_usize; + let indices = {{ [a, b, c, d] }}; + mir_precond {{ indices == [0, 1, 2, 3] + \/ indices == [5, 6, 7, 4] + \/ indices == [10, 11, 8, 9] + \/ indices == [15, 12, 13, 14] + \/ indices == [0, 4, 8, 12] + \/ indices == [5, 9, 13, 1] + \/ indices == [10, 14, 2, 6] + \/ indices == [15, 3, 7, 11] + }}; + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [ mir_term a + , mir_term b + , mir_term c + , mir_term d + , state_ref + ]; + + let state_arr' = {{ updates state_arr indices (quarterround (state_arr @@ indices)) }}; + mir_points_to state_ref (mir_term state_arr'); +}; + +quarter_round_ov <- + mir_unsafe_assume_spec m "salsa20::core#1::quarter_round" quarter_round_spec; + // Temporarily commented out to save time: + // + // mir_verify m "salsa20::core#1::quarter_round" [] false quarter_round_spec z3; + +let r_adt num_rounds = mir_find_adt m (str_concat "salsa20::rounds::R" (show num_rounds)) []; +let phantom_data_adt r = mir_find_adt m "core::marker::PhantomData" [mir_adt r]; +let core_adt r = mir_find_adt m "salsa20::core#1::Core" [mir_adt r]; + +let rounds_spec num_rounds = do { + let r = r_adt num_rounds; + let core_adt_inst = core_adt r; + self_ref <- mir_alloc_mut (mir_adt core_adt_inst); + self_state <- mir_fresh_var "self_state" (mir_array STATE_WORDS mir_u32); + let self_rounds = mir_struct_value (phantom_data_adt r) []; + let self_val = mir_struct_value core_adt_inst [mir_term self_state, self_rounds]; + mir_points_to self_ref self_val; + + state_ref <- mir_alloc_mut (mir_array STATE_WORDS mir_u32); + state_arr <- mir_fresh_var "state" (mir_array STATE_WORDS mir_u32); + mir_points_to state_ref (mir_term state_arr); + + mir_execute_func [self_ref, state_ref]; + + mir_points_to self_ref self_val; + mir_points_to state_ref (mir_term {{ Salsa20_rounds `num_rounds self_state state_arr }}); +}; + +rounds_8_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_inst6e4a2d7250998ef7" [quarter_round_ov] false (rounds_spec 8) z3; +rounds_20_spec_ov <- + mir_verify m "salsa20::core#1::{impl#0}::rounds::_instfa33e77d840484a0" [quarter_round_ov] false (rounds_spec 20) z3; diff --git a/doc/rust-tutorial/code/salsa20/salsa20.linked-mir.json.tar.gz b/doc/rust-tutorial/code/salsa20/salsa20.linked-mir.json.tar.gz new file mode 100644 index 0000000000..0281738af4 Binary files /dev/null and b/doc/rust-tutorial/code/salsa20/salsa20.linked-mir.json.tar.gz differ diff --git a/doc/rust-tutorial/code/salsa20/src/core.rs b/doc/rust-tutorial/code/salsa20/src/core.rs new file mode 100644 index 0000000000..4b3d5ad571 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/src/core.rs @@ -0,0 +1,498 @@ +//! The Salsa20 core function. + +use crate::{rounds::Rounds, Key, Nonce, BLOCK_SIZE, CONSTANTS, STATE_WORDS}; +use core::{convert::TryInto, marker::PhantomData, /* mem */}; + +/// The Salsa20 core function. +// TODO(tarcieri): zeroize support +pub struct Core { + /// Internal state of the core function + state: [u32; STATE_WORDS], + + /// Number of rounds to perform + rounds: PhantomData, +} + +impl Core { + /// Initialize core function with the given key and IV + pub fn new(key: &Key, iv: &Nonce) -> Self { + Self::new_raw(key.as_ref(), iv.as_ref()) + } + + /// Initialize core function with the given key and IV + pub fn new_raw(key: &[u8; 32], iv: &[u8; 8]) -> Self { + #[allow(unsafe_code)] + //let mut state: [u32; STATE_WORDS] = unsafe { mem::zeroed() }; + let mut state: [u32; STATE_WORDS] = [0; STATE_WORDS]; + state[0] = CONSTANTS[0]; + + for (i, chunk) in key[..16].chunks(4).enumerate() { + state[1 + i] = u32::from_le_bytes(chunk.try_into().unwrap()); + } + + state[5] = CONSTANTS[1]; + + for (i, chunk) in iv.chunks(4).enumerate() { + state[6 + i] = u32::from_le_bytes(chunk.try_into().unwrap()); + } + + state[8] = 0; + state[9] = 0; + state[10] = CONSTANTS[2]; + + for (i, chunk) in key[16..].chunks(4).enumerate() { + state[11 + i] = u32::from_le_bytes(chunk.try_into().unwrap()); + } + + state[15] = CONSTANTS[3]; + + Self { + state, + rounds: PhantomData, + } + } + + /// Generate output, overwriting data already in the buffer + pub fn generate(&mut self, output: &mut [u8]) { + debug_assert_eq!(output.len(), BLOCK_SIZE); + + let mut state = self.state; + self.rounds(&mut state); + + for (i, chunk) in output.chunks_mut(4).enumerate() { + chunk.copy_from_slice(&state[i].to_le_bytes()); + } + } + + /// Apply generated keystream to the output buffer + pub fn apply_keystream(&mut self, counter: u64, output: &mut [u8]) { + debug_assert_eq!(output.len(), BLOCK_SIZE); + self.counter_setup(counter); + + let mut state = self.state; + self.rounds(&mut state); + + for (i, chunk) in output.chunks_mut(4).enumerate() { + for (a, b) in chunk.iter_mut().zip(&state[i].to_le_bytes()) { + *a ^= *b; + } + } + } + + #[inline] + pub(crate) fn counter_setup(&mut self, counter: u64) { + self.state[8] = (counter & 0xffff_ffff) as u32; + self.state[9] = ((counter >> 32) & 0xffff_ffff) as u32; + } + + /// Run the 20 rounds (i.e. 10 double rounds) of Salsa20 + #[inline] + fn rounds(&mut self, state: &mut [u32; STATE_WORDS]) { + for _ in 0..(R::COUNT / 2) { + // column rounds + quarter_round(0, 4, 8, 12, state); + quarter_round(5, 9, 13, 1, state); + quarter_round(10, 14, 2, 6, state); + quarter_round(15, 3, 7, 11, state); + + // diagonal rounds + quarter_round(0, 1, 2, 3, state); + quarter_round(5, 6, 7, 4, state); + quarter_round(10, 11, 8, 9, state); + quarter_round(15, 12, 13, 14, state); + } + + for (s1, s0) in state.iter_mut().zip(&self.state) { + *s1 = s1.wrapping_add(*s0); + } + } +} + +impl From<[u32; STATE_WORDS]> for Core { + fn from(state: [u32; STATE_WORDS]) -> Core { + Self { + state, + rounds: PhantomData, + } + } +} + +#[inline] +#[allow(clippy::many_single_char_names)] +pub(crate) fn quarter_round( + a: usize, + b: usize, + c: usize, + d: usize, + state: &mut [u32; STATE_WORDS], +) { + let mut t: u32; + + t = state[a].wrapping_add(state[d]); + state[b] ^= t.rotate_left(7) as u32; + + t = state[b].wrapping_add(state[a]); + state[c] ^= t.rotate_left(9) as u32; + + t = state[c].wrapping_add(state[b]); + state[d] ^= t.rotate_left(13) as u32; + + t = state[d].wrapping_add(state[c]); + state[a] ^= t.rotate_left(18) as u32; +} + +#[inline] +fn double_round( + state: &mut [u32; STATE_WORDS], +) { + // column rounds + quarter_round(0, 4, 8, 12, state); + quarter_round(5, 9, 13, 1, state); + quarter_round(10, 14, 2, 6, state); + quarter_round(15, 3, 7, 11, state); + + // diagonal rounds + quarter_round(0, 1, 2, 3, state); + quarter_round(5, 6, 7, 4, state); + quarter_round(10, 11, 8, 9, state); + quarter_round(15, 12, 13, 14, state); +} + + +#[cfg(crux)] +mod crux_test { + extern crate crucible; + use crucible::*; + // use crucible::method_spec::{MethodSpec, MethodSpecBuilder, clobber_globals}; + use super::*; + + /* + mod cry { + use super::crucible::cryptol; + cryptol! { + path "/home/stuart/work/cryptol-specs/Primitive/Symmetric/Cipher/Stream/Salsa20.cry"; + pub fn quarter_round(x: [u32; 4]) -> [u32; 4] = "quarterround"; + pub fn double_round(x: [u32; 16]) -> [u32; 16] = "doubleround"; + pub fn rounds(x: [u32; 16]) -> [u32; 16]; + pub fn salsa20(x: [u8; 64]) -> [u8; 64] = "Salsa20"; + + pub fn u32_from_bytes_le(x: [u8; 4]) -> u32 = "littleendian"; + pub fn u32_to_bytes_le(x: u32) -> [u8; 4] = "littleendian_inverse"; + + pub fn expand(k: [u8; 32], n: [u8; 16]) -> [u8; 64] = "Salsa20_expansion_key32"; + + pub fn encrypt_block(k: [u8; 32], v: [u8; 8], o: u64, m: [u8; 64]) -> [u8; 64] + = "Salsa20_encrypt_block_key32"; + } + } + + fn state_to_bytes [u8; 4]>(f: F, x: [u32; 16]) -> [u8; 64] { + let mut out = [0; 64]; + for i in 0 .. 16 { + out[i * 4 .. (i + 1) * 4].copy_from_slice(&f(x[i])); + } + out + } + + fn state_from_bytes u32>(f: F, x: [u8; 64]) -> [u32; 16] { + let mut out = [0; 16]; + for i in 0 .. 16 { + let mut buf = [0; 4]; + buf.copy_from_slice(&x[i * 4 .. (i + 1) * 4]); + out[i] = f(buf); + } + out + } + + fn state_to_bytes_cryptol(x: [u32; 16]) -> [u8; 64] { + state_to_bytes(cry::u32_to_bytes_le, x) + } + + fn state_from_bytes_cryptol(x: [u8; 64]) -> [u32; 16] { + state_from_bytes(cry::u32_from_bytes_le, x) + } + + fn state_to_bytes_rust(x: [u32; 16]) -> [u8; 64] { + state_to_bytes(u32::to_le_bytes, x) + } + + fn state_from_bytes_rust(x: [u8; 64]) -> [u32; 16] { + state_from_bytes(u32::from_le_bytes, x) + } + + #[crux::test] + fn test_state_to_bytes_eq() { + let state = <[u32; 16]>::symbolic("state"); + crucible_assert!( + (&state_to_bytes_cryptol(state) as &[_]) == + (&state_to_bytes_rust(state) as &[_])); + } + + #[crux::test] + fn test_state_to_from_bytes() { + let state = <[u32; 16]>::symbolic("state"); + crucible_assert!(state == state_from_bytes_cryptol(state_to_bytes_cryptol(state))); + } + + #[crux::test] + fn test_state_from_to_bytes() { + let mut state = [0; 64]; + for b in state.iter_mut() { + *b = u8::symbolic("state"); + } + crucible_assert!((&state as &[_]) == + (&state_to_bytes_cryptol(state_from_bytes_cryptol(state)) as &[_])); + } + + #[crux::test] + fn test_salsa20_rounds_from_bytes() { + let mut state0 = [0; 64]; + for b in state0.iter_mut() { + *b = u8::symbolic("state"); + } + crucible_assert!( + state_from_bytes_cryptol(cry::salsa20(state0)) == + cry::rounds(state_from_bytes_cryptol(state0)) + ) + } + + #[crux::test] + fn test_salsa20_rounds_to_from_bytes() { + let mut state0 = [0; 64]; + for b in state0.iter_mut() { + *b = u8::symbolic("state"); + } + let x = cry::salsa20(state0); + let y = state_to_bytes_cryptol(cry::rounds(state_from_bytes_cryptol(state0))); + assert!(x.len() == y.len()); + crucible_assert!(x.iter().eq(y.iter())); + } + + fn quarter_round_cryptol( + a: usize, + b: usize, + c: usize, + d: usize, + state: &mut [u32; STATE_WORDS], + ) { + let vals0 = [state[a], state[b], state[c], state[d]]; + let vals1 = cry::quarter_round(vals0); + state[a] = vals1[0]; + state[b] = vals1[1]; + state[c] = vals1[2]; + state[d] = vals1[3]; + } + + fn rounds_cryptol( + state0: [u32; 16], + ) -> [u32; 16] { + let mut state_bytes0 = [0; 64]; + for (i, &x) in state0.iter().enumerate() { + state_bytes0[i * 4 .. (i + 1) * 4].copy_from_slice(&x.to_le_bytes()); + } + + let state_bytes1 = cry::salsa20(state_bytes0); + let mut state1 = [0; 16]; + for (i, x) in state1.iter_mut().enumerate() { + let mut arr = [0; 4]; + arr.copy_from_slice(&state_bytes1[i * 4 .. (i + 1) * 4]); + *x = u32::from_le_bytes(arr); + } + + state1 + } + + /// There are eight sets of indices that are used with the `quarter_round` function; this + /// function chooses one such set arbitrarily. + fn quarter_round_indices() -> (usize, usize, usize, usize) { + let indices = Symbolic::symbolic("indices"); + crucible_assume!( + indices == (0, 1, 2, 3) || + indices == (5, 6, 7, 4) || + indices == (10, 11, 8, 9) || + indices == (15, 12, 13, 14) || + indices == (0, 4, 8, 12) || + indices == (5, 9, 13, 1) || + indices == (10, 14, 2, 6) || + indices == (15, 3, 7, 11) + ); + indices + } + + #[crux::test] + fn quarter_round_test() { + let state0 = <[u32; STATE_WORDS]>::symbolic("state"); + let (a, b, c, d) = quarter_round_indices(); + + let mut state1_real = state0; + quarter_round(a, b, c, d, &mut state1_real); + + let mut state1_cryptol = state0; + quarter_round_cryptol(a, b, c, d, &mut state1_cryptol); + + crucible_assert!(state1_real == state1_cryptol); + } + + fn quarter_round_spec() -> MethodSpec { + let state0 = <[u32; STATE_WORDS]>::symbolic("state"); + let (a, b, c, d) = quarter_round_indices(); + + let mut state1_real = state0; + //quarter_round(a, b, c, d, &mut state1_real); + let mut msb = MethodSpecBuilder::new(quarter_round); + msb.add_arg(&a); + msb.add_arg(&b); + msb.add_arg(&c); + msb.add_arg(&d); + msb.add_arg(& &mut state1_real); + msb.gather_assumes(); + + let mut state1_cryptol = state0; + quarter_round_cryptol(a, b, c, d, &mut state1_cryptol); + + crucible_assert!(state1_real == state1_cryptol); + + msb.set_return(&()); + msb.gather_asserts(); + msb.finish() + } + */ + + #[crux::test] + fn double_round_test() { + //quarter_round_spec().enable(); + + let state0 = <[u32; STATE_WORDS]>::symbolic("state"); + + let mut state1_real = state0; + double_round(&mut state1_real); + + // crucible_assert!(state1_real == cry::double_round(state0)); + } + + /* + fn double_round_spec() -> MethodSpec { + let state0 = <[u32; STATE_WORDS]>::symbolic("state"); + + let mut state1_real = state0; + //double_round(&mut state1_real); + let mut msb = MethodSpecBuilder::new(double_round); + msb.add_arg(& &mut state1_real); + msb.gather_assumes(); + + crucible_assert!(state1_real == cry::double_round(state0)); + + msb.set_return(&()); + msb.gather_asserts(); + msb.finish() + } + */ + + /* + #[crux::test] + fn rounds_test() { + //double_round_spec().enable(); + + let state0 = <[u32; STATE_WORDS]>::symbolic("state"); + + let mut core = Core:: { + state: state0, + rounds: PhantomData, + }; + let mut state_copy = core.state; + core.rounds(&mut state_copy); + + crucible_assert!(state_copy == cry::rounds(state0)); + } + */ + + /* + #[crux::test] + fn rounds_test() { + //double_round_spec().enable(); + + let mut state0_bytes = [0; 64]; + for b in state0_bytes.iter_mut() { + *b = u8::symbolic("state"); + } + let state0 = state_from_bytes_rust(state0_bytes); + + let mut core = Core:: { + state: state0, + rounds: PhantomData, + }; + let mut state_copy = core.state; + core.rounds(&mut state_copy); + + crucible_assert!( + state_to_bytes_rust(state_copy).iter() + .eq(cry::salsa20(state0_bytes).iter()) + ); + } + + #[crux::test] + fn expansion_test() { + let key = <[u8; 32]>::symbolic("key"); + let nonce = <[u8; 8]>::symbolic("nonce"); + let counter = <[u8; 8]>::symbolic("counter"); + + let mut core = Core::::new_raw(&key, &nonce); + core.counter_setup(u64::from_le_bytes(counter)); + let mut state = core.state; + core.rounds(&mut state); + + let mut nonce_and_counter = [0; 16]; + nonce_and_counter[0..8].copy_from_slice(&nonce); + nonce_and_counter[8..16].copy_from_slice(&counter); + let expansion = cry::expand(key, nonce_and_counter); + + crucible_assert!( + state.iter() + .eq(state_from_bytes_rust(expansion).iter()) + ); + } + */ + + #[crux::test] + fn apply_keystream_test() { + let key = <[u8; 32]>::symbolic("key"); + let nonce = <[u8; 8]>::symbolic("nonce"); + let counter = u64::symbolic("counter"); + let mut msg = [0; 64]; + for b in msg.iter_mut() { + *b = u8::symbolic("msg"); + } + + let mut core = Core::::new_raw(&key, &nonce); + let mut msg1 = msg; + core.apply_keystream(counter, &mut msg1); + + // let msg2 = cry::encrypt_block(key, nonce, counter, msg); + + // crucible_assert!( + // msg1.iter().eq(msg2.iter()) + // ); + } + + #[crux::test] + fn apply_keystream_test8() { + let key = <[u8; 32]>::symbolic("key"); + let nonce = <[u8; 8]>::symbolic("nonce"); + let counter = u64::symbolic("counter"); + let mut msg = [0; 64]; + for b in msg.iter_mut() { + *b = u8::symbolic("msg"); + } + + let mut core = Core::::new_raw(&key, &nonce); + let mut msg1 = msg; + core.apply_keystream(counter, &mut msg1); + + // let msg2 = cry::encrypt_block(key, nonce, counter, msg); + + // crucible_assert!( + // msg1.iter().eq(msg2.iter()) + // ); + } + +} diff --git a/doc/rust-tutorial/code/salsa20/src/lib.rs b/doc/rust-tutorial/code/salsa20/src/lib.rs new file mode 100644 index 0000000000..cce5dc3655 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/src/lib.rs @@ -0,0 +1,92 @@ +//! The Salsa20 stream cipher. +//! +//! Cipher functionality is accessed using traits from re-exported +//! [`cipher`](https://docs.rs/cipher) crate. +//! +//! # Security Warning +//! +//! This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity +//! is not verified, which can lead to serious vulnerabilities! +//! +//! USE AT YOUR OWN RISK! +//! +//! # Diagram +//! +//! This diagram illustrates the Salsa quarter round function. +//! Each round consists of four quarter-rounds: +//! +//! +//! +//! Legend: +//! +//! - ⊞ add +//! - ‹‹‹ rotate +//! - ⊕ xor +//! +//! # Usage +//! +//! ``` +//! use salsa20::{Salsa20, Key, Nonce}; +//! use salsa20::cipher::{NewCipher, StreamCipher, StreamCipherSeek}; +//! +//! let mut data = [1, 2, 3, 4, 5, 6, 7]; +//! +//! let key = Key::from_slice(b"an example very very secret key."); +//! let nonce = Nonce::from_slice(b"a nonce."); +//! +//! // create cipher instance +//! let mut cipher = Salsa20::new(&key, &nonce); +//! +//! // apply keystream (encrypt) +//! cipher.apply_keystream(&mut data); +//! assert_eq!(data, [182, 14, 133, 113, 210, 25, 165]); +//! +//! // seek to the keystream beginning and apply it again to the `data` (decrypt) +//! cipher.seek(0); +//! cipher.apply_keystream(&mut data); +//! assert_eq!(data, [1, 2, 3, 4, 5, 6, 7]); +//! ``` + +#![no_std] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" +)] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(unsafe_code)] +#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)] + +pub use cipher; + +mod core; +mod rounds; +mod salsa; +// #[cfg(feature = "xsalsa20")] +// mod xsalsa; + +pub use crate::salsa::{Key, Nonce}; +// pub use crate::salsa::{Key, Nonce, Salsa, Salsa12, Salsa20, Salsa8}; + +// #[cfg(feature = "expose-core")] +pub use crate::{ + core::Core, + rounds::{R12, R20, R8}, +}; + +// #[cfg(feature = "hsalsa20")] +// pub use crate::xsalsa::hsalsa20; +// +// #[cfg(feature = "xsalsa20")] +// pub use crate::xsalsa::{XNonce, XSalsa20}; + +/// Size of a Salsa20 block in bytes +pub const BLOCK_SIZE: usize = 64; + +/// Size of a Salsa20 key in bytes +pub const KEY_SIZE: usize = 32; + +/// Number of 32-bit words in the Salsa20 state +const STATE_WORDS: usize = 16; + +/// State initialization constant ("expand 32-byte k") +const CONSTANTS: [u32; 4] = [0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]; diff --git a/doc/rust-tutorial/code/salsa20/src/rounds.rs b/doc/rust-tutorial/code/salsa20/src/rounds.rs new file mode 100644 index 0000000000..22905591b1 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/src/rounds.rs @@ -0,0 +1,29 @@ +//! Numbers of rounds allowed to be used with a Salsa20 family stream cipher + +pub trait Rounds: Copy { + const COUNT: usize; +} + +/// 8-rounds (Salsa20/8) +#[derive(Copy, Clone)] +pub struct R8; + +impl Rounds for R8 { + const COUNT: usize = 8; +} + +/// 12-rounds (Salsa20/12) +#[derive(Copy, Clone)] +pub struct R12; + +impl Rounds for R12 { + const COUNT: usize = 12; +} + +/// 20-rounds (Salsa20/20) +#[derive(Copy, Clone)] +pub struct R20; + +impl Rounds for R20 { + const COUNT: usize = 20; +} diff --git a/doc/rust-tutorial/code/salsa20/src/salsa.rs b/doc/rust-tutorial/code/salsa20/src/salsa.rs new file mode 100644 index 0000000000..c25f374ee7 --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/src/salsa.rs @@ -0,0 +1,174 @@ +//! Salsa20 stream cipher implementation. +//! +//! Adapted from the `ctr` crate. + +// TODO(tarcieri): figure out how to unify this with the `ctr` crate (see #95) + +// use crate::{ +// core::Core, +// rounds::{Rounds, R12, R20, R8}, +// BLOCK_SIZE, +// }; +use cipher::{ + consts::{U32, U8}, + // errors::{LoopError, OverflowError}, + // NewCipher, SeekNum, StreamCipher, StreamCipherSeek, +}; +// use core::fmt; + +#[cfg(docsrs)] +use cipher::generic_array::GenericArray; + +/// Key type. +/// +/// Implemented as an alias for [`GenericArray`]. +/// +/// (NOTE: all three round variants use the same key size) +pub type Key = cipher::generic_array::GenericArray; +// pub type Key = cipher::CipherKey; + +/// Nonce type. +/// +/// Implemented as an alias for [`GenericArray`]. +pub type Nonce = cipher::generic_array::GenericArray; +// pub type Nonce = cipher::Nonce; + +/* +/// Salsa20/8 stream cipher +/// (reduced-round variant of Salsa20 with 8 rounds, *not recommended*) +pub type Salsa8 = Salsa; + +/// Salsa20/12 stream cipher +/// (reduced-round variant of Salsa20 with 12 rounds, *not recommended*) +pub type Salsa12 = Salsa; + +/// Salsa20/20 stream cipher +/// (20 rounds; **recommended**) +pub type Salsa20 = Salsa; + +/// Internal buffer +type Buffer = [u8; BLOCK_SIZE]; + +/// The Salsa20 family of stream ciphers +/// (implemented generically over a number of rounds). +/// +/// We recommend you use the [`Salsa20`] (a.k.a. Salsa20/20) variant. +pub struct Salsa { + /// Salsa core function initialized with a key and IV + block: Core, + + /// Buffer containing previous output + buffer: Buffer, + + /// Position within buffer, or `None` if the buffer is not in use + buffer_pos: u8, + + /// Current counter value relative to the start of the keystream + counter: u64, +} + +impl NewCipher for Salsa { + /// Key size in bytes + type KeySize = U32; + + /// Nonce size in bytes + type NonceSize = U8; + + fn new(key: &Key, nonce: &Nonce) -> Self { + let block = Core::new(key, nonce); + + Self { + block, + buffer: [0u8; BLOCK_SIZE], + buffer_pos: 0, + counter: 0, + } + } +} + +impl StreamCipher for Salsa { + fn try_apply_keystream(&mut self, mut data: &mut [u8]) -> Result<(), LoopError> { + self.check_data_len(data)?; + let pos = self.buffer_pos as usize; + debug_assert!(BLOCK_SIZE > pos); + + let mut counter = self.counter; + // xor with leftover bytes from the last call if any + if pos != 0 { + if data.len() < BLOCK_SIZE - pos { + let n = pos + data.len(); + xor(data, &self.buffer[pos..n]); + self.buffer_pos = n as u8; + return Ok(()); + } else { + let (l, r) = data.split_at_mut(BLOCK_SIZE - pos); + data = r; + xor(l, &self.buffer[pos..]); + counter += 1; + } + } + + let mut chunks = data.chunks_exact_mut(BLOCK_SIZE); + for chunk in &mut chunks { + self.block.apply_keystream(counter, chunk); + counter += 1; + } + + let rem = chunks.into_remainder(); + self.buffer_pos = rem.len() as u8; + self.counter = counter; + if !rem.is_empty() { + self.block.counter_setup(counter); + self.block.generate(&mut self.buffer); + xor(rem, &self.buffer[..rem.len()]); + } + + Ok(()) + } +} + +impl StreamCipherSeek for Salsa { + fn try_current_pos(&self) -> Result { + T::from_block_byte(self.counter, self.buffer_pos, BLOCK_SIZE as u8) + } + + fn try_seek(&mut self, pos: T) -> Result<(), LoopError> { + let res = pos.to_block_byte(BLOCK_SIZE as u8)?; + self.counter = res.0; + self.buffer_pos = res.1; + if self.buffer_pos != 0 { + self.block.counter_setup(self.counter); + self.block.generate(&mut self.buffer); + } + Ok(()) + } +} + +impl Salsa { + fn check_data_len(&self, data: &[u8]) -> Result<(), LoopError> { + let leftover_bytes = BLOCK_SIZE - self.buffer_pos as usize; + if data.len() < leftover_bytes { + return Ok(()); + } + let blocks = 1 + (data.len() - leftover_bytes) / BLOCK_SIZE; + self.counter + .checked_add(blocks as u64) + .ok_or(LoopError) + .map(|_| ()) + } +} + +impl fmt::Debug for Salsa { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "Cipher {{ .. }}") + } +} + +#[inline(always)] +fn xor(buf: &mut [u8], key: &[u8]) { + debug_assert_eq!(buf.len(), key.len()); + for (a, b) in buf.iter_mut().zip(key) { + *a ^= *b; + } +} +*/ diff --git a/doc/rust-tutorial/code/salsa20/src/xsalsa.rs b/doc/rust-tutorial/code/salsa20/src/xsalsa.rs new file mode 100644 index 0000000000..fc442895cc --- /dev/null +++ b/doc/rust-tutorial/code/salsa20/src/xsalsa.rs @@ -0,0 +1,123 @@ +//! XSalsa20 is an extended nonce variant of Salsa20 + +use crate::{core::quarter_round, Key, Nonce, Salsa20, CONSTANTS}; +use cipher::{ + consts::{U16, U24, U32}, + errors::{LoopError, OverflowError}, + generic_array::GenericArray, + NewCipher, SeekNum, StreamCipher, StreamCipherSeek, +}; +use core::convert::TryInto; + +/// EXtended Salsa20 nonce (192-bit/24-byte) +#[cfg_attr(docsrs, doc(cfg(feature = "xsalsa20")))] +pub type XNonce = cipher::Nonce; + +/// XSalsa20 is a Salsa20 variant with an extended 192-bit (24-byte) nonce. +/// +/// Based on the paper "Extending the Salsa20 Nonce": +/// +/// +/// +/// The `xsalsa20` Cargo feature must be enabled in order to use this +/// (which it is by default). +#[cfg_attr(docsrs, doc(cfg(feature = "xsalsa20")))] +pub struct XSalsa20(Salsa20); + +impl NewCipher for XSalsa20 { + /// Key size in bytes + type KeySize = U32; + + /// Nonce size in bytes + type NonceSize = U24; + + #[allow(unused_mut, clippy::let_and_return)] + fn new(key: &Key, nonce: &XNonce) -> Self { + let mut subkey = hsalsa20(key, nonce[..16].as_ref().into()); + let mut padded_nonce = Nonce::default(); + padded_nonce.copy_from_slice(&nonce[16..]); + + let mut result = XSalsa20(Salsa20::new(&subkey, &padded_nonce)); + + #[cfg(feature = "zeroize")] + { + use zeroize::Zeroize; + subkey.as_mut_slice().zeroize(); + } + + result + } +} + +impl StreamCipher for XSalsa20 { + fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> { + self.0.try_apply_keystream(data) + } +} + +impl StreamCipherSeek for XSalsa20 { + fn try_current_pos(&self) -> Result { + self.0.try_current_pos() + } + + fn try_seek(&mut self, pos: T) -> Result<(), LoopError> { + self.0.try_seek(pos) + } +} + +/// The HSalsa20 function defined in the paper "Extending the Salsa20 nonce" +/// +/// +/// +/// HSalsa20 takes 512-bits of input: +/// +/// - Constants (`u32` x 4) +/// - Key (`u32` x 8) +/// - Nonce (`u32` x 4) +/// +/// It produces 256-bits of output suitable for use as a Salsa20 key +#[cfg_attr(docsrs, doc(cfg(feature = "hsalsa20")))] +pub fn hsalsa20(key: &Key, input: &GenericArray) -> GenericArray { + let mut state = [0u32; 16]; + + state[0] = CONSTANTS[0]; + state[5] = CONSTANTS[1]; + state[10] = CONSTANTS[2]; + state[15] = CONSTANTS[3]; + + for (i, chunk) in key.chunks(4).take(4).enumerate() { + state[1 + i] = u32::from_le_bytes(chunk.try_into().unwrap()); + } + + for (i, chunk) in key.chunks(4).skip(4).enumerate() { + state[11 + i] = u32::from_le_bytes(chunk.try_into().unwrap()); + } + + for (i, chunk) in input.chunks(4).enumerate() { + state[6 + i] = u32::from_le_bytes(chunk.try_into().unwrap()); + } + + // 20 rounds consisting of 10 column rounds and 10 diagonal rounds + for _ in 0..10 { + // column rounds + quarter_round(0, 4, 8, 12, &mut state); + quarter_round(5, 9, 13, 1, &mut state); + quarter_round(10, 14, 2, 6, &mut state); + quarter_round(15, 3, 7, 11, &mut state); + + // diagonal rounds + quarter_round(0, 1, 2, 3, &mut state); + quarter_round(5, 6, 7, 4, &mut state); + quarter_round(10, 11, 8, 9, &mut state); + quarter_round(15, 12, 13, 14, &mut state); + } + + let mut output = GenericArray::default(); + let key_idx: [usize; 8] = [0, 5, 10, 15, 6, 7, 8, 9]; + + for (i, chunk) in output.chunks_mut(4).enumerate() { + chunk.copy_from_slice(&state[key_idx[i]].to_le_bytes()); + } + + output +} diff --git a/doc/rust-tutorial/code/saw-basics.linked-mir.json b/doc/rust-tutorial/code/saw-basics.linked-mir.json new file mode 100644 index 0000000000..e43e717abf --- /dev/null +++ b/doc/rust-tutorial/code/saw-basics.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u8"}},"pos":"saw-basics.rs:6:8: 6:9","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u8"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::b3c48eb6a81cb2e8"},"kind":"Constant"},"kind":"Call","pos":"saw-basics.rs:6:5: 6:10"}},"blockid":"bb0"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"saw-basics.rs:7:2: 7:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u8"}]},"name":"saw_basics/f77ebf43::id_u8","return_ty":"ty::u8","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}},"pos":"saw-basics.rs:2:5: 2:6","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u8"}},"kind":"Move"}}}],"terminator":{"kind":"Return","pos":"saw-basics.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u8"}]},"name":"saw_basics/f77ebf43::id::_instaddce72e1232152c[0]","return_ty":"ty::u8","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"saw_basics/f77ebf43::id_u8","kind":"Item","substs":[]},"name":"saw_basics/f77ebf43::id_u8"},{"inst":{"def_id":"saw_basics/f77ebf43::id","kind":"Item","substs":["ty::u8"]},"name":"saw_basics/f77ebf43::id::_instaddce72e1232152c[0]"}],"tys":[{"name":"ty::u8","ty":{"kind":"Uint","uintkind":{"kind":"U8"}}},{"name":"ty::FnDef::b3c48eb6a81cb2e8","ty":{"defid":"saw_basics/f77ebf43::id::_instaddce72e1232152c[0]","kind":"FnDef"}}],"roots":["saw_basics/f77ebf43::id_u8"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/saw-basics.rs b/doc/rust-tutorial/code/saw-basics.rs new file mode 100644 index 0000000000..31df101083 --- /dev/null +++ b/doc/rust-tutorial/code/saw-basics.rs @@ -0,0 +1,7 @@ +pub fn id(x: A) -> A { + x +} + +pub fn id_u8(x: u8) -> u8 { + id(x) +} diff --git a/doc/rust-tutorial/code/saw-basics.saw b/doc/rust-tutorial/code/saw-basics.saw new file mode 100644 index 0000000000..d1d4f61aa5 --- /dev/null +++ b/doc/rust-tutorial/code/saw-basics.saw @@ -0,0 +1,11 @@ +enable_experimental; + +let id_u8_spec = do { + x <- mir_fresh_var "x" mir_u8; + mir_execute_func [mir_term x]; + mir_return (mir_term x); +}; + +m <- mir_load_module "saw-basics.linked-mir.json"; + +mir_verify m "saw_basics::id_u8" [] false id_u8_spec z3; diff --git a/doc/rust-tutorial/code/slices.linked-mir.json b/doc/rust-tutorial/code/slices.linked-mir.json new file mode 100644 index 0000000000..055f74184c --- /dev/null +++ b/doc/rust-tutorial/code/slices.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}},"pos":"slices.rs:2:7: 2:8","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"usize","size":8,"val":"0"},"ty":"ty::usize"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"pos":"slices.rs:2:5: 2:9","rhs":{"kind":"Len","lv":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}},"pos":"slices.rs:2:5: 2:9","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}},"kind":"Copy"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"kind":"Copy"},"kind":"BinaryOp","op":{"kind":"Lt"}}}],"terminator":{"cleanup":null,"cond":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"}},"kind":"Move"},"expected":true,"kind":"Assert","msg":"index out of bounds: the length is move _4 but the index is _3","pos":"slices.rs:2:5: 2:9","target":"bb1"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"pos":"slices.rs:2:5: 2:9","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"},{"kind":"Index","op":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"}}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_7","ty":"ty::usize"}},"pos":"slices.rs:2:25: 2:26","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"usize","size":8,"val":"1"},"ty":"ty::usize"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},"pos":"slices.rs:2:23: 2:27","rhs":{"kind":"Len","lv":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}},"pos":"slices.rs:2:23: 2:27","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_7","ty":"ty::usize"}},"kind":"Copy"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},"kind":"Copy"},"kind":"BinaryOp","op":{"kind":"Lt"}}}],"terminator":{"cleanup":null,"cond":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}},"kind":"Move"},"expected":true,"kind":"Assert","msg":"index out of bounds: the length is move _8 but the index is _7","pos":"slices.rs:2:23: 2:27","target":"bb2"}},"blockid":"bb1"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}},"pos":"slices.rs:2:23: 2:27","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"},{"kind":"Index","op":{"is_zst":false,"mut":{"kind":"Not"},"name":"_7","ty":"ty::usize"}}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"bb3"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::f55acdef755f1aaa"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:2:5: 2:28"}},"blockid":"bb2"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"slices.rs:3:2: 3:2"}},"blockid":"bb3"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::bool"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_7","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}]},"name":"slices/6276e58b::sum_of_prefix","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::cef0e4ed0a308aa2"}},"pos":"slices.rs:6:14: 6:20","rhs":{"akind":{"kind":"Array","ty":"ty::u32"},"kind":"Aggregate","ops":[{"data":{"rendered":{"kind":"uint","size":4,"val":"1"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"2"},"ty":"ty::u32"},"kind":"Constant"}]}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::80c3ec1c9ff088a1"}},"pos":"slices.rs:7:15: 7:17","rhs":{"borrowkind":"Shared","kind":"Ref","refvar":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::cef0e4ed0a308aa2"}},"region":"unimplement"}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::80c3ec1c9ff088a1"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"bb1"],"from_hir_call":false,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::a0fec82b15861ab8"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:7:15: 7:21"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}},"pos":"slices.rs:7:14: 7:21","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::Ref::2829f685526f8473"}},"pos":"slices.rs:8:30: 8:32","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_6","ty":"ty::u32"}},"bb2"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::b183ff91e8e7e945"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:8:16: 8:33"}},"blockid":"bb1"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_8","ty":"ty::Array::a60250c8af2ca6f4"}},"pos":"slices.rs:10:14: 10:29","rhs":{"akind":{"kind":"Array","ty":"ty::u32"},"kind":"Aggregate","ops":[{"data":{"rendered":{"kind":"uint","size":4,"val":"1"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"2"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"3"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"4"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"5"},"ty":"ty::u32"},"kind":"Constant"}]}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::Ref::511dbdc7522bceba"}},"pos":"slices.rs:11:15: 11:17","rhs":{"borrowkind":"Shared","kind":"Ref","refvar":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_8","ty":"ty::Array::a60250c8af2ca6f4"}},"region":"unimplement"}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::Ref::511dbdc7522bceba"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_10","ty":"ty::Ref::2829f685526f8473"}},"bb3"],"from_hir_call":false,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::10ead23d3baa817d"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:11:15: 11:21"}},"blockid":"bb2"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_9","ty":"ty::Ref::2829f685526f8473"}},"pos":"slices.rs:11:14: 11:21","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_10","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::Ref::2829f685526f8473"}},"pos":"slices.rs:12:30: 12:32","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_9","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_13","ty":"ty::u32"}},"bb4"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::b183ff91e8e7e945"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:12:16: 12:33"}},"blockid":"bb3"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_15","ty":"ty::Array::a60250c8af2ca6f4"}},"pos":"slices.rs:14:14: 14:29","rhs":{"akind":{"kind":"Array","ty":"ty::u32"},"kind":"Aggregate","ops":[{"data":{"rendered":{"kind":"uint","size":4,"val":"1"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"2"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"3"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"4"},"ty":"ty::u32"},"kind":"Constant"},{"data":{"rendered":{"kind":"uint","size":4,"val":"5"},"ty":"ty::u32"},"kind":"Constant"}]}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Ref::511dbdc7522bceba"}},"pos":"slices.rs:15:15: 15:17","rhs":{"borrowkind":"Shared","kind":"Ref","refvar":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_15","ty":"ty::Array::a60250c8af2ca6f4"}},"region":"unimplement"}},{"kind":"Deinit","pos":"slices.rs:15:18: 15:22"},{"kind":"Assign","lhs":{"data":[{"field":0,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::Adt::a72d82d5b19bcba3"}},"pos":"slices.rs:15:18: 15:22","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"usize","size":8,"val":"0"},"ty":"ty::usize"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::Adt::a72d82d5b19bcba3"}},"pos":"slices.rs:15:18: 15:22","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"usize","size":8,"val":"2"},"ty":"ty::usize"},"kind":"Constant"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Ref::511dbdc7522bceba"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::Ref::2829f685526f8473"}},"bb5"],"from_hir_call":false,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::e9b516da07bc653d"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:15:15: 15:23"}},"blockid":"bb4"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_16","ty":"ty::Ref::2829f685526f8473"}},"pos":"slices.rs:15:14: 15:23","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::Ref::2829f685526f8473"}},"pos":"slices.rs:16:30: 16:32","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_16","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_20","ty":"ty::u32"}},"bb6"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::b183ff91e8e7e945"},"kind":"Constant"},"kind":"Call","pos":"slices.rs:16:16: 16:33"}},"blockid":"bb5"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"slices.rs:17:2: 17:2"}},"blockid":"bb6"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Array::cef0e4ed0a308aa2"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::80c3ec1c9ff088a1"},{"is_zst":true,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Adt::b662b166ba926eb4"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_6","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_8","ty":"ty::Array::a60250c8af2ca6f4"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_9","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_10","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::Ref::511dbdc7522bceba"},{"is_zst":true,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Adt::b662b166ba926eb4"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_13","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_15","ty":"ty::Array::a60250c8af2ca6f4"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_16","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Ref::511dbdc7522bceba"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_20","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::Ref::2829f685526f8473"}]},"name":"slices/6276e58b::sum_of_prefix_examples","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::511dbdc7522bceba"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::b662b166ba926eb4"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","slvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::511dbdc7522bceba"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","rhs":{"kind":"Cast","op":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},"kind":"Move"},"ty":"ty::Ref::2829f685526f8473","type":{"kind":"Pointer(Unsize)"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:25: 358:26","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:36: 358:41","slvar":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:36: 358:41","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::0239e0053834f2bf"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:9: 358:42"}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:41: 358:42","sdvar":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:41: 358:42","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:359:5: 359:6","sdvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:359:6: 359:6"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"},{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}]},"name":"core/73237d41::array::{impl#16}::index::_instd846e681ef826fa7[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::80c3ec1c9ff088a1"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::b662b166ba926eb4"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","slvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::80c3ec1c9ff088a1"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::80c3ec1c9ff088a1"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::80c3ec1c9ff088a1"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","rhs":{"kind":"Cast","op":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::80c3ec1c9ff088a1"}},"kind":"Move"},"ty":"ty::Ref::2829f685526f8473","type":{"kind":"Pointer(Unsize)"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:25: 358:26","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::80c3ec1c9ff088a1"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:36: 358:41","slvar":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:36: 358:41","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::0239e0053834f2bf"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:9: 358:42"}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:41: 358:42","sdvar":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:41: 358:42","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:359:5: 359:6","sdvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:359:6: 359:6"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::80c3ec1c9ff088a1"},{"is_zst":true,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::b662b166ba926eb4"}]},"name":"core/73237d41::array::{impl#16}::index::_inste0f162b79baa1a10[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:38: 1162:42 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:38: 1162:42 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:44: 1162:47 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:44: 1162:47 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:13: 1162:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"kind":"Move"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},"kind":"Move"},"kind":"BinaryOp","op":{"kind":"Add"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:47: 1162:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1162:47: 1162:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/uint_macros.rs:1163:10: 1163:10 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/num/mod.rs:921:5: 922:101"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::u32"}]},"name":"core/73237d41::num::{impl#9}::wrapping_add","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::511dbdc7522bceba"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::a72d82d5b19bcba3"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","slvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::511dbdc7522bceba"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:26","rhs":{"kind":"Cast","op":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},"kind":"Move"},"ty":"ty::Ref::2829f685526f8473","type":{"kind":"Pointer(Unsize)"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:25: 358:26","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:22: 358:34","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:36: 358:41","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::a72d82d5b19bcba3"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::a72d82d5b19bcba3"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:36: 358:41","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::03fdec9cd6ad1d17"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:9: 358:42"}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:41: 358:42","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::a72d82d5b19bcba3"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:358:41: 358:42","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:359:5: 359:6","sdvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/array/mod.rs:359:6: 359:6"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_4","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::Ref::511dbdc7522bceba"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::Adt::a72d82d5b19bcba3"}]},"name":"core/73237d41::array::{impl#16}::index::_inst963235467e6b6f44[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::b662b166ba926eb4"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:9: 18:14","slvar":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::b662b166ba926eb4"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::b662b166ba926eb4"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:9: 18:14","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:21: 18:25","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:21: 18:25","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::b662b166ba926eb4"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::98a4e8040f6908ed"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:9: 18:26"}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:25: 18:26","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:25: 18:26","sdvar":{"is_zst":true,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::b662b166ba926eb4"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:19:6: 19:6"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"},{"is_zst":true,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::b662b166ba926eb4"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}]},"name":"core/73237d41::slice::index::{impl#0}::index::_inst7c0dc32325c43fc1[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::a72d82d5b19bcba3"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:9: 18:14","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:9: 18:14","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:21: 18:25","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:21: 18:25","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::f092ac821bbad40d"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:9: 18:26"}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:25: 18:26","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:18:25: 18:26","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:19:6: 19:6"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::Ref::2829f685526f8473"}]},"name":"core/73237d41::slice::index::{impl#0}::index::_instc3853b5b165fc57c[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":true,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::b662b166ba926eb4"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:538:9: 538:14","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:539:6: 539:6"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}]},"name":"core/73237d41::slice::index::{impl#7}::index::_instc5e93708b8ca6e2a[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::bool"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:22","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:22","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:25: 406:33","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:25: 406:33","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::bool"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}},"kind":"Move"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::usize"}},"kind":"Move"},"kind":"BinaryOp","op":{"kind":"Gt"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:32: 406:33","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:32: 406:33","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"}}],"terminator":{"discr":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::bool"}},"kind":"Move"},"discr_span":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33","kind":"SwitchInt","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:406:12: 406:33","switch_ty":"ty::bool","targets":["bb2","bb1"],"values":["0"]}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:407:13: 407:57","slvar":{"is_zst":true,"mut":{"kind":"Not"},"name":"_6","ty":"ty::Never::7199a9b06188843c"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:407:36: 407:46","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:407:36: 407:46","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:407:48: 407:56","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:407:48: 407:56","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},"kind":"Move"}],"cleanup":null,"destination":null,"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::f751a3d22ca1fd3b"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:407:13: 407:57"}},"blockid":"bb1"},{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:27","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:27","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:30: 408:41","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::usize"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:30: 408:41","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Ref::2829f685526f8473"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:30: 408:41","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:30: 408:41","rhs":{"kind":"Len","lv":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Ref::2829f685526f8473"}}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:40: 408:41","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Ref::2829f685526f8473"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},"kind":"Move"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::usize"}},"kind":"Move"},"kind":"BinaryOp","op":{"kind":"Gt"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:40: 408:41","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:40: 408:41","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}}],"terminator":{"discr":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}},"kind":"Move"},"discr_span":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41","kind":"SwitchInt","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:408:19: 408:41","switch_ty":"ty::bool","targets":["bb4","bb3"],"values":["0"]}},"blockid":"bb2"},{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:13: 409:60","slvar":{"is_zst":true,"mut":{"kind":"Not"},"name":"_13","ty":"ty::Never::7199a9b06188843c"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:38: 409:46","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:38: 409:46","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:48: 409:59","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::usize"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:48: 409:59","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::Ref::2829f685526f8473"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:48: 409:59","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:48: 409:59","rhs":{"kind":"Len","lv":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::Ref::2829f685526f8473"}}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:58: 409:59","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::Ref::2829f685526f8473"}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::usize"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::usize"}},"kind":"Move"}],"cleanup":null,"destination":null,"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::293b7d0b334e36b5"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:409:13: 409:60"}},"blockid":"bb3"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:410:9: 410:10","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:410:9: 410:10","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::bool"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:20: 412:45","slvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:20: 412:24","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Adt::a72d82d5b19bcba3"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Adt::a72d82d5b19bcba3"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:20: 412:24","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:39: 412:44","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:39: 412:44","rhs":{"kind":"AddressOf","mutbl":{"kind":"Not"},"place":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::Ref::2829f685526f8473"}}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"bb5"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::a1fb0a669f0985bf"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:20: 412:45"}},"blockid":"bb4"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:44: 412:45","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:44: 412:45","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Adt::a72d82d5b19bcba3"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:412:18: 412:45","rhs":{"borrowkind":"Shared","kind":"Ref","refvar":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"region":"unimplement"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:413:5: 413:6","sdvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::RawPtr::97f6f552ec6f43bc"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:413:6: 413:6"}},"blockid":"bb5"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::bool"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::usize"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_6","ty":"ty::Never::7199a9b06188843c"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::bool"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::Ref::2829f685526f8473"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_13","ty":"ty::Never::7199a9b06188843c"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::Ref::2829f685526f8473"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_17","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::97f6f552ec6f43bc"}]},"name":"core/73237d41::slice::index::{impl#4}::index::_instc5e93708b8ca6e2a[0]","return_ty":"ty::Ref::2829f685526f8473","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::RawPtr::97f6f552ec6f43bc"}],"body":{"blocks":[{"block":{"data":[{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:374:13: 374:17","slvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:39: 386:69","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:39: 386:53","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:39: 386:44","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:39: 386:44","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_2","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:1650:9: 1650:13 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:45: 386:53","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:1650:9: 1650:13 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:45: 386:53","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:1650:9: 1650:25 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:45: 386:53","rhs":{"kind":"Cast","op":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"kind":"Move"},"ty":"ty::RawPtr::1f2b1eadb40cd255","type":{"kind":"PtrToPtr"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:1650:24: 1650:25 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:45: 386:53","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:52: 386:53","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::RawPtr::97f6f552ec6f43bc"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:58: 386:68","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:58: 386:68","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:18: 932:22 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:18: 932:22 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:30: 932:44 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_17","ty":"ty::isize"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:30: 932:35 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:30: 932:35 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_17","ty":"ty::isize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:30: 932:44 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","rhs":{"kind":"Cast","op":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::usize"}},"kind":"Move"},"ty":"ty::isize","type":{"kind":"IntToInt"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:43: 932:44 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::usize"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:37: 473:41 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:37: 473:41 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:43: 473:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_20","ty":"ty::isize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_20","ty":"ty::isize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:43: 473:48 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_17","ty":"ty::isize"}},"kind":"Copy"}}}],"terminator":{"args":[{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"kind":"Move"},{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_20","ty":"ty::isize"}},"kind":"Move"}],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::c699298b9e73f83a"},"kind":"Constant"},"kind":"Call","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:18: 473:49 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69"}},"blockid":"bb0"},{"block":{"data":[{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:48: 473:49 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_20","ty":"ty::isize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:473:48: 473:49 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:44: 932:45 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_17","ty":"ty::isize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:932:44: 932:45 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:54: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:68: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:68: 386:69","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:71: 386:92","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:71: 386:79","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:71: 386:79","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:82: 386:92","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:82: 386:92","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::a72d82d5b19bcba3"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:71: 386:92","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::usize"}},"kind":"Move"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},"kind":"Move"},"kind":"BinaryOp","op":{"kind":"Sub"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:91: 386:92","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:91: 386:92","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::usize"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:20: 734:31 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::RawPtr::ac3bacfc73b0b976"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:20: 734:24 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_22","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_22","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:20: 734:24 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:61:9: 61:13 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_24","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_24","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:61:9: 61:13 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_22","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::RawPtr::ac3bacfc73b0b976"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:61:9: 61:18 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Cast","op":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_24","ty":"ty::RawPtr::1f2b1eadb40cd255"}},"kind":"Move"},"ty":"ty::RawPtr::ac3bacfc73b0b976","type":{"kind":"PtrToPtr"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/const_ptr.rs:61:17: 61:18 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_24","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:30: 734:31 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_22","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:33: 734:36 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_23","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_23","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:33: 734:36 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:14: 118:78 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_25","ty":"ty::Adt::1f7c550e96e53aa8"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:36: 118:76 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_26","ty":"ty::Adt::c4a120efbbc79aa2"}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:52: 118:64 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_27","ty":"ty::RawPtr::ac3bacfc73b0b976"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_27","ty":"ty::RawPtr::ac3bacfc73b0b976"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:52: 118:64 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::RawPtr::ac3bacfc73b0b976"}},"kind":"Copy"}}},{"kind":"StorageLive","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:66: 118:74 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","slvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_28","ty":"ty::usize"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_28","ty":"ty::usize"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:66: 118:74 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_23","ty":"ty::usize"}},"kind":"Copy"}}},{"kind":"Deinit","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:36: 118:76 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93"},{"kind":"Assign","lhs":{"data":[{"field":0,"kind":"Field","ty":"ty::RawPtr::ac3bacfc73b0b976"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_26","ty":"ty::Adt::c4a120efbbc79aa2"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:36: 118:76 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_27","ty":"ty::RawPtr::ac3bacfc73b0b976"}},"kind":"Move"}}},{"kind":"Assign","lhs":{"data":[{"field":1,"kind":"Field","ty":"ty::usize"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_26","ty":"ty::Adt::c4a120efbbc79aa2"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:36: 118:76 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_28","ty":"ty::usize"}},"kind":"Move"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:75: 118:76 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_28","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:75: 118:76 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_27","ty":"ty::RawPtr::ac3bacfc73b0b976"}},{"kind":"Deinit","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:14: 118:78 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93"},{"kind":"Assign","lhs":{"data":[{"field":2,"kind":"Field","ty":"ty::Adt::c4a120efbbc79aa2"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_25","ty":"ty::Adt::1f7c550e96e53aa8"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:14: 118:78 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_26","ty":"ty::Adt::c4a120efbbc79aa2"}},"kind":"Move"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:77: 118:78 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_26","ty":"ty::Adt::c4a120efbbc79aa2"}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::RawPtr::97f6f552ec6f43bc"}},"pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:118:14: 118:88 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::RawPtr::97f6f552ec6f43bc"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_25","ty":"ty::Adt::1f7c550e96e53aa8"}},"kind":"Copy"}}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/metadata.rs:119:1: 119:2 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_25","ty":"ty::Adt::1f7c550e96e53aa8"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:36: 734:37 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_23","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/ptr/mod.rs:734:36: 734:37 !/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:13: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::RawPtr::ac3bacfc73b0b976"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:92: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:386:92: 386:93","sdvar":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::RawPtr::1f2b1eadb40cd255"}},{"kind":"StorageDead","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:388:5: 388:6","sdvar":{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"}}],"terminator":{"kind":"Return","pos":"/rustc/5e37043d63bfe2f3be8fa5a05b07d6c0dad5775d/library/core/src/slice/index.rs:388:6: 388:6"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_3","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_4","ty":"ty::RawPtr::1f2b1eadb40cd255"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_5","ty":"ty::RawPtr::1f2b1eadb40cd255"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_6","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_7","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_8","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_9","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_10","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_11","ty":"ty::Adt::a72d82d5b19bcba3"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_12","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_13","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_14","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_15","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_16","ty":"ty::RawPtr::1f2b1eadb40cd255"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_17","ty":"ty::isize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_18","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_19","ty":"ty::RawPtr::1f2b1eadb40cd255"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_20","ty":"ty::isize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_21","ty":"ty::RawPtr::ac3bacfc73b0b976"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_22","ty":"ty::RawPtr::1f2b1eadb40cd255"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_23","ty":"ty::usize"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_24","ty":"ty::RawPtr::1f2b1eadb40cd255"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_25","ty":"ty::Adt::1f7c550e96e53aa8"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_26","ty":"ty::Adt::c4a120efbbc79aa2"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_27","ty":"ty::RawPtr::ac3bacfc73b0b976"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_28","ty":"ty::usize"}]},"name":"core/73237d41::slice::index::{impl#4}::get_unchecked::_instc5e93708b8ca6e2a[0]","return_ty":"ty::RawPtr::97f6f552ec6f43bc","spread_arg":null}],"adts":[{"kind":{"kind":"Struct"},"name":"core/73237d41::ops::range::Range::_adtaffa7a8b1157c078[0]","orig_def_id":"core/73237d41::ops::range::Range","orig_substs":["ty::usize"],"repr_transparent":false,"size":16,"variants":[{"ctor_kind":null,"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"core/73237d41::ops::range::Range::start","ty":"ty::usize"},{"name":"core/73237d41::ops::range::Range::end","ty":"ty::usize"}],"inhabited":true,"name":"core/73237d41::ops::range::Range"}]},{"kind":{"kind":"Struct"},"name":"core/73237d41::ops::range::RangeFull::_adtb7803c2264daf0ec[0]","orig_def_id":"core/73237d41::ops::range::RangeFull","orig_substs":[],"repr_transparent":false,"size":0,"variants":[{"ctor_kind":{"kind":"Const"},"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[],"inhabited":true,"name":"core/73237d41::ops::range::RangeFull"}]},{"kind":{"kind":"Union"},"name":"core/73237d41::ptr::metadata::PtrRepr::_adt2ed9deda136ace65[0]","orig_def_id":"core/73237d41::ptr::metadata::PtrRepr","orig_substs":["ty::Slice::f7eb0deb10702a2f"],"repr_transparent":false,"size":16,"variants":[{"ctor_kind":null,"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"core/73237d41::ptr::metadata::PtrRepr::const_ptr","ty":"ty::RawPtr::97f6f552ec6f43bc"},{"name":"core/73237d41::ptr::metadata::PtrRepr::mut_ptr","ty":"ty::RawPtr::1aaf1d3d9e30a4c2"},{"name":"core/73237d41::ptr::metadata::PtrRepr::components","ty":"ty::Adt::c4a120efbbc79aa2"}],"inhabited":true,"name":"core/73237d41::ptr::metadata::PtrRepr"}]},{"kind":{"kind":"Struct"},"name":"core/73237d41::ptr::metadata::PtrComponents::_adt2ed9deda136ace65[0]","orig_def_id":"core/73237d41::ptr::metadata::PtrComponents","orig_substs":["ty::Slice::f7eb0deb10702a2f"],"repr_transparent":false,"size":16,"variants":[{"ctor_kind":null,"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"core/73237d41::ptr::metadata::PtrComponents::data_address","ty":"ty::RawPtr::ac3bacfc73b0b976"},{"name":"core/73237d41::ptr::metadata::PtrComponents::metadata","ty":"ty::usize"}],"inhabited":true,"name":"core/73237d41::ptr::metadata::PtrComponents"}]}],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"slices/6276e58b::sum_of_prefix","kind":"Item","substs":[]},"name":"slices/6276e58b::sum_of_prefix"},{"inst":{"def_id":"slices/6276e58b::sum_of_prefix_examples","kind":"Item","substs":[]},"name":"slices/6276e58b::sum_of_prefix_examples"},{"inst":{"def_id":"core/73237d41::array::{impl#16}::index","kind":"Item","substs":["ty::u32","ty::Adt::b662b166ba926eb4","nonty::Const"]},"name":"core/73237d41::array::{impl#16}::index::_instd846e681ef826fa7[0]"},{"inst":{"def_id":"core/73237d41::array::{impl#16}::index","kind":"Item","substs":["ty::u32","ty::Adt::b662b166ba926eb4","nonty::Const"]},"name":"core/73237d41::array::{impl#16}::index::_inste0f162b79baa1a10[0]"},{"inst":{"def_id":"core/73237d41::num::{impl#9}::wrapping_add","kind":"Item","substs":[]},"name":"core/73237d41::num::{impl#9}::wrapping_add"},{"inst":{"def_id":"core/73237d41::array::{impl#16}::index","kind":"Item","substs":["ty::u32","ty::Adt::a72d82d5b19bcba3","nonty::Const"]},"name":"core/73237d41::array::{impl#16}::index::_inst963235467e6b6f44[0]"},{"inst":{"def_id":"core/73237d41::slice::index::{impl#0}::index","kind":"Item","substs":["ty::u32","ty::Adt::b662b166ba926eb4"]},"name":"core/73237d41::slice::index::{impl#0}::index::_inst7c0dc32325c43fc1[0]"},{"inst":{"def_id":"core/73237d41::slice::index::{impl#0}::index","kind":"Item","substs":["ty::u32","ty::Adt::a72d82d5b19bcba3"]},"name":"core/73237d41::slice::index::{impl#0}::index::_instc3853b5b165fc57c[0]"},{"inst":{"def_id":"core/73237d41::slice::index::{impl#7}::index","kind":"Item","substs":["ty::u32"]},"name":"core/73237d41::slice::index::{impl#7}::index::_instc5e93708b8ca6e2a[0]"},{"inst":{"def_id":"core/73237d41::slice::index::{impl#4}::index","kind":"Item","substs":["ty::u32"]},"name":"core/73237d41::slice::index::{impl#4}::index::_instc5e93708b8ca6e2a[0]"},{"inst":{"def_id":"core/73237d41::slice::index::slice_index_order_fail","kind":"Item","substs":[]},"name":"core/73237d41::slice::index::slice_index_order_fail"},{"inst":{"def_id":"core/73237d41::slice::index::slice_end_index_len_fail","kind":"Item","substs":[]},"name":"core/73237d41::slice::index::slice_end_index_len_fail"},{"inst":{"def_id":"core/73237d41::slice::index::{impl#4}::get_unchecked","kind":"Item","substs":["ty::u32"]},"name":"core/73237d41::slice::index::{impl#4}::get_unchecked::_instc5e93708b8ca6e2a[0]"},{"inst":{"def_id":"core/73237d41::intrinsics::{extern#0}::offset","kind":"Intrinsic","substs":["ty::u32"]},"name":"core/73237d41::intrinsics::{extern#0}::offset::_instc5e93708b8ca6e2a[0]"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::Slice::f7eb0deb10702a2f","ty":{"kind":"Slice","ty":"ty::u32"}},{"name":"ty::Ref::2829f685526f8473","ty":{"kind":"Ref","mutability":{"kind":"Not"},"ty":"ty::Slice::f7eb0deb10702a2f"}},{"name":"ty::usize","ty":{"kind":"Uint","uintkind":{"kind":"Usize"}}},{"name":"ty::bool","ty":{"kind":"Bool"}},{"name":"ty::FnDef::f55acdef755f1aaa","ty":{"defid":"core/73237d41::num::{impl#9}::wrapping_add","kind":"FnDef"}},{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}},{"name":"ty::Array::cef0e4ed0a308aa2","ty":{"kind":"Array","size":{"rendered":{"kind":"usize","size":8,"val":"2"},"ty":"ty::usize"},"ty":"ty::u32"}},{"name":"ty::Ref::80c3ec1c9ff088a1","ty":{"kind":"Ref","mutability":{"kind":"Not"},"ty":"ty::Array::cef0e4ed0a308aa2"}},{"name":"ty::Adt::b662b166ba926eb4","ty":{"kind":"Adt","name":"core/73237d41::ops::range::RangeFull::_adtb7803c2264daf0ec[0]","orig_def_id":"core/73237d41::ops::range::RangeFull","substs":[]}},{"name":"ty::Array::a60250c8af2ca6f4","ty":{"kind":"Array","size":{"rendered":{"kind":"usize","size":8,"val":"5"},"ty":"ty::usize"},"ty":"ty::u32"}},{"name":"ty::Ref::511dbdc7522bceba","ty":{"kind":"Ref","mutability":{"kind":"Not"},"ty":"ty::Array::a60250c8af2ca6f4"}},{"name":"ty::Adt::a72d82d5b19bcba3","ty":{"kind":"Adt","name":"core/73237d41::ops::range::Range::_adtaffa7a8b1157c078[0]","orig_def_id":"core/73237d41::ops::range::Range","substs":["ty::usize"]}},{"name":"ty::FnDef::a0fec82b15861ab8","ty":{"defid":"core/73237d41::array::{impl#16}::index::_inste0f162b79baa1a10[0]","kind":"FnDef"}},{"name":"ty::FnDef::b183ff91e8e7e945","ty":{"defid":"slices/6276e58b::sum_of_prefix","kind":"FnDef"}},{"name":"ty::FnDef::10ead23d3baa817d","ty":{"defid":"core/73237d41::array::{impl#16}::index::_instd846e681ef826fa7[0]","kind":"FnDef"}},{"name":"ty::FnDef::e9b516da07bc653d","ty":{"defid":"core/73237d41::array::{impl#16}::index::_inst963235467e6b6f44[0]","kind":"FnDef"}},{"name":"ty::FnDef::0239e0053834f2bf","ty":{"defid":"core/73237d41::slice::index::{impl#0}::index::_inst7c0dc32325c43fc1[0]","kind":"FnDef"}},{"name":"ty::FnDef::03fdec9cd6ad1d17","ty":{"defid":"core/73237d41::slice::index::{impl#0}::index::_instc3853b5b165fc57c[0]","kind":"FnDef"}},{"name":"ty::FnDef::98a4e8040f6908ed","ty":{"defid":"core/73237d41::slice::index::{impl#7}::index::_instc5e93708b8ca6e2a[0]","kind":"FnDef"}},{"name":"ty::FnDef::f092ac821bbad40d","ty":{"defid":"core/73237d41::slice::index::{impl#4}::index::_instc5e93708b8ca6e2a[0]","kind":"FnDef"}},{"name":"ty::Never::7199a9b06188843c","ty":{"kind":"Never"}},{"name":"ty::RawPtr::97f6f552ec6f43bc","ty":{"kind":"RawPtr","mutability":{"kind":"Not"},"ty":"ty::Slice::f7eb0deb10702a2f"}},{"name":"ty::FnDef::f751a3d22ca1fd3b","ty":{"defid":"core/73237d41::slice::index::slice_index_order_fail","kind":"FnDef"}},{"name":"ty::FnDef::293b7d0b334e36b5","ty":{"defid":"core/73237d41::slice::index::slice_end_index_len_fail","kind":"FnDef"}},{"name":"ty::FnDef::a1fb0a669f0985bf","ty":{"defid":"core/73237d41::slice::index::{impl#4}::get_unchecked::_instc5e93708b8ca6e2a[0]","kind":"FnDef"}},{"name":"ty::RawPtr::1f2b1eadb40cd255","ty":{"kind":"RawPtr","mutability":{"kind":"Not"},"ty":"ty::u32"}},{"name":"ty::isize","ty":{"intkind":{"kind":"Isize"},"kind":"Int"}},{"name":"ty::RawPtr::ac3bacfc73b0b976","ty":{"kind":"RawPtr","mutability":{"kind":"Not"},"ty":"ty::Tuple::e93222e871854c41"}},{"name":"ty::Adt::1f7c550e96e53aa8","ty":{"kind":"Adt","name":"core/73237d41::ptr::metadata::PtrRepr::_adt2ed9deda136ace65[0]","orig_def_id":"core/73237d41::ptr::metadata::PtrRepr","substs":["ty::Slice::f7eb0deb10702a2f"]}},{"name":"ty::Adt::c4a120efbbc79aa2","ty":{"kind":"Adt","name":"core/73237d41::ptr::metadata::PtrComponents::_adt2ed9deda136ace65[0]","orig_def_id":"core/73237d41::ptr::metadata::PtrComponents","substs":["ty::Slice::f7eb0deb10702a2f"]}},{"name":"ty::FnDef::c699298b9e73f83a","ty":{"defid":"core/73237d41::intrinsics::{extern#0}::offset::_instc5e93708b8ca6e2a[0]","kind":"FnDef"}},{"name":"ty::RawPtr::1aaf1d3d9e30a4c2","ty":{"kind":"RawPtr","mutability":{"kind":"Mut"},"ty":"ty::Slice::f7eb0deb10702a2f"}}],"roots":["slices/6276e58b::sum_of_prefix","slices/6276e58b::sum_of_prefix_examples"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/slices.rs b/doc/rust-tutorial/code/slices.rs new file mode 100644 index 0000000000..f8767e372a --- /dev/null +++ b/doc/rust-tutorial/code/slices.rs @@ -0,0 +1,17 @@ +pub fn sum_of_prefix(s: &[u32]) -> u32 { + s[0].wrapping_add(s[1]) +} + +pub fn sum_of_prefix_examples() { + let a1 = [1, 2]; + let s1 = &a1[..]; + let sum1 = sum_of_prefix(s1); + + let a2 = [1, 2, 3, 4, 5]; + let s2 = &a2[..]; + let sum2 = sum_of_prefix(s2); + + let a3 = [1, 2, 3, 4, 5]; + let s3 = &a3[0..2]; + let sum3 = sum_of_prefix(s3); +} diff --git a/doc/rust-tutorial/code/slices.saw b/doc/rust-tutorial/code/slices.saw new file mode 100644 index 0000000000..7401ab786a --- /dev/null +++ b/doc/rust-tutorial/code/slices.saw @@ -0,0 +1,45 @@ +enable_experimental; + +m <- mir_load_module "slices.linked-mir.json"; + +let sum_of_prefix_spec1 = do { + a_ref <- mir_alloc (mir_array 2 mir_u32); + a_val <- mir_fresh_var "a" (mir_array 2 mir_u32); + mir_points_to a_ref (mir_term a_val); + + let s = mir_slice_value a_ref; + + mir_execute_func [s]; + + mir_return (mir_term {{ (a_val @ 0) + (a_val @ 1) }}); +}; + +mir_verify m "slices::sum_of_prefix" [] false sum_of_prefix_spec1 z3; + +let sum_of_prefix_spec2 = do { + a_ref <- mir_alloc (mir_array 5 mir_u32); + a_val <- mir_fresh_var "a" (mir_array 5 mir_u32); + mir_points_to a_ref (mir_term a_val); + + let s = mir_slice_value a_ref; + + mir_execute_func [s]; + + mir_return (mir_term {{ (a_val @ 0) + (a_val @ 1) }}); +}; + +mir_verify m "slices::sum_of_prefix" [] false sum_of_prefix_spec2 z3; + +let sum_of_prefix_spec3 = do { + a_ref <- mir_alloc (mir_array 5 mir_u32); + a_val <- mir_fresh_var "a" (mir_array 5 mir_u32); + mir_points_to a_ref (mir_term a_val); + + let s = mir_slice_range_value a_ref 0 2; + + mir_execute_func [s]; + + mir_return (mir_term {{ (a_val @ 0) + (a_val @ 1) }}); +}; + +mir_verify m "slices::sum_of_prefix" [] false sum_of_prefix_spec3 z3; diff --git a/doc/rust-tutorial/code/statics-compositional-fail.saw b/doc/rust-tutorial/code/statics-compositional-fail.saw new file mode 100644 index 0000000000..b0c95e78a2 --- /dev/null +++ b/doc/rust-tutorial/code/statics-compositional-fail.saw @@ -0,0 +1,20 @@ +enable_experimental; + +m <- mir_load_module "statics-compositional.linked-mir.json"; + +let a = "statics_compositional::A"; + +let side_effect_spec = do { + mir_points_to (mir_static a) (mir_static_initializer a); + mir_execute_func []; +}; + +let foo_spec = do { + let a_init = mir_static_initializer a; + mir_points_to (mir_static a) a_init; + mir_execute_func []; + mir_return a_init; +}; + +side_effect_ov <- mir_verify m "statics_compositional::side_effect" [] false side_effect_spec z3; +mir_verify m "statics_compositional::foo" [side_effect_ov] false foo_spec z3; diff --git a/doc/rust-tutorial/code/statics-compositional.linked-mir.json b/doc/rust-tutorial/code/statics-compositional.linked-mir.json new file mode 100644 index 0000000000..d9b8332dd7 --- /dev/null +++ b/doc/rust-tutorial/code/statics-compositional.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"statics-compositional.rs:1:21: 1:23","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"42"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"statics-compositional.rs:1:1: 1:24"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}]},"name":"statics_compositional/16fea9c0::A","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[],"terminator":{"args":[],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":true,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Tuple::e93222e871854c41"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::117f2364d607b4ff"},"kind":"Constant"},"kind":"Call","pos":"statics-compositional.rs:10:5: 10:18"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::RawPtr::63e5937014067f41"}},"pos":"statics-compositional.rs:11:14: 11:15","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"def_id":"statics_compositional/16fea9c0::A","kind":"static_ref"},"ty":"ty::RawPtr::63e5937014067f41"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"statics-compositional.rs:11:14: 11:15","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::RawPtr::63e5937014067f41"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"statics-compositional.rs:12:2: 12:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":true,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Tuple::e93222e871854c41"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::RawPtr::63e5937014067f41"}]},"name":"statics_compositional/16fea9c0::foo","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}},"pos":"statics-compositional.rs:5:9: 5:10","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"def_id":"statics_compositional/16fea9c0::A","kind":"static_ref"},"ty":"ty::RawPtr::63e5937014067f41"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}},"pos":"statics-compositional.rs:5:9: 5:14","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"0"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"statics-compositional.rs:7:2: 7:2"}},"blockid":"bb0"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}]},"name":"statics_compositional/16fea9c0::side_effect","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null}],"adts":[],"statics":[{"kind":"body","mutable":true,"name":"statics_compositional/16fea9c0::A","ty":"ty::u32"}],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"statics_compositional/16fea9c0::foo","kind":"Item","substs":[]},"name":"statics_compositional/16fea9c0::foo"},{"inst":{"def_id":"statics_compositional/16fea9c0::side_effect","kind":"Item","substs":[]},"name":"statics_compositional/16fea9c0::side_effect"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}},{"name":"ty::RawPtr::63e5937014067f41","ty":{"kind":"RawPtr","mutability":{"kind":"Mut"},"ty":"ty::u32"}},{"name":"ty::FnDef::117f2364d607b4ff","ty":{"defid":"statics_compositional/16fea9c0::side_effect","kind":"FnDef"}}],"roots":["statics_compositional/16fea9c0::side_effect","statics_compositional/16fea9c0::foo"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/statics-compositional.rs b/doc/rust-tutorial/code/statics-compositional.rs new file mode 100644 index 0000000000..452b4658eb --- /dev/null +++ b/doc/rust-tutorial/code/statics-compositional.rs @@ -0,0 +1,12 @@ +static mut A: u32 = 42; + +pub fn side_effect() { + unsafe { + A = 0; + } +} + +pub fn foo() -> u32 { + side_effect(); + unsafe { A } +} diff --git a/doc/rust-tutorial/code/statics-compositional.saw b/doc/rust-tutorial/code/statics-compositional.saw new file mode 100644 index 0000000000..bb30e049f4 --- /dev/null +++ b/doc/rust-tutorial/code/statics-compositional.saw @@ -0,0 +1,25 @@ +enable_experimental; + +m <- mir_load_module "statics-compositional.linked-mir.json"; + +let a = "statics_compositional::A"; + +let side_effect_spec = do { + mir_points_to (mir_static a) (mir_static_initializer a); + mir_execute_func []; + + // This is new + mir_points_to (mir_static a) (mir_term {{ 0 : [32] }}); +}; + +let foo_spec = do { + let a_init = mir_static_initializer a; + mir_points_to (mir_static a) a_init; + mir_execute_func []; + + // This is new + mir_return (mir_term {{ 0 : [32] }}); +}; + +side_effect_ov <- mir_verify m "statics_compositional::side_effect" [] false side_effect_spec z3; +mir_verify m "statics_compositional::foo" [side_effect_ov] false foo_spec z3; diff --git a/doc/rust-tutorial/code/statics-fail.saw b/doc/rust-tutorial/code/statics-fail.saw new file mode 100644 index 0000000000..8197628332 --- /dev/null +++ b/doc/rust-tutorial/code/statics-fail.saw @@ -0,0 +1,12 @@ +enable_experimental; + +m <- mir_load_module "statics.linked-mir.json"; + +let mut_answer_to_the_ultimate_question_spec = do { + mir_execute_func []; + + mir_return (mir_static_initializer "statics::MUT_ANSWER"); +}; + +mir_verify m "statics::mut_answer_to_the_ultimate_question" [] false + mut_answer_to_the_ultimate_question_spec z3; diff --git a/doc/rust-tutorial/code/statics.linked-mir.json b/doc/rust-tutorial/code/statics.linked-mir.json new file mode 100644 index 0000000000..cecd5e9a1a --- /dev/null +++ b/doc/rust-tutorial/code/statics.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"statics.rs:11:30: 11:32","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"42"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"statics.rs:11:1: 11:33"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}]},"name":"statics/3cdb9fa4::MUT_ANSWER","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"statics.rs:1:22: 1:24","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"42"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"statics.rs:1:1: 1:25"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}]},"name":"statics/3cdb9fa4::ANSWER","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}},"pos":"statics.rs:19:9: 19:19","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"def_id":"statics/3cdb9fa4::MUT_ANSWER","kind":"static_ref"},"ty":"ty::RawPtr::63e5937014067f41"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}},"pos":"statics.rs:19:9: 19:24","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"27"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"args":[],"cleanup":null,"destination":[{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"bb1"],"from_hir_call":true,"func":{"data":{"rendered":{"kind":"zst"},"ty":"ty::FnDef::8f369ba71bf633e3"},"kind":"Constant"},"kind":"Call","pos":"statics.rs:21:5: 21:42"}},"blockid":"bb0"},{"block":{"data":[],"terminator":{"kind":"Return","pos":"statics.rs:22:2: 22:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}]},"name":"statics/3cdb9fa4::alternate_universe","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::e028c0f25e8b6323"}},"pos":"statics.rs:8:6: 8:12","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"def_id":"statics/3cdb9fa4::ANSWER","kind":"static_ref"},"ty":"ty::Ref::e028c0f25e8b6323"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::e028c0f25e8b6323"}},"pos":"statics.rs:8:5: 8:12","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::e028c0f25e8b6323"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"statics.rs:9:2: 9:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Ref::e028c0f25e8b6323"},{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Ref::e028c0f25e8b6323"}]},"name":"statics/3cdb9fa4::answer_in_ref_form","return_ty":"ty::Ref::e028c0f25e8b6323","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}},"pos":"statics.rs:14:14: 14:24","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"def_id":"statics/3cdb9fa4::MUT_ANSWER","kind":"static_ref"},"ty":"ty::RawPtr::63e5937014067f41"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"statics.rs:14:14: 14:24","rhs":{"kind":"Use","usevar":{"data":{"data":[{"kind":"Deref"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}},"kind":"Copy"}}}],"terminator":{"kind":"Return","pos":"statics.rs:15:2: 15:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_1","ty":"ty::RawPtr::63e5937014067f41"}]},"name":"statics/3cdb9fa4::mut_answer_to_the_ultimate_question","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"statics.rs:4:5: 4:11","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"42"},"ty":"ty::u32"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"statics.rs:5:2: 5:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}]},"name":"statics/3cdb9fa4::answer_to_the_ultimate_question","return_ty":"ty::u32","spread_arg":null}],"adts":[],"statics":[{"kind":"body","mutable":true,"name":"statics/3cdb9fa4::MUT_ANSWER","ty":"ty::u32"},{"kind":"body","mutable":false,"name":"statics/3cdb9fa4::ANSWER","ty":"ty::u32"}],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"statics/3cdb9fa4::alternate_universe","kind":"Item","substs":[]},"name":"statics/3cdb9fa4::alternate_universe"},{"inst":{"def_id":"statics/3cdb9fa4::answer_in_ref_form","kind":"Item","substs":[]},"name":"statics/3cdb9fa4::answer_in_ref_form"},{"inst":{"def_id":"statics/3cdb9fa4::mut_answer_to_the_ultimate_question","kind":"Item","substs":[]},"name":"statics/3cdb9fa4::mut_answer_to_the_ultimate_question"},{"inst":{"def_id":"statics/3cdb9fa4::answer_to_the_ultimate_question","kind":"Item","substs":[]},"name":"statics/3cdb9fa4::answer_to_the_ultimate_question"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::RawPtr::63e5937014067f41","ty":{"kind":"RawPtr","mutability":{"kind":"Mut"},"ty":"ty::u32"}},{"name":"ty::FnDef::8f369ba71bf633e3","ty":{"defid":"statics/3cdb9fa4::mut_answer_to_the_ultimate_question","kind":"FnDef"}},{"name":"ty::Ref::e028c0f25e8b6323","ty":{"kind":"Ref","mutability":{"kind":"Not"},"ty":"ty::u32"}}],"roots":["statics/3cdb9fa4::answer_to_the_ultimate_question","statics/3cdb9fa4::answer_in_ref_form","statics/3cdb9fa4::mut_answer_to_the_ultimate_question","statics/3cdb9fa4::alternate_universe"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/statics.rs b/doc/rust-tutorial/code/statics.rs new file mode 100644 index 0000000000..ccb77c4503 --- /dev/null +++ b/doc/rust-tutorial/code/statics.rs @@ -0,0 +1,22 @@ +static ANSWER: u32 = 42; + +pub fn answer_to_the_ultimate_question() -> u32 { + ANSWER +} + +pub fn answer_in_ref_form() -> &'static u32 { + &ANSWER +} + +static mut MUT_ANSWER: u32 = 42; + +pub fn mut_answer_to_the_ultimate_question() -> u32 { + unsafe { MUT_ANSWER } +} + +pub fn alternate_universe() -> u32 { + unsafe { + MUT_ANSWER = 27; + } + mut_answer_to_the_ultimate_question() +} diff --git a/doc/rust-tutorial/code/statics.saw b/doc/rust-tutorial/code/statics.saw new file mode 100644 index 0000000000..0a1f7bb5a6 --- /dev/null +++ b/doc/rust-tutorial/code/statics.saw @@ -0,0 +1,55 @@ +enable_experimental; + +m <- mir_load_module "statics.linked-mir.json"; + +let answer_to_the_ultimate_question_spec1 = do { + mir_execute_func []; + + mir_return (mir_term {{ 42 : [32] }}); +}; + +mir_verify m "statics::answer_to_the_ultimate_question" [] false + answer_to_the_ultimate_question_spec1 z3; + +let answer_to_the_ultimate_question_spec2 = do { + mir_execute_func []; + + mir_return (mir_static_initializer "statics::ANSWER"); +}; + +mir_verify m "statics::answer_to_the_ultimate_question" [] false + answer_to_the_ultimate_question_spec2 z3; + +let answer_in_ref_form_spec = do { + mir_execute_func []; + + mir_return (mir_static "statics::ANSWER"); +}; + +mir_verify m "statics::answer_in_ref_form" [] false + answer_in_ref_form_spec z3; + +let mut_answer_to_the_ultimate_question_spec = do { + let mut_answer = "statics::MUT_ANSWER"; + let mut_answer_init = mir_static_initializer mut_answer; + mir_points_to (mir_static mut_answer) mut_answer_init; + + mir_execute_func []; + + mir_return mut_answer_init; +}; + +mir_verify m "statics::mut_answer_to_the_ultimate_question" [] false + mut_answer_to_the_ultimate_question_spec z3; + +let mut_answer_to_the_ultimate_question_alt_spec = do { + let alt_answer = mir_term {{ 27 : [32] }}; + mir_points_to (mir_static "statics::MUT_ANSWER") alt_answer; + + mir_execute_func []; + + mir_return alt_answer; +}; + +mir_verify m "statics::mut_answer_to_the_ultimate_question" [] false + mut_answer_to_the_ultimate_question_alt_spec z3; diff --git a/doc/rust-tutorial/code/structs.linked-mir.json b/doc/rust-tutorial/code/structs.linked-mir.json new file mode 100644 index 0000000000..2fdf8ec6a1 --- /dev/null +++ b/doc/rust-tutorial/code/structs.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Deinit","pos":"structs.rs:5:5: 5:14"},{"kind":"Assign","lhs":{"data":[{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::f0f86f6b48fbfed2"}},"pos":"structs.rs:5:5: 5:14","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"27"},"ty":"ty::u32"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[{"field":1,"kind":"Field","ty":"ty::u64"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::f0f86f6b48fbfed2"}},"pos":"structs.rs:5:5: 5:14","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":8,"val":"42"},"ty":"ty::u64"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"structs.rs:6:2: 6:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::f0f86f6b48fbfed2"}]},"name":"structs/7a69f310::make_s","return_ty":"ty::Adt::f0f86f6b48fbfed2","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Adt::2b5dd517baacf4c7"}],"body":{"blocks":[{"block":{"data":[],"terminator":{"kind":"Return","pos":"structs.rs:22:2: 22:2"}},"blockid":"bb0"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"}]},"name":"structs/7a69f310::do_stuff_with_bar","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Deinit","pos":"structs.rs:9:5: 9:14"},{"kind":"Assign","lhs":{"data":[{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::a0808cf197e64fba"}},"pos":"structs.rs:9:5: 9:14","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"27"},"ty":"ty::u32"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[{"field":1,"kind":"Field","ty":"ty::u64"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::a0808cf197e64fba"}},"pos":"structs.rs:9:5: 9:14","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":8,"val":"42"},"ty":"ty::u64"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"structs.rs:10:2: 10:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::a0808cf197e64fba"}]},"name":"structs/7a69f310::make_t","return_ty":"ty::Adt::a0808cf197e64fba","spread_arg":null},{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[{"kind":"Deinit","pos":"structs.rs:15:5: 15:16"},{"kind":"Assign","lhs":{"data":[{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::705107dc065f2b29"}},"pos":"structs.rs:15:5: 15:16","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":4,"val":"27"},"ty":"ty::u32"},"kind":"Constant"}}},{"kind":"Assign","lhs":{"data":[{"field":1,"kind":"Field","ty":"ty::u64"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::705107dc065f2b29"}},"pos":"structs.rs:15:5: 15:16","rhs":{"kind":"Use","usevar":{"data":{"rendered":{"kind":"uint","size":8,"val":"42"},"ty":"ty::u64"},"kind":"Constant"}}}],"terminator":{"kind":"Return","pos":"structs.rs:16:2: 16:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Adt::705107dc065f2b29"}]},"name":"structs/7a69f310::make_foo","return_ty":"ty::Adt::705107dc065f2b29","spread_arg":null}],"adts":[{"kind":{"kind":"Struct"},"name":"structs/7a69f310::S::_adtb7803c2264daf0ec[0]","orig_def_id":"structs/7a69f310::S","orig_substs":[],"repr_transparent":false,"size":16,"variants":[{"ctor_kind":{"kind":"Fn"},"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"structs/7a69f310::S::0","ty":"ty::u32"},{"name":"structs/7a69f310::S::1","ty":"ty::u64"}],"inhabited":true,"name":"structs/7a69f310::S"}]},{"kind":{"kind":"Struct"},"name":"structs/7a69f310::Bar::_adtb7803c2264daf0ec[0]","orig_def_id":"structs/7a69f310::Bar","orig_substs":[],"repr_transparent":false,"size":24,"variants":[{"ctor_kind":{"kind":"Fn"},"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"structs/7a69f310::Bar::0","ty":"ty::u8"},{"name":"structs/7a69f310::Bar::1","ty":"ty::u16"},{"name":"structs/7a69f310::Bar::2","ty":"ty::Adt::705107dc065f2b29"}],"inhabited":true,"name":"structs/7a69f310::Bar"}]},{"kind":{"kind":"Struct"},"name":"structs/7a69f310::T::_adtb7803c2264daf0ec[0]","orig_def_id":"structs/7a69f310::T","orig_substs":[],"repr_transparent":false,"size":16,"variants":[{"ctor_kind":{"kind":"Fn"},"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"structs/7a69f310::T::0","ty":"ty::u32"},{"name":"structs/7a69f310::T::1","ty":"ty::u64"}],"inhabited":true,"name":"structs/7a69f310::T"}]},{"kind":{"kind":"Struct"},"name":"structs/7a69f310::Foo::_adt7eaeafbd77999f83[0]","orig_def_id":"structs/7a69f310::Foo","orig_substs":["ty::u32","ty::u64"],"repr_transparent":false,"size":16,"variants":[{"ctor_kind":{"kind":"Fn"},"discr":{"index":0,"kind":"Relative"},"discr_value":null,"fields":[{"name":"structs/7a69f310::Foo::0","ty":"ty::u32"},{"name":"structs/7a69f310::Foo::1","ty":"ty::u64"}],"inhabited":true,"name":"structs/7a69f310::Foo"}]}],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"structs/7a69f310::make_s","kind":"Item","substs":[]},"name":"structs/7a69f310::make_s"},{"inst":{"def_id":"structs/7a69f310::do_stuff_with_bar","kind":"Item","substs":[]},"name":"structs/7a69f310::do_stuff_with_bar"},{"inst":{"def_id":"structs/7a69f310::make_t","kind":"Item","substs":[]},"name":"structs/7a69f310::make_t"},{"inst":{"def_id":"structs/7a69f310::make_foo","kind":"Item","substs":[]},"name":"structs/7a69f310::make_foo"}],"tys":[{"name":"ty::Adt::f0f86f6b48fbfed2","ty":{"kind":"Adt","name":"structs/7a69f310::S::_adtb7803c2264daf0ec[0]","orig_def_id":"structs/7a69f310::S","substs":[]}},{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::u64","ty":{"kind":"Uint","uintkind":{"kind":"U64"}}},{"name":"ty::Adt::2b5dd517baacf4c7","ty":{"kind":"Adt","name":"structs/7a69f310::Bar::_adtb7803c2264daf0ec[0]","orig_def_id":"structs/7a69f310::Bar","substs":[]}},{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}},{"name":"ty::Adt::a0808cf197e64fba","ty":{"kind":"Adt","name":"structs/7a69f310::T::_adtb7803c2264daf0ec[0]","orig_def_id":"structs/7a69f310::T","substs":[]}},{"name":"ty::Adt::705107dc065f2b29","ty":{"kind":"Adt","name":"structs/7a69f310::Foo::_adt7eaeafbd77999f83[0]","orig_def_id":"structs/7a69f310::Foo","substs":["ty::u32","ty::u64"]}},{"name":"ty::u8","ty":{"kind":"Uint","uintkind":{"kind":"U8"}}},{"name":"ty::u16","ty":{"kind":"Uint","uintkind":{"kind":"U16"}}}],"roots":["structs/7a69f310::make_s","structs/7a69f310::make_t","structs/7a69f310::make_foo","structs/7a69f310::do_stuff_with_bar"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/structs.rs b/doc/rust-tutorial/code/structs.rs new file mode 100644 index 0000000000..a02655ff29 --- /dev/null +++ b/doc/rust-tutorial/code/structs.rs @@ -0,0 +1,22 @@ +pub struct S(u32, u64); +pub struct T(u32, u64); + +pub fn make_s() -> S { + S(27, 42) +} + +pub fn make_t() -> T { + T(27, 42) +} + +pub struct Foo(A, B); + +pub fn make_foo() -> Foo { + Foo(27, 42) +} + +pub struct Bar(u8, u16, Foo); + +pub fn do_stuff_with_bar(b: Bar) { + // ... +} diff --git a/doc/rust-tutorial/code/structs.saw b/doc/rust-tutorial/code/structs.saw new file mode 100644 index 0000000000..be8d957c92 --- /dev/null +++ b/doc/rust-tutorial/code/structs.saw @@ -0,0 +1,50 @@ +enable_experimental; + +m <- mir_load_module "structs.linked-mir.json"; + +s_adt <- mir_find_adt m "structs::S" []; +t_adt <- mir_find_adt m "structs::T" []; +foo_adt <- mir_find_adt m "structs::Foo" [mir_u32, mir_u64]; + +let make_foo_spec = do { + mir_execute_func []; + + let ret = mir_struct_value + foo_adt + [mir_term {{ 27 : [32] }}, mir_term {{ 42 : [64] }}]; + mir_return ret; +}; + +mir_verify m "structs::make_foo" [] false make_foo_spec z3; + +bar_adt <- mir_find_adt m "structs::Bar" []; + +let do_stuff_with_bar_spec1 = do { + z1 <- mir_fresh_var "z1" mir_u32; + z2 <- mir_fresh_var "z2" mir_u64; + let z = mir_struct_value + foo_adt + [mir_term z1, mir_term z2]; + + x <- mir_fresh_var "x" mir_u8; + y <- mir_fresh_var "y" mir_u16; + let b = mir_struct_value + bar_adt + [mir_term x, mir_term y, z]; + + mir_execute_func [b]; + + // ... +}; + +mir_verify m "structs::do_stuff_with_bar" [] false do_stuff_with_bar_spec1 z3; + +let do_stuff_with_bar_spec2 = do { + b <- mir_fresh_expanded_value "b" (mir_adt bar_adt); + + mir_execute_func [b]; + + // ... +}; + +mir_verify m "structs::do_stuff_with_bar" [] false do_stuff_with_bar_spec2 z3; diff --git a/doc/rust-tutorial/code/times-two-ref-fail.saw b/doc/rust-tutorial/code/times-two-ref-fail.saw new file mode 100644 index 0000000000..d3d2a5dd74 --- /dev/null +++ b/doc/rust-tutorial/code/times-two-ref-fail.saw @@ -0,0 +1,11 @@ +enable_experimental; + +let times_two_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_execute_func [mir_term x]; + mir_return (mir_term {{ 2 * x }}); +}; + +m <- mir_load_module "times-two.linked-mir.json"; + +mir_verify m "times_two::times_two_ref" [] false times_two_spec z3; diff --git a/doc/rust-tutorial/code/times-two.linked-mir.json b/doc/rust-tutorial/code/times-two.linked-mir.json new file mode 100644 index 0000000000..7be6f0737b --- /dev/null +++ b/doc/rust-tutorial/code/times-two.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"pos":"times-two.rs:6:9: 6:10","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}},"pos":"times-two.rs:6:5: 6:10","rhs":{"L":{"data":{"rendered":{"kind":"uint","size":4,"val":"2"},"ty":"ty::u32"},"kind":"Constant"},"R":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"kind":"Copy"},"kind":"CheckedBinaryOp","op":{"kind":"Mul"}}}],"terminator":{"cleanup":null,"cond":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::bool"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}},"kind":"Move"},"expected":false,"kind":"Assert","msg":"attempt to compute `const 2_u32 * move _2`, which would overflow","pos":"times-two.rs:6:5: 6:10","target":"bb1"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"times-two.rs:6:5: 6:10","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}},"kind":"Move"}}}],"terminator":{"kind":"Return","pos":"times-two.rs:7:2: 7:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}]},"name":"times_two/56182919::times_two_ref","return_ty":"ty::u32","spread_arg":null},{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"pos":"times-two.rs:2:5: 2:6","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::u32"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}},"pos":"times-two.rs:2:5: 2:11","rhs":{"L":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"}},"kind":"Copy"},"R":{"data":{"rendered":{"kind":"int","size":4,"val":"1"},"ty":"ty::i32"},"kind":"Constant"},"kind":"CheckedBinaryOp","op":{"kind":"Shl"}}}],"terminator":{"cleanup":null,"cond":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::bool"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}},"kind":"Move"},"expected":false,"kind":"Assert","msg":"attempt to shift left by `const 1_i32`, which would overflow","pos":"times-two.rs:2:5: 2:11","target":"bb1"}},"blockid":"bb0"},{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"}},"pos":"times-two.rs:2:5: 2:11","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}},"kind":"Move"}}}],"terminator":{"kind":"Return","pos":"times-two.rs:3:2: 3:2"}},"blockid":"bb1"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u32"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::Tuple::7063e33f0dbc8a58"}]},"name":"times_two/56182919::times_two","return_ty":"ty::u32","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"times_two/56182919::times_two_ref","kind":"Item","substs":[]},"name":"times_two/56182919::times_two_ref"},{"inst":{"def_id":"times_two/56182919::times_two","kind":"Item","substs":[]},"name":"times_two/56182919::times_two"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::bool","ty":{"kind":"Bool"}},{"name":"ty::Tuple::7063e33f0dbc8a58","ty":{"kind":"Tuple","tys":["ty::u32","ty::bool"]}},{"name":"ty::i32","ty":{"intkind":{"kind":"I32"},"kind":"Int"}}],"roots":["times_two/56182919::times_two","times_two/56182919::times_two_ref"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/times-two.rs b/doc/rust-tutorial/code/times-two.rs new file mode 100644 index 0000000000..d05ca16561 --- /dev/null +++ b/doc/rust-tutorial/code/times-two.rs @@ -0,0 +1,7 @@ +pub fn times_two(x: u32) -> u32 { + x << 1 // Gotta go fast +} + +pub fn times_two_ref(x: u32) -> u32 { + 2 * x +} diff --git a/doc/rust-tutorial/code/times-two.saw b/doc/rust-tutorial/code/times-two.saw new file mode 100644 index 0000000000..3b15de3c3f --- /dev/null +++ b/doc/rust-tutorial/code/times-two.saw @@ -0,0 +1,52 @@ +enable_experimental; + +let times_two_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_execute_func [mir_term x]; + mir_return (mir_term {{ 2 * x }}); +}; + +m <- mir_load_module "times-two.linked-mir.json"; + +mir_verify m "times_two::times_two" [] false times_two_spec z3; + +let times_two_ref_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ x < 2^^31 }}; + mir_execute_func [mir_term x]; + mir_return (mir_term {{ 2 * x }}); +}; + +mir_verify m "times_two::times_two_ref" [] false times_two_ref_spec z3; + +let times_two_ref_positive_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ 0 < x }}; // The input must be positive + mir_precond {{ x < 2^^31 }}; + mir_execute_func [mir_term x]; + mir_return (mir_term {{ 2 * x }}); +}; + +mir_verify m "times_two::times_two_ref" [] false times_two_ref_positive_spec z3; + +let times_two_ref_positive_postcond_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_precond {{ 0 < x }}; // The input must be positive + mir_precond {{ x < 2^^31 }}; + mir_execute_func [mir_term x]; + mir_postcond {{ x < (2 * x) }}; // Argument value < return value + mir_return (mir_term {{ 2 * x }}); +}; + +mir_verify m "times_two::times_two_ref" [] false times_two_ref_positive_postcond_spec z3; + +let times_two_ref_positive_postcond_assert_spec = do { + x <- mir_fresh_var "x" mir_u32; + mir_assert {{ 0 < x }}; // The input must be positive + mir_assert {{ x < 2^^31 }}; + mir_execute_func [mir_term x]; + mir_assert {{ x < (2 * x) }}; // Argument value < return value + mir_return (mir_term {{ 2 * x }}); +}; + +mir_verify m "times_two::times_two_ref" [] false times_two_ref_positive_postcond_assert_spec z3; diff --git a/doc/rust-tutorial/code/tuples.linked-mir.json b/doc/rust-tutorial/code/tuples.linked-mir.json new file mode 100644 index 0000000000..e380668154 --- /dev/null +++ b/doc/rust-tutorial/code/tuples.linked-mir.json @@ -0,0 +1 @@ +{"fns":[{"abi":{"kind":"Rust"},"args":[{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Tuple::b0da1a0f543dbb6d"}],"body":{"blocks":[{"block":{"data":[{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u64"}},"pos":"tuples.rs:2:6: 2:9","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":1,"kind":"Field","ty":"ty::u64"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Tuple::b0da1a0f543dbb6d"}},"kind":"Copy"}}},{"kind":"Assign","lhs":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"pos":"tuples.rs:2:11: 2:14","rhs":{"kind":"Use","usevar":{"data":{"data":[{"field":0,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Not"},"name":"_1","ty":"ty::Tuple::b0da1a0f543dbb6d"}},"kind":"Copy"}}},{"kind":"Deinit","pos":"tuples.rs:2:5: 2:15"},{"kind":"Assign","lhs":{"data":[{"field":0,"kind":"Field","ty":"ty::u64"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::1e627c59d8e645f0"}},"pos":"tuples.rs:2:5: 2:15","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u64"}},"kind":"Move"}}},{"kind":"Assign","lhs":{"data":[{"field":1,"kind":"Field","ty":"ty::u32"}],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::1e627c59d8e645f0"}},"pos":"tuples.rs:2:5: 2:15","rhs":{"kind":"Use","usevar":{"data":{"data":[],"var":{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}},"kind":"Move"}}}],"terminator":{"kind":"Return","pos":"tuples.rs:3:2: 3:2"}},"blockid":"bb0"}],"vars":[{"is_zst":false,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::1e627c59d8e645f0"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_2","ty":"ty::u64"},{"is_zst":false,"mut":{"kind":"Mut"},"name":"_3","ty":"ty::u32"}]},"name":"tuples/bc2ddca6::flip","return_ty":"ty::Tuple::1e627c59d8e645f0","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"tuples/bc2ddca6::flip","kind":"Item","substs":[]},"name":"tuples/bc2ddca6::flip"}],"tys":[{"name":"ty::u32","ty":{"kind":"Uint","uintkind":{"kind":"U32"}}},{"name":"ty::u64","ty":{"kind":"Uint","uintkind":{"kind":"U64"}}},{"name":"ty::Tuple::b0da1a0f543dbb6d","ty":{"kind":"Tuple","tys":["ty::u32","ty::u64"]}},{"name":"ty::Tuple::1e627c59d8e645f0","ty":{"kind":"Tuple","tys":["ty::u64","ty::u32"]}}],"roots":["tuples/bc2ddca6::flip"]} \ No newline at end of file diff --git a/doc/rust-tutorial/code/tuples.rs b/doc/rust-tutorial/code/tuples.rs new file mode 100644 index 0000000000..a2bf31f86c --- /dev/null +++ b/doc/rust-tutorial/code/tuples.rs @@ -0,0 +1,3 @@ +pub fn flip(x: (u32, u64)) -> (u64, u32) { + (x.1, x.0) +} diff --git a/doc/rust-tutorial/code/tuples.saw b/doc/rust-tutorial/code/tuples.saw new file mode 100644 index 0000000000..fc859790a7 --- /dev/null +++ b/doc/rust-tutorial/code/tuples.saw @@ -0,0 +1,13 @@ +enable_experimental; + +let flip_spec = do { + x <- mir_fresh_var "x" (mir_tuple [mir_u32, mir_u64]); + + mir_execute_func [mir_term x]; + + mir_return (mir_term {{ (x.1, x.0) }}); +}; + +m <- mir_load_module "tuples.linked-mir.json"; + +mir_verify m "tuples::flip" [] false flip_spec z3; diff --git a/doc/rust-tutorial/doc.css b/doc/rust-tutorial/doc.css new file mode 100644 index 0000000000..08327aa2df --- /dev/null +++ b/doc/rust-tutorial/doc.css @@ -0,0 +1,93 @@ +body { + font-size: 14px; + line-height: 21px; + color: #333; + font-family: "Helvetica Neue", "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; +} +.container { + width: 950px; + margin: 0; + padding: 80px 0px 50px 50px; +} +p, li { + width: 625px; +} +a { + color: #191933; +} +h1, h2, h3, h4, h5, h6, b.header { + color: #000; + margin-top: 40px; + margin-bottom: 15px; + text-shadow: #fff 0 1px 1px; +} +h1 { font-size: 18px } +h2 { font-size: 16px } +h3, h4, h5, h6 { font-size: 14px } +.author { font-weight: normal } + +br.clear { + height: 0; + clear: both; +} +ul { + padding-left: 20px; +} +b.header { + display: block; +} +li { + margin-bottom: 10px; +} +code, pre, tt, textarea { + font-family: Monaco, Consolas, "Lucida Console", monospace; + font-size: 12px; + line-height: 18px; + color: #155; + white-space: pre-wrap; + word-wrap: break-word; +} + tt { + display: inline-block; + background: #fff; + border: 1px solid #dedede; + padding: 0px 0.2em; + } + pre { + border-left: 5px solid rgba(0,0,0,0.2); + padding: 3px 0 3px 12px; + font-size: 12px; + } + pre.no_bar { + border-left: 0; + margin-left: 0; + padding-left: 0; + } +div.code { + position: relative; + background: #fff; + border: 1px solid #d8d8d8; + -webkit-box-shadow: 0px 0px 4px rgba(0,0,0,0.23); + -moz-box-shadow: 0px 0px 4px rgba(0,0,0,0.23); + box-shadow: 0px 0px 4px rgba(0,0,0,0.23); + zoom: 1; +} + div.code { + text-transform: none; + position: absolute; + right: 8px; bottom: 8px; + } + div.code { + left: 8px; right: auto; + } + div.code pre, div.code textarea { + float: left; + width: 450px; + background: #fff; + border-left: 1px dotted #d0d0d0; + margin: 10px 0 15px 3px; + padding: 0 0 0 12px; + } + div.code pre:first-child { + border-left: 0; + } diff --git a/doc/rust-tutorial/docode.hs b/doc/rust-tutorial/docode.hs new file mode 100644 index 0000000000..550c9fec15 --- /dev/null +++ b/doc/rust-tutorial/docode.hs @@ -0,0 +1,30 @@ +module Main where + +import Control.Monad +import System.Process + +interactIO :: (String -> IO String) -> IO () +interactIO act = do + txt <- getContents + mapM_ (act >=> putStr) (lines txt) + +-- TODO: this does no error handling whatsoever +processCommand :: String -> IO String +processCommand line = + case words line of + ("$cmd":cmd:args) -> do + result <- readProcess cmd args "" + return $ unlines [ unwords ("#" : cmd : args) ] ++ result + ["$include", "all", file] -> readFile file + ["$include", range, file] -> + do txt <- readFile file + return . unlines . take (endN - startN) $ drop startN (lines txt) + where + (start, end') = break (== '-') range + end = tail end' + startN = read start - 1 + endN = read end + _ -> return (line ++ "\n") + +main :: IO () +main = interactIO processCommand diff --git a/doc/rust-tutorial/figures/galois.pdf b/doc/rust-tutorial/figures/galois.pdf new file mode 100644 index 0000000000..58cbef37a0 Binary files /dev/null and b/doc/rust-tutorial/figures/galois.pdf differ diff --git a/doc/rust-tutorial/figures/galois.png b/doc/rust-tutorial/figures/galois.png new file mode 100644 index 0000000000..39a5ba86cb Binary files /dev/null and b/doc/rust-tutorial/figures/galois.png differ diff --git a/doc/rust-tutorial/galois-whitepaper.cls b/doc/rust-tutorial/galois-whitepaper.cls new file mode 100644 index 0000000000..9e47c94810 --- /dev/null +++ b/doc/rust-tutorial/galois-whitepaper.cls @@ -0,0 +1,143 @@ +% This class file defines a style useful for writing whitepapers at Galois. +\ProvidesClass{galois-whitepaper}[2010/11/02 Galois whitepaper class] +\newif\if@xelatex +\@xelatexfalse +\DeclareOption{xelatex}{\@xelatextrue} +\DeclareOption*{% +\PassOptionsToClass{\CurrentOption}{article}% +} +\ProcessOptions\relax +\LoadClass{article} + +% Useful packages: +% \RequirePackage[table]{xcolor} +\RequirePackage{graphicx} +%\RequirePackage[headheight=144pt,top=1in,left=1in,right=1in,bottom=1in]{geometry} +\RequirePackage[top=1in,left=1in,right=1in,bottom=1in]{geometry} +\RequirePackage{lastpage} + +% Define fonts +\if@xelatex +\RequirePackage{fontspec} +\RequirePackage{xunicode} +\RequirePackage{xltxtra} +\setmainfont[Mapping=tex-text]{Palatino} +\setsansfont[Mapping=tex-text]{Arial} +\else +\RequirePackage[sc]{mathpazo} +\linespread{1.05} +\RequirePackage[scaled]{helvet} +\fi + +\RequirePackage{sectsty} +\allsectionsfont{\sffamily} + +\newcommand{\highlight}[2][yellow]{\colorbox{#1}{#2}} + +% Misc defines +\makeatletter + \newcommand{\@companyName}{Galois, Inc.} + \newcommand{\@addressPhone}{ + 421 SW 6th Ave., Ste.\ 300\\ + Portland, OR 97204 + } + \newcommand{\@contact}{\todo[Contact]} + \newcommand{\@subtitle}{TODO: Subtitle} + \newcommand{\contact}[1]{\renewcommand{\@contact}{{#1}}} +\makeatother + +\renewcommand{\paragraph}[1]{\textbf{\sffamily{#1}}\quad} + +% \definecolor{galoislightgray}{gray}{0.6} +% Define header and footer +\RequirePackage{fancyhdr} +\pagestyle{fancy} +\fancyheadoffset[l]{1in} +\fancyheadoffset[r]{0in} +%\fancyheadoffset[r]{0.2in} +\fancyhead{}%clear +\fancyfoot{}%clear +\renewcommand{\headrulewidth}{0pt} +\renewcommand{\footrulewidth}{1pt} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Define a special header style for the title page: +% + \makeatletter + \newcommand{\ps@title}{% + \renewcommand{\@oddhead}{% + \sffamily\includegraphics[width=1in]{figures/galois.pdf} + }} +\makeatother + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Set up the headers/footers for the rest of the document: +%% +\lhead{\sffamily\hspace{1in}\includegraphics[width=1in]{figures/galois.pdf}} + +\makeatletter +\rhead{\sffamily \textit{\@title{}}} +\makeatother + +\lfoot{\sffamily\color{lightgray}\small\copyright{} 2023 Galois, Inc.} + +\rfoot{ + % \sffamily \color{galoislightgray}\small + \sffamily \color{lightgray}\small + Page \thepage{}% of \pageref{LastPage} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% The title content definition: +%% +\makeatletter +\DeclareRobustCommand{\maketitle}{ + \thispagestyle{title} + \begin{center} + {\sffamily + {\large \textbf{}}\\ + \vspace{0.3in} + \textbf{\sffamily \LARGE \@title}\\ + %\vspace{0.5in} + %{ \@author }\\ + \vspace{0.3in} + {\large \@companyName }\\ + \vspace{0.025in} + {\small \@addressPhone }\\ + } + \end{center} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Add a stop ``.'' after each section number: +%% + +% Redefine the bibliography environment to use \section{\bibname} +% instead of \section*{\bibname} +\newcommand{\bibname}{References} +\renewenvironment{thebibliography}[1] + {\section*{\bibname}% <-- this line was changed from \chapter* to \section* + \@mkboth{\MakeUppercase\bibname}{\MakeUppercase\bibname}% + \list{\@biblabel{\@arabic\c@enumiv}}% + {\settowidth\labelwidth{\@biblabel{#1}}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep + \@openbib@code + \usecounter{enumiv}% + \let\p@enumiv\@empty + \renewcommand\theenumiv{\@arabic\c@enumiv}}% + \sloppy + \clubpenalty4000 + \@clubpenalty \clubpenalty + \widowpenalty4000% + \sfcode`\.\@m} + {\def\@noitemerr + {\@latex@warning{Empty `thebibliography' environment}}% + \endlist} + +\makeatother diff --git a/doc/rust-tutorial/rust-tutorial-after.tex b/doc/rust-tutorial/rust-tutorial-after.tex new file mode 100644 index 0000000000..aae03f4149 --- /dev/null +++ b/doc/rust-tutorial/rust-tutorial-after.tex @@ -0,0 +1,4 @@ +\newpage +\bibliography{sawScriptRustTutorial} +\addcontentsline{toc}{section}{References} +\bibliographystyle{abbrv} diff --git a/doc/rust-tutorial/rust-tutorial-before.html b/doc/rust-tutorial/rust-tutorial-before.html new file mode 100644 index 0000000000..2ce0a49c74 --- /dev/null +++ b/doc/rust-tutorial/rust-tutorial-before.html @@ -0,0 +1 @@ + diff --git a/doc/rust-tutorial/rust-tutorial-before.tex b/doc/rust-tutorial/rust-tutorial-before.tex new file mode 100644 index 0000000000..2a8b21e849 --- /dev/null +++ b/doc/rust-tutorial/rust-tutorial-before.tex @@ -0,0 +1 @@ +\maketitle diff --git a/doc/rust-tutorial/rust-tutorial-head.tex b/doc/rust-tutorial/rust-tutorial-head.tex new file mode 100644 index 0000000000..a38a1e6da2 --- /dev/null +++ b/doc/rust-tutorial/rust-tutorial-head.tex @@ -0,0 +1,60 @@ +\usepackage{listings} +\usepackage{float} +\usepackage{xspace} +\usepackage{color} +\usepackage{tikz} +\usepackage{url} +\usepackage{amsmath} +\usepackage{amscd} +\usepackage{verbatim} +\usepackage{fancyvrb} + +\let\verbatiminput=\verbatimtabinput +\VerbatimFootnotes +\DefineVerbatimEnvironment{code}{Verbatim}{} +\DefineVerbatimEnvironment{pseudoCode}{Verbatim}{} +\hyphenation{SAW-Script} +\newcommand{\sawScript}{{\sc SAWScript}\xspace} +\renewcommand{\textfraction}{0.05} +\renewcommand{\topfraction}{0.95} +\renewcommand{\bottomfraction}{0.95} +\renewcommand{\floatpagefraction}{0.35} +\setcounter{totalnumber}{5} +\definecolor{MyGray}{rgb}{0.9,0.9,0.9} +\makeatletter\newenvironment{graybox}{% + \begin{lrbox}{\@tempboxa}\begin{minipage}{\columnwidth}}{\end{minipage}\end{lrbox}% + \colorbox{MyGray}{\usebox{\@tempboxa}} +}\makeatother + +\setlength{\parskip}{0.6em} +\setlength{\abovecaptionskip}{0.5em} + +\lstset{ + basicstyle=\footnotesize\ttfamily, % Standardschrift + %numbers=left, % Ort der Zeilennummern + numberstyle=\tiny, % Stil der Zeilennummern + %stepnumber=2, % Abstand zwischen den Zeilennummern + numbersep=5pt, % Abstand der Nummern zum Text + tabsize=2, % Groesse von Tabs + extendedchars=true, % + breaklines=true, % Zeilen werden Umgebrochen + keywordstyle=\color{red}, + frame=lrtb, % left, right, top, bottom frames. + % keywordstyle=[1]\textbf, % Stil der Keywords + % keywordstyle=[2]\textbf, % + % keywordstyle=[3]\textbf, % + % keywordstyle=[4]\textbf, \sqrt{\sqrt{}} % + stringstyle=\color{white}\ttfamily, % Farbe der String + showspaces=false, % Leerzeichen anzeigen ? + showtabs=false, % Tabs anzeigen ? + xleftmargin=10pt, % was 17 + xrightmargin=5pt, + framexleftmargin=5pt, % was 17 + framexrightmargin=-1pt, % was 5pt + framexbottommargin=4pt, + %backgroundcolor=\color{lightgray}, + showstringspaces=false % Leerzeichen in Strings anzeigen ? +} + +\author{The Galois SAW Team\\\texttt{saw@galois.com}} +\title{SAWScript Rust Tutorial} diff --git a/doc/rust-tutorial/rust-tutorial.md b/doc/rust-tutorial/rust-tutorial.md new file mode 100644 index 0000000000..e023cf5b72 --- /dev/null +++ b/doc/rust-tutorial/rust-tutorial.md @@ -0,0 +1,3155 @@ +# A tutorial on Rust verification with SAW + +SAW is a special-purpose programming environment developed by Galois to help +orchestrate and track the results of the large collection of proof tools +necessary for analysis and verification of complex software artifacts. + +SAW adopts the functional paradigm, and largely follows the structure of many +other typed functional languages, with some special features specifically +targeted at the coordination of verification and analysis tasks. + +This tutorial introduces the details of the language by walking through several +examples, and showing how simple verification tasks can be described. The +complete examples are available [on +GitHub](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code). +Most of the examples make use of inline specifications written in Cryptol, a +language originally designed for high-level descriptions of cryptographic +algorithms. For readers unfamiliar with Cryptol, various documents describing +its use are available [here](http://cryptol.net/documentation.html). + +This tutorial also include a [case study](#case-study-salsa20) on how to use +SAW to verify a real-world implementation of the Salsa20 stream cipher based on +the [`stream-ciphers`](https://github.com/RustCrypto/stream-ciphers) Rust +project. The code for this case study is also available [on +GitHub](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20). + +## Prerequisites + +In order to run the examples in this tutorial, you will need to install the +following prerequisite tools: + +* SAW itself, which can be installed by following the instructions + [here](https://github.com/GaloisInc/saw-script#manual-installation). +* The Z3 and Yices SMT solvers. Z3 can be downloaded from + [here](https://github.com/Z3Prover/z3/releases), and Yices can be downloaded + from [here](https://yices.csl.sri.com/). +* The `mir-json` tool, which can be installed by following the instructions + [here](https://github.com/GaloisInc/mir-json#installation-instructions). + +## About `mir-json` + +We are interested in verifying code written in Rust, but Rust is an extremely +rich programming language that has many distinct language features. To make the +process of verifying Rust simpler, SAW targets an intermediate language used in +the Rust compiler called [MIR](https://blog.rust-lang.org/2016/04/19/MIR.html) +(short for "Mid-level IR"). MIR takes the variety of different features and +syntactic extensions in Rust and boils them down to a minimal subset that is +easier for a computer program to analyze. + +The process of extracting MIR code that is suitable for SAW's needs is somewhat +tricky, so we wrote a suite of tools called `mir-json` to automate this +process. `mir-json` provides a plugin for tools like `rustc` and `cargo` that +lets you compile Rust code as you normally would and produce an additional +`.json` file as output. This `.json` file contains the MIR code that was +produced internally by the Rust compiler, with some additional minor tweaks to +make it suitable for SAW's needs. + +`mir-json` is not a single tool but rather a suite of related tools that +leverage the same underlying plugin. For SAW purposes, the two `mir-json` tools +that are most relevant are: + +* `saw-rustc`: A thin wrapper around `rustc` (the Rust compiler), which is + suitable for individual `.rs` files. +* `cargo-saw-build`: A thin wrapper around the `cargo build` command, which is + suitable for `cargo`-based Rust projects. + +Most of the examples in this tutorial involve self-contained examples, which +will use `saw-rustc`. Later in the tutorial, we will examine a Salsa20 case +study that involves a `cargo`-based project, which will use `cargo-saw-build`. + +### A first example with `saw-rustc` + +Let's try out `saw-rustc` on a small example file, which we'll name +`first-example.rs`: + +``` {.rs} +$include all code/first-example.rs +``` + +This is the identity function, but specialized to the type `u8`. We can compile +this with `saw-rustc` like so: + +``` +$ saw-rustc first-example.rs + +note: Emitting MIR for first_example/abef32c5::id_u8 + +linking 1 mir files into first-example.linked-mir.json + +``` + +`saw-rustc` prints out some additional information that `rustc` alone does not +print, and we have displayed the parts of this information that are most +interesting. In particular: + +* `saw-rustc` notes that is is `Emitting MIR for first_example/abef32c5::id_u8`, + where `first_example/abef32c5::id_u8` is the full _identifier_ used to uniquely + refer to the `id_u8` function. It's entirely possible that the `abef32c5` + bit will look different on your machine; we'll talk more about identifiers in + the "Identifiers" section. +* Once `saw-rustc` produced a MIR JSON file named + `first-example.linked-mir.json`. This is an important bit of information, as + SAW will ingest this JSON file. + +If you'd like, you can inspect the `first-example.linked-mir.json` file with +JSON tools (e.g., [`jq`](https://jqlang.github.io/jq/)), but it is not +important to understand everything that is going on there. This is +machine-generated JSON, and as such, it is not meant to be particularly +readable by human eyes. + +### The `SAW_RUST_LIBRARY_PATH` environment variable + +Rust has a large set of standard libraries that ship with the compiler, and +parts of the standard library are quite low-level and tricky. SAW's primary +objective is to provide a tool that can analyze code in a tractable way. For +this reason, SAW sometimes needs to invoke simplified versions of Rust standard +library functions that are more reasonable for an SMT-based tool like SAW to +handle. These simplified functions are equivalent in behavior, but avoid using +problematic code patterns (e.g., gnarly pointer arithmetic or the +[`transmute`](https://doc.rust-lang.org/std/intrinsics/fn.transmute.html) +function). + +If you are only ever compiling self-contained pieces of code with `saw-rustc`, +there is a good chance that you can get away without needing to use SAW's +custom version of the Rust standard libraries. However, if you ever need to +build something more complicated than that (e.g., the Salsa20 case study later +in this tutorial), then you _will_ need the custom libraries. For this reason, +it is worthwhile to teach SAW the location of the custom libraries now. + +At present, the best way to obtain the custom version of the Rust standard +libraries is to perform the following steps: + +1. Clone the [`crucible`](https://github.com/GaloisInc/crucible) repo like so: + + ``` + $ git clone https://github.com/GaloisInc/crucible + ``` + +2. Navigate to the + [`crux-mir`](https://github.com/GaloisInc/crucible/tree/master/crux-mir) + subdirectory of the `crucible` checkout: + + ``` + $ cd crucible/crux-mir/ + ``` + +3. Run the `translate_libs.sh` script: + + ``` + $ ./translate_libs.sh + ``` + + This will compile the custom versions of the Rust standard libraries using + `mir-json`, placing the results under the `rlibs` subdirectory. + +4. Finally, define a `SAW_RUST_LIBRARY_PATH` environment variable that points + to the newly created `rlibs` subdirectory: + + ``` + $ export SAW_RUST_LIBRARY_PATH=<...>/crucible/crux-mir/rlibs + ``` + +An upcoming release of SAW will include these custom libraries pre-built, which +will greatly simplify the steps above. Either way, you will need to set the +`SAW_RUST_LIBRARY_PATH` environment variable to point to the location of the +custom libraries. + +### A note about generics + +The `id_u8` function above is likely not how most Rust programmers would define +the identity function. Instead, it would seem more natural to define it +generically, that is, by parameterizing the function by a type parameter: + +``` {.rs} +$include all code/generics-take-1.rs +``` + +If you compile this with `saw-rustc`, however, the resulting JSON file will +lack a definition for `id`! We can see this by using `jq`: + +``` +$ saw-rustc generics-take-1.rs + +$ jq . generics-take-1.linked-mir.json +{ + "fns": [], + "adts": [], + "statics": [], + "vtables": [], + "traits": [], + "intrinsics": [], + "tys": [], + "roots": [] +} +``` + +What is going on here? This is the result of an important design choice that +SAW makes: _SAW only supports verifying monomorphic functions_. To be more +precise, SAW's approach to symbolic simulation requires all of the code being +simulated to have fixed types without any type parameters. + +In order to verify a function using generics in your Rust code, you must +provide a separate, monomorphic function that calls into the generic function. +For example, you can rewrite the example above like so: + +``` {.rs} +$include all code/generics-take-2.rs +``` + +If you compile this version with `saw-rustc`, you'll see: + +``` +$ saw-rustc generics-take-2.rs + +note: Emitting MIR for generics_take_2/8b1bf337::id_u8 + +note: Emitting MIR for generics_take_2/8b1bf337::id::_instaddce72e1232152c[0] + +linking 1 mir files into generics-take-2.linked-mir.json + +``` + +This time, the resulting JSON file contains a definition for `id_u8`. The +reason that this works is because when `id_u8` calls `id`, the Rust compile +will generate a specialized version of `id` where `A` is instantiated with the +type `u8`. This specialized version of `id` is named +`id::_instaddce72e1232152c[0]` in the output above. (You don't have to remember +this name, thankfully!) + +Although the resulting JSON file contains a definition for `id_u8`, it does +_not_ contain a definition for the generic `id` function. As a result, SAW will +only be able to verify the `id_u8` function from this file. If you are ever in +doubt about which functions are accessible for verification with SAW, you can +check this with `jq .roots` like so: + +``` +$ jq .roots generics-take-2.linked-mir.json +[ + "generics_take_2/8b1bf337::id_u8" +] +``` + +Here, "roots" can be thought of as entrypoints that are visible to SAW. Note +that `saw-rustc` will optimize away all definitions that are not accessible +from one of the roots. This explains why the original program that only defined +a generic `id` function resulted in a definition-less JSON file, as that +program did not contain any roots. + +### Identifiers + +When you compile a function named `id_u8`, `saw-rustc` will expand it to a much +longer name such as `first_example/abef32c5::id_u8`. This longer name is called +an _identifier_, and it provides a globally unique name for that function. In +the small examples we've seen up to this point, there hasn't been any risk of +name collisions, but you could imagine compiling this code alongside another +file (or crate) that also defines an `id_u8` function. If that happens, then it +is essential that we can tell apart all of the different `id_u8` functions, and +identifiers provide us the mechanism for doing so. + +Let's take a closer look at what goes into an identifier. In general, an identifier +will look like the following: + +* `/::` + +`` is the name of the crate in which the function is defined. All +of the examples we've seen up to this point have been defined in standalone +files, and as a result, the crate name has been the same as the file name, but +without the `.rs` extension and with all hyphens replaced with underscores +(e.g., `first-example.rs` is given the crate name `first_example`). In +`cargo`-based projects, the crate name will likely differ from the file name. + +`` is a hash of the crate and its dependencies. In extreme +cases, it is possible for two different crates to have identical crate names, +in which case the disambiguator must be used to distinguish between the two +crates. In the common case, however, most crate names will correspond to +exactly one disambiguator. (More on this in a bit.) + +`` is the path to the function within the crate. Sometimes, this +is as simple as the function name itself. In other cases, a function path may +involve multiple _segments_, depending on the module hierarchy for the program +being verified. For instance, a `read` function located in +`core/src/ptr/mod.rs` will have the identifier: + +``` +core/::ptr::read +``` + +Where `core` is the crate name and `ptr::read` is the function path, which +has two segments `ptr` and `read`. There are also some special forms of +segments that appear for functions defined in certain language constructs. +For instance, if a function is defined in an `impl` block, then it will have +`{impl}` as one of its segments, e.g., + +``` +core/::ptr::const_ptr::{impl}::offset +``` + +The most cumbersome part of writing an identifier is the disambiguator, as it +is extremely sensitive to changes in the code (not to mention hard to remember +and type). Luckily, the vast majority of crate names correspond to exactly one +disambiguator, and we can exploit this fact to abbreviate identifiers that live +in such crates. For instance, we can abbreviate this identifier: + +``` +core/::ptr::read +``` + +To simply: + +``` +core::ptr::read +``` + +We will adopt the latter, shorter notation throughout the rest of the tutorial. +SAW also understands this shorthand, so we will also use this notation when +passing identifiers to SAW commands. + +## SAW basics + +### A first SAW example + +We now have the knowledge necessary to compile Rust code in a way that is +suitable for SAW. Let's put our skills to the test and verify something! We will +build on the example from above, which we will put into a file named +`saw-basics.rs`: + +``` {.rs} +$include all code/saw-basics.rs +``` + +Our goal is to verify the correctness of the `id_u8` function. However, it is +meaningless to talk about whether a function is correct without having a +_specification_ for how the function should behave. This is where SAW enters +the picture. SAW provides a scripting language named _SAWScript_ that allows +you to write a precise specification for describing a function's behavior. For +example, here is a specification that captures the intended behavior of +`id_u8`: + +``` +$include 3-7 code/saw-basics.saw +``` + +At a high level, this specification says that `id_u8` is a function that accepts +a single argument of type `u8`, and it returns its argument unchanged. Nothing +too surprising there, but this example illustrates many of the concepts that one +must use when working with SAW. Let's unpack what this is doing, line by line: + +* In SAWScript, specifications are ordinary values that are defined with `let`. + In this example, we are defining a specification named `id_u8_spec`. +* Specifications are defined using "`do`-notation". That is, they are assembled + by writing `do { ; ; ...; ; }`, where each `` is a + statement that declares some property about the function being verified. A + statement can optionally bind a variable that can be passed to later + statements, which is accomplished by writing ` <- `. +* The `x <- mir_fresh_var "x" mir_u8;` line declares that `x` is a fresh + variable of type `u8` (represented by `mir_u8` in SAWScript) that has some + unspecified value. In SAW parlance, we refer to these unspecified values as + _symbolic_ values. SAW uses an SMT solver under the hood to reason about + symbolic values. + + The `"x"` string indicates what name the variable `x` should have when sent + to the underlying SMT solver. This is primarily meant as a debugging aid, and + it is not required that the string match the name of the SAWScript variable. + (For instance, you could just as well have passed `"x_smt"` or something + else.) +* The `mir_execute_func [mir_term x];` line declares that the function should + be invoked with `x` as the argument. For technical reasons, we pass + `mir_term x` to `mir_execute_func` rather than just `x`; we will go over what + `mir_term` does later in the tutorial. +* Finally, the `mir_return (mir_term x);` line declares that the function should + return `x` once it has finished. + +Now that we have a specification in hand, it's time to prove that `id_u8` +actually adheres to the spec. To do so, we need to load the MIR JSON version of +`id_u8` into SAW, which is done with the `mir_load_module` command: + +``` +$include 9-9 code/saw-basics.saw +``` + +This `m` variable contains the definition of `id_u8`, as well as the other code +defined in the program. We can then pass `m` to the `mir_verify` command, which +actually verifies that `id_u8` behaves according to `id_u8_spec`: + +``` +$include 11-11 code/saw-basics.saw +``` + +Here is what is going on in this command: + +* The `m` and `"saw_basics::id_u8"` arguments instruct SAW to verify the + `id_u8` function located in the `saw_basics` crate defined in `m`. Note that + we are using the shorthand identifier notation here, so we are allowed to omit + the disambiguator for the `saw_basics` crate. +* The `[]` argument indicates that we will not provide any function overrides to + use when SAW simulates the `id_u8` function. (We will go over how overrides + work later in the tutorial.) +* The `false` argument indicates that SAW should not use path satisfiability + checking when analyzing the function. Path satisfiability checking is an + advanced SAW feature that we will not be making use of in this tutorial, so we + will always use `false` here. +* The `id_u8_spec` argument indicates that `id_u8` should be checked against the + specification defined by `id_u8_spec`. +* The `z3` argument indicates that SAW should use the Z3 SMT solver to solve + any proof goals that are generated during verification. SAW also supports + other SMT solvers, although we will mostly use Z3 in this tutorial. + +Putting this all together, our complete `saw-basics.saw` file is: + +``` +$include all code/saw-basics.saw +``` + +One minor detail that we left out until just now is that the SAW's interface to +MIR is still experimental, so you must explicitly opt into it with the +`enable_experimental` command. + +Now that everything is in place, we can check this proof like so: + +``` +$ saw saw-basics.saw + + + +[16:14:07.006] Loading file "saw-basics.saw" +[16:14:07.009] Verifying saw_basics/f77ebf43::id_u8[0] ... +[16:14:07.017] Simulating saw_basics/f77ebf43::id_u8[0] ... +[16:14:07.017] Checking proof obligations saw_basics/f77ebf43::id_u8[0] ... +[16:14:07.017] Proof succeeded! saw_basics/f77ebf43::id_u8[0] +``` + +Tada! SAW was successfully able to prove that `id_u8` adheres to its spec. + +### Cryptol + +The spec in the previous section is nice and simple. It's also not very +interesting, as it's fairly obvious at a glance that `id_u8`'s implementation +is correct. Most of the time, we want to verify more complicated functions +where the correspondence between the specification and the implementation is +not always so clear. + +For example, consider this function, which multiplies a number by two: + +``` {.rs} +$include 1-3 code/times-two.rs +``` + +The straightforward way to implement this function would be to return `2 * x`, +but the author of this function _really_ cared about performance. As such, the +author applied a micro-optimization that computes the multiplication with a +single left-shift (`<<`). This is the sort of scenario where we are pretty sure +that the optimized version of the code is equivalent to the original version, +but it would be nice for SAW to check this. + +Let's write a specification for the `times_two` function: + +``` +$include 3-7 code/times-two.saw +``` + +This spec introduces code delimited by double curly braces `{{ ... }}`, which +is a piece of syntax that we haven't seen before. The code in between the curly +braces is written in [Cryptol](http://cryptol.net/documentation.html), a +language designed for writing high-level specifications of various algorithms. +Cryptol supports most arithmetic operations, so `2 * x` works exactly as you +would expect. Also note that the `x` variable was originally bound in the +SAWScript language, but it is possible to embed `x` into the Cryptol language +by referencing `x` within the curly braces. (We'll say more about how this +embedding works later.) + +`{{ 2 * x }}` takes the Cryptol expression `2 * x` and lifts it to a SAW +expression. As such, this SAW spec declares that the function takes a single +`u32`-typed argument `x` and returns `2 * x`. We could have also wrote the +specification to declare that the function returns `x << 1`, but that would +have defeated the point of this exercise: we specifically want to check that +the function against a spec that is as simple and readable as possible. + +Our full SAW file is: + +``` +$include 1-11 code/times-two.saw +``` + +Which we can verify is correct like so: + +``` +$ saw times-two.saw + + + +[17:51:35.469] Loading file "times-two.saw" +[17:51:35.497] Verifying times_two/6f4e41af::times_two[0] ... +[17:51:35.512] Simulating times_two/6f4e41af::times_two[0] ... +[17:51:35.513] Checking proof obligations times_two/6f4e41af::times_two[0] ... +[17:51:35.527] Proof succeeded! times_two/6f4e41af::times_two[0] +``` + +Nice! Even though the `times_two` function does not literally return `2 * x`, +SAW is able to confirm that the function behaves as if it were implemented that +way. + +### `Term`s and other types + +Now that we know how Cryptol can be used within SAW, we can go back and explain +what the `mir_term` function does. It is helpful to examine the type of +`mir_term` by using SAW's interactive mode. To do so, run the `saw` binary +without any other arguments: + +``` +$ saw +``` + +Then run `enable_experimental` (to enable MIR-related commands) and run `:type +mir_term`: + +``` +sawscript> enable_experimental +sawscript> :type mir_term +Term -> MIRValue +``` + +Here, we see that `mir_term` accepts a `Term` as an argument and returns a +`MIRValue`. In this context, the `Term` type represents a Cryptol value, and +the `MIRValue` type represents SAW-related MIR values. `Term`s can be thought +of as a subset of `MIRValue`s, and the `mir_term` function is used to promote a +`Term` to a `MIRValue`. + +Most other MIR-related commands work over `MIRValue`s, as can be seen with +SAW's `:type` command: + +``` +sawscript> :type mir_execute_func +[MIRValue] -> MIRSetup () +sawscript> :type mir_return +MIRValue -> MIRSetup () +``` + +Note that `MIRSetup` is the type of statements in a MIR specification, and two +`MIRSetup`-typed commands can be chained together by using `do`-notation. +Writing `MIRSetup ()` means that the statement does not return anything +interesting, and the use of `()` here is very much analogous to how `()` is +used in Rust. There are other `MIRSetup`-typed commands that _do_ return +something interesting, as is the case with `mir_fresh_var`: + +``` +sawscript> :type mir_fresh_var +String -> MIRType -> MIRSetup Term +``` + +This command returns a `MIRSetup Term`, which means that when you write `x <- +mir_fresh_var ... ...` in a MIR specification, then `x` will be bound at type +`Term`. + +Values of type `Term` have the property that they can be embedded into Cryptol +expression that are enclosed in double curly braces `{{ ... }}`. This is why +our earlier `{{ 2 * x }}` example works, as `x` is of type `Term`. + +### Preconditions and postconditions + +As a sanity check, let's write a naïve version of `times_two` that explicitly +returns `2 * x`: + +``` {.rs} +$include 5-7 code/times-two.rs +``` + +It seems like we should be able to verify this `times_two_ref` function using +the same spec that we used for `times_two`: + +``` +$include 11-11 code/times-two-ref-fail.saw +``` + +Somewhat surprisingly, SAW fails to verify this function: + +``` +$ saw times-two-ref-fail.saw + + + +[18:58:22.578] Loading file "times-two-ref-fail.saw" +[18:58:22.608] Verifying times_two/56182919::times_two_ref[0] ... +[18:58:22.621] Simulating times_two/56182919::times_two_ref[0] ... +[18:58:22.622] Checking proof obligations times_two/56182919::times_two_ref[0] ... +[18:58:22.640] Subgoal failed: times_two/56182919::times_two_ref[0] attempt to compute `const 2_u32 * move _2`, which would overflow +[18:58:22.640] SolverStats {solverStatsSolvers = fromList ["SBV->Z3"], solverStatsGoalSize = 375} +[18:58:22.640] ----------Counterexample---------- +[18:58:22.640] x: 2147483648 +[18:58:22.640] Stack trace: +"mir_verify" (times-two-ref-fail.saw:11:1-11:11) +Proof failed. +``` + +The "`which would overflow`" portion of the error message suggests what went +wrong. When a Rust program is compiled with debug settings (which is the +default for `rustc` and `saw-rustc`), arithmetic operations such as +multiplication will check if the result of the operation can fit in the +requested number of bits. If not, the program will raise an error. + +In this case, we must make the result of multiplication fit in a `u32`, which +can represent values in the range `0` to `2^^32 - 1` (where `^^` is Cryptol's +exponentiation operator). But it is possible to take a number in this range, +multiply it by two, and have the result fall outside of the range. In fact, SAW +gives us a counterexample with exactly this number: `2147483648`, which can +also be written as `2^^31`. Multiplying this by two yields `2^^32`, which is +just outside of the range of values expressible with `u32`. SAW's duties +include checking that a function cannot fail at runtime, so this function falls +afoul of that check. + +Note that we didn't have this problem with the original definition of +`times_two` because the semantics of `<<` are such that if the result is too +large to fit in the requested type, then the result will _overflow_, i.e., wrap +back around to zero and count up. This means that `(2^^31) << 1` evaluates to +`0` rather than raising an error. Cryptol's multiplication operation also +performs integer overflow (unlike Rust in debug settings), which is why we +didn't notice any overflow-related issues when verifying `times_two`. + +There are two possible ways that we can repair this. One way is to rewrite +`times_two_ref` to use Rust's +[`wrapping_mul`](https://doc.rust-lang.org/std/primitive.u32.html#method.wrapping_mul) +function, a variant of multiplication that always uses integer overflow. This +work around the issue, but it is a bit more verbose. + +The other way is to make our spec more precise such that we only verify +`times_two_ref` for particular inputs. Although `times_two_ref` will run into +overflow-related issues when the argument is `2^^31` or greater, it is +perfectly fine for inputs smaller than `2^^31`. We can encode such an +assumption in SAW by adding a _precondition_. To do so, we write a slightly +modified version of `times_two_spec`: + +``` +$include 13-18 code/times-two.saw +``` + +The most notable change is the `mir_precond {{ x < 2^^31 }};` line. +`mir_precond` (where "`precond`" is short for "precondition") is a command that +takes a `Term` argument that contains a boolean predicate, such as `{{ x < +2^^31 }}`. Declaring a precondition requires that this predicate must hold +during verification, and any values of `x` that do not satisfy this predicate +are not considered. + +By doing this, we have limited the range of the function from `0` to `2^^31 - +1`, which is exactly the range of values for which `times_two_ref` is well +defined. SAW will confirm this if we run it: + +``` +$include 20-20 code/times-two.saw +``` +``` +[19:23:53.480] Verifying times_two/56182919::times_two_ref[0] ... +[19:23:53.496] Simulating times_two/56182919::times_two_ref[0] ... +[19:23:53.497] Checking proof obligations times_two/56182919::times_two_ref[0] ... +[19:23:53.531] Proof succeeded! times_two/56182919::times_two_ref[0] +``` + +We can add as many preconditions to a spec as we see fit. For instance, if we +only want to verify `times_two_ref` for positive integers, we could add an +additional assumption: + +``` +$include 22-28 code/times-two.saw +``` + +In addition to preconditions, SAW also supports postconditions. Whereas +preconditions represent conditions that must hold _before_ invoking a function, +postconditions represent conditions that must hold _after_ invoking a function. +We have already seen one type of postcondition in the form of the `mir_return` +command, which imposes a postcondition on what the return value must be equal +to. + +We can introduce additional postconditions with the `mir_postcond` command. +For example, if we call `times_two_ref` with a positive argument, then it +should be the case that the return value should be strictly greater than the +argument value. We can check for this using `mir_postcond` like so: + +``` +$include 32-39 code/times-two.saw +``` + +An additional convenience that SAW offers is the `mir_assert` command. +`mir_assert` has the same type as `mir_precond` and `mir_postcond`, but +`mir_assert` can be used to declare both preconditions _and_ postconditions. +The difference is where `mir_assert` appears in a specification. If +`mir_assert` is used before the call to `mir_execute_func`, then it declares a +precondition. If `mir_assert` is used after the call to `mir_execute_func`, +then it declares a postcondition. + +For example, we can rewrite `times_two_ref_positive_postcond_spec` to use +`mir_assert`s like so: + +``` +$include 43-50 code/times-two.saw +``` + +The choice of whether to use `mir_precond`/`mir_postcond` versus `mir_assert` is +mostly a matter personal taste. + +## Reference types + +All of the examples we have seen up to this point involve simple integer types +such as `u8` and `u32`. While these are useful, Rust's type system features +much more than just integers. A key part of Rust's type system are its +reference types. For example, in this `read_ref` function: + +``` {.rs} +$include 1-3 code/ref-basics.rs +``` + +The function reads the value that `r` (of type `&u32`) points to and returns +it. Writing SAW specifications involving references is somewhat trickier than +with other types of values because we must also specify what memory the +reference points to. SAW provides a special command for doing this called +`mir_alloc`: + +``` +sawscript> :type mir_alloc +MIRType -> MIRSetup MIRValue +``` + +`mir_alloc` will allocate a reference value with enough space to hold a value +of the given `MIRType`. Unlike `mir_fresh_var`, `mir_alloc` returns a +`MIRValue` instead of a `Term`. We mentioned before that `Term`s are only a +subset of `MIRValue`s, and this is one of the reasons why. Cryptol does not +have a notion of reference values, but `MIRValue`s do. As a result, you cannot +embed the result of a call to `mir_alloc` in a Cryptol expression. + +`mir_alloc` must be used with some care. Here is a first, not-quite-correct +attempt at writing a spec for `read_ref` using `mir_alloc`: + +``` +$include 3-11 code/ref-basics-fail.saw +``` + +As the comment suggests, it's not entirely clear what this spec should return. +We can't return `r`, since `read_ref` returns something of type `u32`, not +`&u32`. On the other hand, we don't have any values of type `u32` lying around +that are obviously the right thing to use here. Nevertheless, it's not required +for a SAW spec to include a `mir_return` statement, so let's see what happens +if we verify this as-is: + +``` +$ saw ref-basics-fail.saw + + + +[20:13:27.224] Loading file "ref-basics-fail.saw" +[20:13:27.227] Verifying ref_basics/54ae7b63::read_ref[0] ... +[20:13:27.235] Simulating ref_basics/54ae7b63::read_ref[0] ... +[20:13:27.235] Stack trace: +"mir_verify" (ref-basics-fail.saw:11:1-11:11) +Symbolic execution failed. +Abort due to assertion failure: + ref-basics.rs:2:5: 2:7: error: in ref_basics/54ae7b63::read_ref[0] + attempted to read empty mux tree +``` + +Clearly, SAW didn't like what we gave it. The reason this happens is although +we allocated memory for the reference `r`, we never told SAW what value should +live in that memory. When SAW simulated the `read_ref` function, it attempted +to dereference `r`, which pointed to uninitialized memory. This is constitutes +an error in SAW, which is what this "`attempted to read empty mux tree`" +business is about. + +SAW provides a `mir_points_to` command to declare what value a reference should +point to: + +``` +sawscript> :type mir_points_to +MIRValue -> MIRValue -> MIRSetup () +``` + +Here, the first `MIRValue` argument represents a reference value, and the +second `MIRValue` argument represents the value that the reference should point +to. In our spec for `read_ref`, we can declare that the reference should point +to a symbolic `u32` value like so: + +``` +$include 3-9 code/ref-basics.saw +``` + +We have renamed `r` to `r_ref` in this revised spec to more easily distinguish +it from `r_val`, which is the value that `r_ref` is declared to point to using +`mir_points_to`. In this version of the spec, it is clear that we should return +`r_val` using `mir_return`, as `r_val` is exactly the value that will be +computed by dereferencing `r_ref`. + +This pattern, where a call to `mir_alloc`/`mir_alloc_mut` to followed by a call +to `mir_points_to`, is common with function specs that involve references. +Later in the tutorial, we will see other examples of `mir_points_to` where the +reference argument does not come from `mir_alloc`/`mir_alloc_mut`. + +The argument to `read_ref` is an immutable reference, so the implementation of +the function is not allowed to modify the memory that the argument points to. +Rust also features mutable references that do permit modifying the underlying +memory, as seen in this `swap` function: + +``` {.rs} +$include 5-11 code/ref-basics.rs +``` + +A corresponding spec for `swap` is: + +``` +$include 15-28 code/ref-basics.saw +``` + +There are two interesting things worth calling out in this spec: + +1. Instead of allocating the reference values with `mir_alloc`, we instead use + `mir_alloc_mut`. This is a consequence of the fact that `&mut u32` is a + different type from `&mut` in Rust (and in MIR), and and such, we need a + separate `mir_alloc_mut` to get the types right. +2. This spec features calls to `mir_points_to` before _and_ after + `mir_execute_func`. This is because the values that `a_ref` and `b_ref` point + to before calling the function are different than the values that they point + to after calling the function. The two uses to `mir_points_to` after the + function has been called swap the order of `a_val` and `b_val`, reflecting + the fact that the `swap` function itself swaps the values that the references + point to. + +## Compound data types + +Besides integer types and reference types, Rust also features a variety of other +interesting data types. This part of the tutorial will briefly go over some of +these data types and how to interface with them in SAW. + +### Array types + +Rust includes array types where the length of the array is known ahead of time. +For instance, this `index` function takes an `arr` argument that must contain +exactly three `u32` values: + +``` {.rs} +$include 1-3 code/arrays.rs +``` + +While Rust is good at catching many classes of programmer errors at compile +time, one thing that it cannot catch in general is out-of-bounds array +accesses. In this `index` example, calling the function with a value of `idx` +ranging from `0` to `2` is fine, but any other choice of `idx` will cause the +program to crash, since the `idx` will be out of the bounds of `arr`. + +SAW is suited to checking for these sorts of out-of-bound accesses. Let's write +an incorrect spec for `index` to illustrate this: + +``` +$include 3-14 code/arrays-fail.saw +``` + +Before we run this with SAW, let's highlight some of the new concepts that this +spec uses: + +1. The type of the `arr` variable is specified using `mir_array 3 mir_u32`. + Here, the `mir_array` function takes the length of the array and the element + type as arguments, just as in Rust. +2. The spec declares the return value to be `{{ arr @ idx }}`, where `@` is + Cryptol's indexing operator. Also note that it is completely valid to embed + a MIR array type into a Cryptol expression, as Cryptol has a sequence type + that acts much like arrays do in MIR. + +As we hinted above, this spec is wrong, as it says that this should work for +_any_ possible values of `idx`. SAW will catch this mistake: + +``` +$ saw arrays-fail.saw + + + +[21:03:05.374] Loading file "arrays-fail.saw" +[21:03:05.411] Verifying arrays/47a26581::index[0] ... +[21:03:05.425] Simulating arrays/47a26581::index[0] ... +[21:03:05.426] Checking proof obligations arrays/47a26581::index[0] ... +[21:03:05.445] Subgoal failed: arrays/47a26581::index[0] index out of bounds: the length is move _4 but the index is _3 +[21:03:05.445] SolverStats {solverStatsSolvers = fromList ["SBV->Z3"], solverStatsGoalSize = 53} +[21:03:05.445] ----------Counterexample---------- +[21:03:05.445] idx: 2147483648 +[21:03:05.445] Stack trace: +"mir_verify" (arrays-fail.saw:14:1-14:11) +Proof failed. +``` + +We can repair this spec by adding some preconditions: + +``` +$include 3-12 code/arrays.saw +``` + +An alternative way of writing this spec is by using SAW's `mir_array_value` +command: + +``` +sawscript> :type mir_array_value +MIRType -> [MIRValue] -> MIRValue +``` + +Here, the `MIRType` argument represents the element type, and the list of +`MIRValue` arguments are the element values of the array. We can rewrite +`index_spec` using `mir_array_value` like so: + +``` +$include 18-30 code/arrays.saw +``` + +Here, `[arr0, arr1, arr2]` is Cryptol notation for constructing a length-3 +sequence consisting of `arr0`, `arr1`, and `arr2` as the elements. +`index_alt_spec` is equivalent to `index_spec`, albeit more verbose. For this +reason, it is usually preferable to use `mir_fresh_var` to create an entire +symbolic array rather than creating separate symbolic values for each element +and combining them with `mir_array_value`. + +There are some situations where `mir_array_value` is the only viable choice, +however. Consider this variant of the `index` function: + +``` {.rs} +$include 5-7 code/arrays.rs +``` + +When writing a SAW spec for `index_ref_arr`, we can't just create a symbolic +variable for `arr` using `mir_alloc (mir_array 3 ...)`, as the reference values +in the array wouldn't point to valid memory. Instead, we must individually +allocate the elements of `arr` using separate calls to `mir_alloc` and then +build up the array using `mir_array_value`. (As an exercise, try writing and +verifying a spec for `index_ref_arr`). + +### Tuple types + +Rust includes tuple types where the elements of the tuple can be of different +types. For example: + +``` {.rs} +$include 1-3 code/tuples.rs +``` + +SAW includes a `mir_tuple` function for specifying the type of a tuple value. +In addition, one can embed MIR tuples into Cryptol, as Cryptol also includes +tuple types whose fields can be indexed with `.0`, `.1`, etc. Here is a spec +for `flip` that makes use of all these features: + +``` +$include 3-9 code/tuples.saw +``` + +SAW also includes a `mir_tuple_value` function for constructing a tuple value +from other `MIRValue`s: + +``` +sawscript> :type mir_tuple_value +[MIRValue] -> MIRValue +``` + +`mir_tuple_value` plays a similar role for tuples as `mir_array_value` does for +arrays. + +### Struct types + +Rust supports the ability for users to define custom struct types. Structs are +uniquely identified by their names, so if you have two structs like these: + +``` {.rs} +$include 1-2 code/structs.rs +``` + +Then even though the fields of the `S` and `T` structs are the same, they are +_not_ the same struct. This is a type system feature that Cryptol does not +have, and for this reason, it is not possible to embed MIR struct values into +Cryptol. It is also not possible to use `mir_fresh_var` to create a symbolic +struct value. Instead, one can use the `mir_struct_value` command: + +``` +sawscript> :type mir_struct_value +MIRAdt -> [MIRValue] -> MIRValue +``` + +Like with `mir_array_value` and `mir_tuple_value`, the `mir_struct_value` +function takes a list of `MIRValue`s as arguments. What makes +`mir_struct_value` unique is its `MIRAdt` argument, which we have not seen up +to this point. In this context, "`Adt`" is shorthand for "[algebraic data +type](https://en.wikipedia.org/wiki/Algebraic_data_type)", and Rust's structs +are an example of ADTs. (Rust also supports enums, another type of ADT that we +will see later in this tutorial.) + +ADTs in Rust are named entities, and as such, they have unique identifiers in +the MIR JSON file in which they are defined. Looking up these identifiers can +be somewhat error-prone, so SAW offers a `mir_find_adt` command that computes +an ADT's identifier and returns the `MIRAdt` associated with it: + +``` +sawscript> :type mir_find_adt +MIRModule -> String -> [MIRType] -> MIRAdt +``` + +Here, `MIRModule` correspond to the MIR JSON file containing the ADT +definition, and the `String` is the name of the ADT whose identifier we want to +look up. The list of `MIRType`s represent types to instantiate any type +parameters to the struct (more on this in a bit). + +As an example, we can look up the `S` and `T` structs from above like so: + +``` +$include 3-6 code/structs.saw +``` + +We pass an empty list of `MIRType`s to each use of `mir_find_adt`, as neither +`S` nor `T` have any type parameters. An example of a struct that does include +type parameters can be seen here: + +``` {.rs} +$include 12-12 code/structs.rs +``` + +As mentioned before, SAW doesn't support generic definitions out of the box, so +the only way that we can make use of the `Foo` struct is by looking up a +particular instantiation of `Foo`'s type parameters. If we define a function +like this, for example: + +``` {.rs} +$include 14-16 code/structs.rs +``` + +Then this function instantiates `Foo`'s `A` type parameter with `u32` and the +`B` type parameter with `u64`. We can use `mir_find_adt` to look up this +particular instantiation of `Foo` like so: + +``` +$include 7-7 code/structs.saw +``` + +In general, a MIR JSON file can have many separate instantiations of a single +struct's type parameters, and each instantiation must be looked up separately +using `mir_find_adt`. + +Having looked up `Foo` using `mir_find_adt`, let's use the resulting +`MIRAdt` in a spec: + +``` +$include 9-18 code/structs.saw +``` + +Note that we are directly writing out the values `27` and `42` in Cryptol. +Cryptol's numeric literals can take on many different types, so in order to +disambiguate which type they should be, we give each numeric literal an +explicit type annotation. For instance, the expression `27 : [32]` means that +`27` should be a 32-bit integer. + +#### Symbolic structs + +Let's now verify a function that takes a struct value as an argument: + +``` {.rs} +$include 18-22 code/structs.rs +``` + +Moreover, let's verify this function for all possible `Bar` values. One way to +do this is to write a SAW spec that constructs a struct value whose fields are +themselves symbolic: + +``` +$include 20-38 code/structs.saw +``` + +This is a rather tedious process, however, as we had to repeatedly use +`mir_fresh_var` to create a fresh, symbolic value for each field. Moreover, +because `mit_fresh_var` does not work for structs, we had to recursively apply +this process in order to create a fresh `Foo` value. It works, but it takes a +lot of typing to accomplish. + +To make this process less tedious, SAW offers a `mir_fresh_expanded_value` +command that allows one to create symbolic values of many more types. While +`mir_fresh_var` is limited to those MIR types that can be directly converted to +Cryptol, `mir_fresh_expanded_value` can create symbolic structs by automating +the process of creating fresh values for each field. This process also applies +recursively for struct fields, such as the `Foo` field in `Bar`. + +As an example, a much shorter way to write the spec above using +`mir_fresh_expanded_value` is: + +``` +$include 42-48 code/structs.saw +``` + +That's it! Note that the string `"z"` is used as a prefix for all fresh names +that `mir_fresh_expanded_value` generates, so if SAW produces a counterexample +involving this symbolic struct value, one can expect to see names such as +`z_0`, `z_1`, etc. for the fields of the struct. + +### Enum types + +Besides structs, another form of ADT that Rust supports are enums. Each enum +has a number of different _variants_ that describe the different ways that an +enum value can look like. A famous example of a Rust enum is the `Option` type, +which is defined by the standard library like so: + +``` {.rs} +enum Option { + None, + Some(T), +} +``` + +`Option` is commonly used in Rust code to represent a value that may be present +(`Some`) or absent (`None`). For this reason, we will use `Option` as our +motivating example of an enum in this section. + +First, let's start by defining some functions that make use of `Option`'s +variants: + +``` {.rs} +$include 1-7 code/enums.rs +``` + +Both functions return an `Option` value, but each function returns a +different variant. In order to tell these variants apart, we need a SAW +function which can construct an enum value that allows the user to pick which +variant they want to construct. The `mir_enum_value function does exactly that: + +``` +sawscript> :type mir_enum_value +MIRAdt -> String -> [MIRValue] -> MIRValue +``` + +Like `mir_struct_value`, `mir_enum_value` also requires a `MIRAdt` argument in +order to discern which particular enum you want. Unlike `mir_struct_value`, +however, it also requires a `String` which variant of the enum you want. In the +case of `Option`, this `String` will either be `"None"` or `"Some"`. Finally, +the `[MIRValue]` arguments represent the fields of the enum variant. + +Let's now verify some enum-related code with SAW. First, we must look up the +`Option` ADT, which works just as if you had a struct type: + +``` +$include 5-5 code/enums.saw +``` + +Next, we can use this ADT to construct enum values. We shall use +`mir_enum_value` to create a `Some` value in the spec for `i_found_something`: + +``` +$include 7-16 code/enums.saw +``` + +Note that while we used the full identifier `core::option::Option` to look up +the `Option` ADT, we do not need to use the `core::option` prefix when +specifying the `"Some"` variant. This is because SAW already knows what the +prefix should be from the `option_u32` ADT, so the `"Some"` shorthand suffices. + +Similarly, we can also write a spec for `i_got_nothing`, which uses the `None` +variant: + +``` +$include 18-25 code/enums.saw +``` + +#### Symbolic enums + +In order to create a symbolic struct, one could create symbolic fields and pack +them into a larger struct value using `mir_struct_value`. The same process is +not possible with `mir_enum_value`, however, as a symbolic enum value would +need to range over _all_ possible variants in an enum. + +Just as `mir_fresh_expanded_value` supports creating symbolic structs, +`mir_fresh_expanded_value` also supports creating symbolic enum values. For +example, given this function that accepts an `Option` value as an +argument: + +``` {.rs} +$include 9-11 code/enums.rs +``` + +We can write a spec for this function that considers all possible `Option` +values like so: + +``` +$include 27-33 code/enums.saw +``` + +Here, `o` can be a `None` value, or it can be a `Some` value with a symbolic +field. + +### Slices + +Slices are a particular type of reference that allow referencing contiguous +sequences of elements in a collection, such as an array. Unlike ordinary +references (e.g., `&u32`), SAW does not permit allocating a slice directly. +Instead, one must take a slice of an existing reference. To better illustrate +this distinction, consider this function: + +``` {.rs} +$include 1-3 code/slices.rs +``` + +`sum_of_prefix` takes a slice to a sequence of `u32`s as an argument, indexes +into the first two elements in the sequence, and adds them together. There are +many possible ways we can write a spec for this function, as the slice argument +may be backed by many different sequences. For example, the slice might be +backed by an array whose length is exactly two: + +``` {.rs} +$include 6-8 code/slices.rs +``` + +We could also make a slice whose length is longer than two: + +``` {.rs} +$include 10-12 code/slices.rs +``` + +Alternatively, the slice might be a subset of an array whose length is longer +than two: + +``` {.rs} +$include 14-16 code/slices.rs +``` + +All of these are valid ways of building the slice argument to `sum_of_prefix`. +Let's try to write SAW specifications that construct these different forms of +slices. To do so, we will need SAW functions that take a reference to a +collection (e.g., an array) and converts them into a slice reference. The +`mir_slice_value` function is one such function: + +``` +sawscript> :type mir_slice_value +MIRValue -> MIRValue +``` + +`mir_slice_value arr_ref` is the SAW equivalent of writing `arr_ref[..]`. That +is, if `arr_ref` is of type `&[T; N]`, then `mir_slice_value arr_ref` is of +type `&[T]`. Note that `arr_ref` must be a _reference_ to an array, not an +array itself. + +Let's use `mir_slice_value` to write a spec for `sum_of_prefix` when the slice +argument is backed by an array of length two: + +``` +$include 5-15 code/slices.saw +``` + +The first part of this spec allocates an array reference `a_ref` and declares +that it points to a fresh array value `a_val`. The next part declares a slice +`s` that is backed by the entirety of `a_ref`, which is then passed as an +argument to the function itself. Finally, the return value is declared to be +the sum of the first and second elements of `a_val`, which are the same values +that back the slice `s` itself. + +As noted above, the `sum_of_prefix` function can work with slices of many +different lengths. Here is a slight modification to this spec that declares it +to take a slice of length 5 rather than a slice of length 2: + +``` +$include 9-19 code/slices.saw +``` + +Both of these examples declare a slice whose length matches the length of the +underlying array. In general, there is no reason that these have to be the +same, and it is perfectly fine for a slice's length to be less than the the +length of the underlying array. In Rust, for example, we can write a slice of a +subset of an array by writing `&arr_ref[0..2]`. The SAW equivalent of this can +be achieved with the `mir_slice_range_value` function: + +``` +sawscript> :type mir_slice_range_value +MIRValue -> Int -> Int -> MIRValue +``` + +`mir_slice_range_value` takes takes two additional `Int` arguments that +represent (1) the index to start the slice from, and (2) the index at which the +slice ends. For example, `mir_slice_range_value arr_ref 0 2` creates a slice +that is backed by the first element (index `0`) and the second element (index +`1`) of `arr_ref`. Note that the range `[0..2]` is half-open, so this range +does _not_ include the third element (index `2`). + +For example, here is how to write a spec for `sum_of_prefix` where the slice is +a length-2 subset of the original array: + +``` +$include 33-43 code/slices.saw +``` + +Note that both `Int` arguments to `mir_slice_range_value` must be concrete +(i.e., not symbolic). (See the section below if you want an explanation for why +they are not allowed to be symbolic.) + +#### Aside: slices of arbitrary length + +After reading the section about slices above, one might reasonably wonder: is +there a way to write a more general spec for `sum_of_prefix`: that covers all +possible slice lengths `n`, where `n` is greater than or equal to 2? In this +case, the answer is "no". + +This is a fundamental limitation of the way SAW's symbolic execution works. The +full reason for why this is the case is somewhat technical (keep reading if you +want to learn more), but the short answer is that if SAW attempts to +simulate code whose length is bounded by a symbolic integer, then SAW will go +into an infinite loop. To avoid this pitfall, the `mir_slice_range_value` +function very deliberately requires the start and end values to be concrete +integers, as allowing these values to be symbolic would allow users to +inadvertently introduce infinite loops in their specifications. + +A longer answer as to why SAW loops forever on computations that are bounded by +symbolic lengths: due to the way SAW's symblolic execution works, it creates a +complete model of the behavior of a function for all possible inputs. The way +that SAW achieves this is by exploring all possible execution paths through a +program. If a program involves a loop, for example, then SAW will unroll all +iterations of the loop to construct a model of the loop's behavior. Similarly, +if a sequence (e.g., a slice or array) has an unspecified length, then SAW must +consider all possible lengths of the array. + +SAW's ability to completely characterize the behavior of all paths through a +function is one of its strengths, as this allows it to prove theorems that +other program verification techniques would not. This strength is also a +weakness, however. If a loop has a symbolic number of iterations, for example, +then SAW will spin forever trying to unroll the loop. Similarly, if a slice +were to have a symbolic length, then SAW would spin forever trying to simulate +the program for all possible slice lengths. + +In general, SAW cannot prevent users from writing programs whose length is +bounded by a symbolic value. For now, however, SAW removes one potential +footgun by requiring that slice values always have a concrete length. + +## Overrides and compositional verification + +Up until this point, all uses of `mir_verify` in this tutorial have provided an +empty list (`[]`) of overrides. This means that any time SAW has simulated a +function which calls another function, it will step into the definition of the +callee function and verify its behavior alongside the behavior of the callee +function. This is a fine thing to do, but it can be inefficient. For example, +consider a function like this: + +``` {.rs} +$include 5-9 code/overrides.rs +``` + +Here, the caller function `f` invokes the callee function `g` three separate +times. If we verify `f` with `mir_verify` as we have done up until this point, +then SAW must analyze the behavior of `g` three separate times. This is +wasteful, and especially so if `g` is a large and complicated function. + +This is where _compositional verification_ enters the picture. The idea behind +compositional verification is that when we prove properties of a caller +function, we can reuse properties that we have already proved about callee +functions. These properties are captured as _override specifications_, which +are also referred to by the shorthand term _overrides_. When a caller invokes a +callee with a corresponding override specification, the override's properties +are applied without needing to re-simulate the entire function. + +As it turns out, the command needed to produce an override specification is +already familiar to us—it's `mir_verify`! If you examine the type of this +command: + +``` +sawscript> :type mir_verify +MIRModule -> String -> [MIRSpec] -> Bool -> MIRSetup () -> ProofScript () -> TopLevel MIRSpec +``` + +The returned value is a `MIRSpec`, which captures the behavior of the function +that was verified as an override spec. This override can then be passed to +another call to `mir_verify` to use as part of a larger proof. + +Let's now try compositional verification in practice. To do so, we will first +prove a spec for the `g` function above. For demonstration purposes, we will +pick a simplistic implementation of `g`: + +``` {.rs} +$include 1-3 code/overrides.rs +``` + +Note that we don't really _have_ to use compositional verification when `g` is +this simple, as SAW is capable of reasoning about `g`'s behavior directly when +proving a spec for `f`. It's still worth going along with this exercise, +however, as the same principles of compositional verification apply whether the +implementation of `g` is small or large. + +The first step of compositional verification is to prove a spec for `g`, the +callee function: + +``` +$include 5-13 code/overrides.saw +``` + +There's nothing that different about this particular proof from the proofs +we've seen before. The only notable different is that we bind the result of +calling `mir_verify` to a `MIRSpec` value that we name `g_ov` (short for "`g` +override"). This part is important, as we will need to use `g_ov` shortly. + +The next step is to write a spec for `f`. Since `g` adds `1` to its argument, +`f` will add `3` to its argument: + +``` +$include 15-21 code/overrides.saw +``` + +Again, nothing too surprising. Now let's prove `f` against `f_spec` by using +`g_ov` as a compositional override: + +``` +$include 23-23 code/overrides.saw +``` + +Here, note that instead of passing an empty list (`[]`) as we have done before, +we now pass a list containing `g_ov`. This informs `mir_verify` that whenever +it simulates a call to `g`, it should reuse the properties captured in `g_ov`. +In general, we can pass as many overrides as we want (we will see examples of +this later in the tutorial), but for now, one override will suffice. + +Let's run the proof of `f` against `f_spec`, making sure to pay attention to +the output of SAW: + +``` +[19:06:17.392] Verifying overrides/96c5af24::f[0] ... +[19:06:17.406] Simulating overrides/96c5af24::f[0] ... +[19:06:17.407] Matching 1 overrides of overrides/96c5af24::g[0] ... +[19:06:17.407] Branching on 1 override variants of overrides/96c5af24::g[0] ... +[19:06:17.407] Applied override! overrides/96c5af24::g[0] +[19:06:17.407] Matching 1 overrides of overrides/96c5af24::g[0] ... +[19:06:17.407] Branching on 1 override variants of overrides/96c5af24::g[0] ... +[19:06:17.407] Applied override! overrides/96c5af24::g[0] +[19:06:17.407] Matching 1 overrides of overrides/96c5af24::g[0] ... +[19:06:17.407] Branching on 1 override variants of overrides/96c5af24::g[0] ... +[19:06:17.407] Applied override! overrides/96c5af24::g[0] +[19:06:17.407] Checking proof obligations overrides/96c5af24::f[0] ... +[19:06:17.422] Proof succeeded! overrides/96c5af24::f[0] +``` + +We've now proven `f` compositionally! The first two lines ("`Verifying ...`" +and "`Simulating ...`") and the last two lines ("`Checking proof obligations +...`" and "`Proof succeeded! ..."`) are the same as before, but this time, we +have some additional lines of output in between: + +* Whenever SAW prints "`Matching overrides of `", that's when you + know that SAW is about to simulate a call to ``. At that point, SAW + will check to see how many overrides (``) for `` are available. +* Whenever SAW prints "`Brancing on override variants of ", SAW is + trying to figure out which of the `` overrides to apply. In this example, + there is only a single override, so the choice is easy. In cases where there + are multiple overrides, however, SAW may have to work harder (possibly even + consulting an SMT solver) to figure out which override to use. +* If SAW successfully picks an override to apply, it will print + "`Applied override! ...`". + +In the example above, we used a single `g` override that applies for all +possible arguments. In general, however, there is no requirement that overrides +must work for all arguments. In fact, it is quite common for SAW verification +efforts to write different specifications for the same function, but with +different arguments. We can then provide multiple overrides for the same +function as part of a compositional verification, and SAW will be able to pick +the right override depending on the shape of the argument when invoking the +function being overridden. + +For example, let's suppose that we wrote different `g` specs, one where the +argument to `g` is even, and another where the argument to `g` is odd: + +``` +$include 25-44 code/overrides.saw +``` + +We can then prove `f` compositionally by passing both of the `g` overrides to +`mir_verify`: + +``` +$include 45-45 code/overrides.saw +``` + +Like before, this will successfully verify. The only different now is that SAW +will print output involving two overrides instead of just one: + +``` +[20:48:07.649] Simulating overrides/96c5af24::f[0] ... +[20:48:07.650] Matching 2 overrides of overrides/96c5af24::g[0] ... +[20:48:07.650] Branching on 2 override variants of overrides/96c5af24::g[0] ... +[20:48:07.652] Applied override! overrides/96c5af24::g[0] +... +``` + +Keep in mind that if you provide at least one override for a function as part +of a compositional verification, then SAW _must_ apply an override whenever it +invokes that function during simulation. If SAW cannot find a matching +override, then the verification will fail. For instance, consider what would +happen if you tried proving `f` like so: + +``` +$include 33-33 code/overrides-fail.saw +``` + +This time, we supply one override for `g` that only matches when the argument +is even. This is a problem, as SAW will not be able to find a matching override +when the argument is odd. Indeed, SAW will fail to verify this: + +``` +[20:53:29.588] Verifying overrides/96c5af24::f[0] ... +[20:53:29.602] Simulating overrides/96c5af24::f[0] ... +[20:53:29.602] Matching 1 overrides of overrides/96c5af24::g[0] ... +[20:53:29.602] Branching on 1 override variants of overrides/96c5af24::g[0] ... +[20:53:29.603] Applied override! overrides/96c5af24::g[0] +[20:53:29.603] Matching 1 overrides of overrides/96c5af24::g[0] ... +[20:53:29.603] Branching on 1 override variants of overrides/96c5af24::g[0] ... +[20:53:29.604] Applied override! overrides/96c5af24::g[0] +[20:53:29.604] Matching 1 overrides of overrides/96c5af24::g[0] ... +[20:53:29.604] Branching on 1 override variants of overrides/96c5af24::g[0] ... +[20:53:29.605] Applied override! overrides/96c5af24::g[0] +[20:53:29.605] Symbolic simulation completed with side conditions. +[20:53:29.606] Checking proof obligations overrides/96c5af24::f[0] ... +[20:53:29.623] Subgoal failed: overrides/96c5af24::f[0] No override specification applies for overrides/96c5af24::g[0]. +Arguments: +- c@26:bv +Run SAW with --sim-verbose=3 to see a description of each override. +[20:53:29.623] SolverStats {solverStatsSolvers = fromList ["SBV->Z3"], solverStatsGoalSize = 388} +[20:53:29.624] ----------Counterexample---------- +[20:53:29.624] x: 1 +... +Proof failed. +``` + +Here, we can see that `No override specification applies`, and SAW also +generates a counterexample of `x: 1`. Sure enough, `1` is an odd number! + +### Overrides and mutable references + +Compositional overrides provide great power, as they effectively allow you to +skip over certain functions when simulating them and replace them with simpler +implementations. With great power comes great responsibility, however. In +particular, one must be careful when using overrides for functions that modify +mutable references. If an override does not properly capture the behavior of a +mutable reference, it could potentially lead to incorrect proofs. + +This is the sort of thing that is best explained with an example, so consider +these two functions: + +``` {.rs} +$include 1-9 code/overrides-mut.rs +``` + +The `side_effect` function does not return anything interesting; it is only +ever invoked to perform a side effect of changing the mutable reference `a` to +point to `0`. The `foo` function invokes `side_effect`, and as a result, it +will always return `0`, regardless of what the argument to `foo` is. No +surprises just yet. + +Now let's make a first attempt at verifying `foo` using compositional +verification. First, we will write a spec for `side_effect`: + +``` +$include 5-10 code/overrides-mut-fail.saw +``` + +`side_effect_spec` is somewhat odd. Although it goes through the effort of +allocating a mutable reference `a_ref` and initializing it, nothing about this +spec states that `a_ref` will point to `0` after the function has been invoked. +This omission is strange, but not outright wrong—the spec just underspecifies +what the behavior of the function is. Indeed, SAW will successfully verify this +spec using `mir_verify`: + +``` +$include 18-18 code/overrides-mut-fail.saw +``` + +Next, let's try to write a spec for `foo`: + +``` +$include 12-16 code/overrides-mut-fail.saw +``` + +At this point, alarm bells should be going off in your head. This spec +incorrectly states that `foo(x)` should return `x`, but it should actually +return `0`! This looks wrong, but consider what would happen if you tried to +verify this compositionally using our `side_effect_ov` override: + +``` +$include 19-19 code/overrides-mut-fail.saw +``` + +If SAW were to simulate `foo(x)`, it would invoke create a temporary variable +`b` and assign it to the value `x`, and then it would invoke `side_effect(&mut +b)`. At this point, the `side_effect_ov` override would apply. According to +`side_effect_spec`, the argument to `side_effect` is not modified at all after +the function returns. This means that when the `foo` function returns `b`, it +will still retain its initial value of `x`. This shows that if we were to use +`side_effect_ov`, we could prove something that's blatantly false! + +Now that we've made you sweat a little bit, it's time for some good news: SAW +won't _actually_ let you prove `foo_spec`. If you try this compositional proof +in practice, SAW will catch your mistake: + +``` +[14:50:29.170] Verifying overrides_mut/11e47708::foo[0] ... +[14:50:29.181] Simulating overrides_mut/11e47708::foo[0] ... +[14:50:29.181] Matching 1 overrides of overrides_mut/11e47708::side_effect[0] ... +[14:50:29.181] Branching on 1 override variants of overrides_mut/11e47708::side_effect[0] ... +... +State of memory allocated in precondition (at overrides-mut-fail.saw:6:12) not described in postcondition +``` + +The line of code that SAW points to in the "`State of memory ...`" error +message is: + +``` +$include 6-6 code/overrides-mut-fail.saw +``` + +SAW informs us that although we allocated the mutable reference `a_ref`, we +never indicated what it should point to after the function has returned. This +is an acceptable (if somewhat unusual) thing to do when verifying +`side_effect_spec` using `mir_verify`, but it is _not_ acceptable to do this +when using this spec as an override. To avoid unsound behavior like what is +described above, any override that allocates a mutable reference in its +preconditions _must_ declare what its value should be in the postconditions, no +exceptions. + +Thankfully, repairing this spec is relatively straightforward. Simply add a +`mir_points_to` statement in the postconditions of `side_effect_spec`: + +``` +$include 5-13 code/overrides-mut.saw +``` + +Then use the correct return value in `foo_spec`: + +``` +$include 15-21 code/overrides-mut.saw +``` + +And now the compositional proof of `foo_spec` works! + +### Unsafe overrides + +Now that we've made it this far into the tutorial, it's time to teach you a +more advanced technique: _unsafe_ overrides. Up until this point, we have +relied on SAW to check all of our work, and this is usually what you'd want +from a formal verification tool. In certain circumstances, however, it can be +useful to say "I know what I'm doing, SAW—just believe me when I say this spec +is valid!" In order to say this, you can use `mir_unsafe_assume_spec`: + +``` +sawscript> :type mir_unsafe_assume_spec +MIRModule -> String -> MIRSetup () -> TopLevel MIRSpec +``` + +`mir_unsafe_assume_spec` is `mir_verify`'s cousin who likes to live a little +more dangerously. Unlike `mir_verify`, the specification that you pass to +`mir_unsafe_assume_spec` (the `MIRSetup ()` argument) is _not_ checked for full +correctness. That is, `mir_unsafe_assume_spec` will bypass SAW's usual symbolic +execution pipeline, which is why one does not need to pass a `ProofScript` +argument (e.g., `z3`) to `mir_unsafe_assume_spec`. SAW will believe whatever +spec you supply `mir_unsafe_assume_spec` to be valid, and the `MIRSpec` that +`mir_unsafe_assume_spec` returns can then be used in later compositional +verifications. + +Why would you want to do this? The main reason is that writing proofs can be +difficult, and sometimes, there are certain functions in a SAW verification +effort that are disproportionately harder to write a spec for than others. It +is tempting to write specs for each function in sequence, but this can run the +risk of getting stuck on a particularly hard-to-verify function, blocking +progress on other parts of the proofs. + +In these situations, `mir_unsafe_assume_spec` can be a useful prototyping tool. +One can use `mir_unsafe_assume_spec` to assume a spec for the hard-to-verify +function and then proceed with the remaining parts of the proof. Of course, you +should make an effort to go back and prove the hard-to-verify function's spec +later, but it can be nice to try something else first. + +For example, here is how one can unsafely assume `g_spec` and use it in a +compositional proof of `f_spec`: + +``` +$include 21-22 code/overrides-fail.saw +``` + +It should be emphasized that when we say "`unsafe`", we really mean it. +`mir_unsafe_assume_spec` can be used to prove specs that are blatantly wrong, +so use it with caution. + +## Static items + +Sometimes, Rust code makes use of [_static +items_](https://doc.rust-lang.org/std/intrinsics/fn.ctpop.html), which are +definitions that are defined in a precise memory location for the entire +duration of the program. As such, static items can be thought of as a form of +global variables. + +### Immutable static items + +There are two kinds of static items in Rust: mutable static items (which have a +`mut` keyword) and immutable static items (which lack `mut`). Immutable static +items are much easier to deal with, so let's start by looking at an example of +a program that uses immutable static data: + +``` {.rs} +$include 1-5 code/statics.rs +``` + +This function will return `ANSWER`, i.e., `42`. We can write a spec that says +as much: + +``` +$include 5-9 code/statics.saw +``` + +This works, but it is somewhat unsatisfying, as it requires hard-coding the +value of `ANSWER` into the spec. Ideally, we'd not have to think about the +precise implementation of static items like `ANSWER`. Fortunately, SAW makes +this possible by providing a `mir_static_initializer` function which computes +the initial value of a static item at the start of the program: + +``` +sawscript> :type mir_static_initializer +String -> MIRValue +``` + +In this case, `mir_static_initializer "statics::ANSWER"` is equivalent to +writing `mir_term {{ 42 : [32] }}`, so this spec is also valid: + +``` {.rs} +$include 14-18 code/statics.rs +``` + +Like `mir_verify`, the `mir_static_initializer` function expects a full +identifier as an argument, so we must write `"statics::ANSWER"` instead of +just `"ANSWER". + +At the MIR level, there is a unique reference to every static item. You can +obtain this reference by using the `mir_static` function: + +``` +sawscript> :type mir_static +String -> MIRValue +``` + +Here is one situation in which you would need to use a _reference_ to a static +item (which `mir_static` computes) rather than the _value_ of a static item +(which `mir_static_initializer` computes): + +``` {.rs} +$include 7-9 code/statics.rs +``` + +A spec for this function would look like this: + +``` +$include 23-27 code/statics.saw +``` + +That's about all there is to say regarding immutable static items. + +### Mutable static items + +Mutable static items are a particularly tricky aspect of Rust. Including a +mutable static item in your program is tantamount to having mutable global +state that any function can access and modify. They are so tricky, in fact, +that Rust does not even allow you to use them unless you surround them in an +`unsafe` block: + +``` {.rs} +$include 11-15 code/statics.rs +``` + +The `mir_static_initializer` and `mut_static` functions work both immutable and +mutable static items, so we can write specs for mutable items using mostly the +same techniques as for writing specs for immutable items. We must be careful, +however, as SAW is pickier when it comes to specifying the initial values of +mutable static items. For example, here is naïve attempt at porting the spec +for `answer_to_the_ultimate_question` over to its mutable static counterpart, +`mut_answer_to_the_ultimate_question`: + +``` +$include 5-9 code/statics-fail.saw +``` + +This looks plausible, but SAW will fail to verify it: + +``` +[21:52:32.738] Verifying statics/28a97e47::mut_answer_to_the_ultimate_question[0] ... +[21:52:32.745] Simulating statics/28a97e47::mut_answer_to_the_ultimate_question[0] ... +... +Symbolic execution failed. +Abort due to assertion failure: + statics.rs:14:14: 14:24: error: in statics/28a97e47::mut_answer_to_the_ultimate_question[0] + attempted to read empty mux tree +``` + +Oh no! Recall that we have seen this "`attempted to read empty mux tree`" error +message once before when discussing reference types. This error arose when we +attempted to read from uninitialized memory from a reference value. The same +situation applies here. A static item is backed by a reference, and SAW +deliberately does _not_ initialize the memory that a mutable static reference +points to upon program startup. Since we did not initialize `MUT_ANSWER`'s +reference value in the preconditions of the spec, SAW crashes at simulation +time when it attempts to read from the uninitialized memory. + +The solution to this problem is to perform this initialization explicitly using +`mir_points_to` in the preconditions of the spec. For example, this is a valid +spec: + +``` +$include 32-40 code/statics-fail.saw +``` + +We don't necessarily have to use `mir_static_initializer` as the starting value +for `MUT_ANSWER`, however. This spec, which uses `27` as the starting value, is +equally valid: + +``` +$include 45-52 code/statics-fail.saw +``` + +At this point, you are likely wondering: why do we need to explicitly +initialize mutable static references but not immutable static references? After +all, when we wrote a spec for `answer_to_the_ultimate_question` earlier, we +managed to get away with not initializing the reference for `ANSWER` (which is +an immutable static item). The difference is that the value of a mutable static +item can change over the course of a program, and SAW requires that you be very +careful in specifying what a mutable static value is at the start of a +function. For example, consider a slightly extended version of the earlier Rust +code we saw: + +``` {.rs} +$include 11-22 code/statics.rs +``` + +Suppose someone were to ask you "what value does +`mut_answer_to_the_ultimate_question` return?" This is not a straightforward +question to answer, as the value that it returns depends on the surrounding +context. If you were to call `mut_answer_to_the_ultimate_question` right as the +program started, it would return `42`. If you were to call +`mut_answer_to_the_ultimate_question` as part of the implementation of +`alternate_universe`, however, then it would return `27`! This is an inherent +danger of using mutable static items, as they can be modified at any time by +any function. For this reason, SAW requires you to be explicit about what the +initial values of mutable static items should be. + +#### Mutable static items and compositional overrides + +In the "Overrides and mutable references" section, we discussed the potential +pitfalls of using mutable references in compositional overrides. Mutable static +items are also mutable values that are backed by references, and as such, they +are also subject to the same pitfalls. Let's see an example of this: + +``` {.rs} +$include 1-12 code/statics-compositional.rs +``` + +The setup is almost the same, except that instead of passing a mutable +reference as an argument to `side_effect`, we instead declare a mutable static +item `A` that is shared between `side_effect` and `foo`. We could potentially +write SAW specs for `side_effect` and `foo` like these: + +``` +$include 5-20 code/statics-compositional-fail.saw +``` + +Note that we have once again underspecified the behavior of `side_effect`, as +we do not say what `A`'s value should be in the postconditions of +`side_effect_spec`. Similarly, `foo_spec` is wrong, as it should return `0` +rather than the initial value of `A`. By similar reasoning as before, we run +the risk that using `side_effect_ov` could lead use to prove something +incorrect. Thankfully, SAW can also catch this sort of mistake: + +``` +[15:46:38.525] Verifying statics_compositional/16fea9c0::side_effect[0] ... +[15:46:38.533] Simulating statics_compositional/16fea9c0::side_effect[0] ... +[15:46:38.533] Checking proof obligations statics_compositional/16fea9c0::side_effect[0] ... +[15:46:38.533] Proof succeeded! statics_compositional/16fea9c0::side_effect[0] +[15:46:38.533] Verifying statics_compositional/16fea9c0::foo[0] ... +[15:46:38.542] Simulating statics_compositional/16fea9c0::foo[0] ... +[15:46:38.542] Matching 1 overrides of statics_compositional/16fea9c0::side_effect[0] ... +[15:46:38.542] Branching on 1 override variants of statics_compositional/16fea9c0::side_effect[0] ... +... +State of mutable static variable "statics_compositional/16fea9c0::A[0]" not described in postcondition +``` + +To repair this proof, add a `mir_points_to` statement in the postconditions of +`side_effect_spec`: + +``` +$include 7-13 code/statics-compositional.saw +``` + +And then correct the behavior of `foo_spec`: + +``` +$include 15-22 code/statics-compositional.saw +``` + +Be warned that if your program declares any mutable static items, then any +compositional override _must_ state what the value of each mutable static item +is in its postconditions. This applies _even if the override does not directly +use the mutable static items_. For example, if we had declared a second mutable +static item alongside `A`: + +``` {.rs} +static mut A: u32 = 42; +static mut B: u32 = 27; +``` + +Then `side_effect_spec` would need an additional `mir_points_to` statement +involving `B` to satisfy this requirement. This requirement is somewhat +heavy-handed, but it is necessary in general to avoid unsoundness. Think +carefully before you use mutable static items! + +## Case study: Salsa20 + +If you've made it this far into the tutorial, congrats! You've now been exposed +to all of the SAW fundamentals that you need to verify Rust code found in the +wild. Of course, talking about verifying real-world code is one thing, but +actually _doing_ the verification is another thing entirely. Making the jump +from the small examples to "industrial-strength" code can be intimidating. + +To make this jump somewhat less frightening, the last part of this tutorial +will consist of a case study in using SAW to verify a non-trivial piece of Rust +code. In particular, we will be looking at a Rust implementation of the +[Salsa20](https://en.wikipedia.org/wiki/Salsa20) stream cipher. We do not +assume any prior expertise in cryptography or stream ciphers in this tutorial, +so don't worry if you are not familiar with Salsa20. + +More than anything, this case study is meant to emphasize that verification is +an iterative process. It's not uncommon to try something with SAW and encounter +an error message. That's OK! We will explain what can go wrong when verifying +Salsa20 and how to recover from these mistakes. Later, if you encounter similar +issues when verifying your own code with SAW, the experience you have developed +when developing these proofs can inform you of possible ways to fix the issues. + +### The `salsa20` crate + +The code for this Salsa20 implementation we will be verifying can be found +under the +[`code/salsa20`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20) +subdirectory. This code is adapted from version 0.3.0 of the `salsa20` crate, +which is a part of the +[`stream-ciphers`](https://github.com/RustCrypto/stream-ciphers) project. The +code implements Salsa20 as well as variants such as HSalsa20 and XSalsa20, but +we will only be focusing on the original Salsa20 cipher in this tutorial. + +The parts of the crate that are relevant for our needs are mostly contained in +the +[`src/core.rs`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/src/core.rs) +file, as well as some auxiliary definitions in the +[`src/rounds.rs`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/src/rounds.rs) +and +[`src/lib.rs`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/src/lib.rs) +files. You can take a look at these files if you'd like, but you don't need to +understand everything in them just yet. We will introduce the relevant parts of +the code in the tutorial as they come up. + +### Salsa20 preliminaries + +Salsa20 is a stream cipher, which is a cryptographic technique for encrypting +and decrypting messages. A stream cipher encrypts a message by combining it +with a _keystream_ to produce a ciphertext (the encrypted message). Moreover, +the same keystream can then be combined with the ciphertext to decrypt it back +into the original message. + +The original author of Salsa20 has published a specification for Salsa20 +[here](https://cr.yp.to/snuffle/spec.pdf). This is a great starting point for a +formal verification project, as this gives us a high-level description of +Salsa20's behavior that will guide us in proving the functional correctness of +the `salsa20` crate. When we say that `salsa20` is functionally correct, we +really mean "proven correct with respect to the Salsa20 specification". + +The first step in our project would be to port the Salsa20 spec to Cryptol +code, as we will need to use this code when writing SAW proofs. The process of +transcribing an English-language specification to executable Cryptol code is +interesting in its own right, but it is not the primary focus of this tutorial. +As such, we will save you some time by providing a pre-baked Cryptol +implementation of the Salsa20 spec +[here](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/src/Salsa20.cry). +(This implementation is +[adapted](https://github.com/GaloisInc/cryptol-specs/blob/1366ccf71db9dca58b16ff04ca7d960a4fe20e34/Primitive/Symmetric/Cipher/Stream/Salsa20.cry) +from the [`cryptol-specs`](https://github.com/GaloisInc/cryptol-specs) repo.) + +Writing the Cryptol version of the spec is only half the battle, however. We +still have to prove that the Rust implementation in the `salsa20` crate adheres +to the behavior prescribed by the spec, which is where SAW enters the picture. +As we will see shortly, the code in `salsa20` is not a direct port of the +pseudocode shown in the Salsa20 spec, as it is somewhat more low-level. SAW's +role is to provide us assurance that the behavior of the low-level Rust code +and the high-level Cryptol code coincide. + +### A note about cryptographic security + +As noted in the previous section, our goal is to prove that the behavior of +`salsa20` functions is functionally correct. This property should _not_ be +confused with cryptographic security. While functional correctness is an +important aspect of cryptographic security, a full cryptographic security audit +would encompass additional properties such as whether the code runs in constant +time on modern CPUs. As such, the SAW proofs we will write would not constitute +a full security audit (and indeed, the [`salsa20` +`README`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/README.md) +states that the crate has never received such an audit). + +### An overview of the `salsa20` code + +Before diving into proofs, it will be helpful to have a basic understanding of +the functions and data types used in the `salsa20` crate. Most of the +interesting code lives in +[`src/core.rs`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/src/core.rs). +At the top of this file, we have the `Core` struct: + +``` {.rs} +$include 8-14 code/salsa20/src/core.rs +``` + +Let's walk through this: + +* The `state` field is an array that is `STATE_WORDS` elements long, where + `STATE_WORDS` is a commonly used alias for `16`: + + ``` {.rs} + $include 88-89 code/salsa20/src/lib.rs + ``` + +* The `rounds` field is of type `PhantomData`. If you haven't seen it + before, + [`PhantomData`](https://doc.rust-lang.org/std/marker/struct.PhantomData.html) + is a special type that tells the Rust compiler to pretend as though the + struct is storing something of type `R`, even though a `PhantomData` value + will not take up any space at runtime. + +The reason that `Core` needs a `PhantomData` field is because `R` +implements the `Rounds` trait: + +``` {.rs} +$include 1-5 code/salsa20/src/rounds.rs +``` + +A core operation in Salsa20 is hashing its input through a series of +_rounds_. The `COUNT` constant indicates how many rounds should be performed. +The Salsa20 spec assumes 20 rounds: + +``` {.rs} +$include 23-29 code/salsa20/src/rounds.rs +``` + +However, there are also reduced-round variants that perform 8 and 12 rounds, +respectively: + +``` {.rs} +$include 7-21 code/salsa20/src/rounds.rs +``` + +Each number of rounds has a corresponding struct whose names begins with the +letter `R`. For instance, a `Core` value represents a 20-round Salsa20 +cipher. Here is the typical use case for a `Core` value: + +* A `Core` value is created using the `new` function: + + ``` {.rs} + $include 18-18 code/salsa20/src/core.rs + ``` + + We'll omit the implementation for now. This function takes a secret `Key` + value and a unique `Nonce` value and uses them to produce the initial `state` + in the `Core` value. + +* After creating a `Core` value, the `counter_setup` and `rounds` functions are + used to produce the Salsa20 keystream: + + ``` {.rs} + $include 83-83 code/salsa20/src/core.rs + ``` + ``` {.rs} + $include 90-90 code/salsa20/src/core.rs + ``` + + We'll have more to say about these functions later. + +* The _pièce de résistance_ is the `apply_keystream` function. This takes a + newly created `Core` value, produces its keystream, and applies it to a + message to produce the `output`: + + ``` {.rs} + $include 68-68 code/salsa20/src/core.rs + ``` + +Our ultimate goal is to verify the `apply_keystream` function, which is the +Rust equivalent of the Salsa20 encryption function described in the spec. + +### Building `salsa20` + +The next step is to build the `salsa20` crate. Unlike the examples we have seen +up to this point, which have been self-contained Rust files, `salsa20` is a +`cargo`-based project. As such, we will need to build it using `cargo +saw-build`, an extension to the `cargo` package manager that integrates with +`mir-json`. Before you proceed, make sure that you have defined the +`SAW_RUST_LIBRARY_PATH` environment variable as described in [this +section](#the-saw_rust_library_path-environment-variable). + +To build the `salsa20` crate, perform the following steps: + +``` +$ cd code/salsa20/ +$ cargo saw-build +``` + +Near the end of the build output, you will see a line that looks like this: + +``` +linking 9 mir files into <...>/saw-script/doc/rust-tutorial/code/salsa20/target/x86_64-unknown-linux-gnu/debug/deps/salsa20-dd0d90f28492b9cb.linked-mir.json +``` + +This is the location of the MIR JSON file that we will need to provide to SAW. +(When we tried it, the hash in the file name was `dd0d90f28492b9cb`, but it +could very well be different on your machine.) Due to how `cargo` works, the +location of this file is in a rather verbose, hard-to-remember location. For +this reason, we recommend copying this file to a different path, e.g., + +``` +$ cp <...>/saw-script/doc/rust-tutorial/code/salsa20/target/x86_64-unknown-linux-gnu/debug/deps/salsa20-dd0d90f28492b9cb.linked-mir.json code/salsa20/salsa20.linked-mir.json +``` + +As a safeguard, we have also checked in a compressed version of this MIR JSON +file as +[`code/salsa20/salsa/salsa20.linked-mir.json.tar.gz`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/salsa20.linked-mir.json.tar.gz). +In a pinch, you can extract this archive to obtain a copy of the MIR JSON file, +which is approximately 4.6 megabytes when uncompressed. + +### Getting started with SAW + +Now that we've built the `salsa20` crate, it's time to start writing some +proofs! Let's start a new `code/salsa20/salsa20.saw` file as fill it in with +the usual preamble: + +``` +$include 1-3 code/salsa20/salsa20-reference.saw +``` + +We are also going to need to make use of the Cryptol implementation of the +Salsa20 spec, which is defined in +[`code/salsa20/Salsa20.cry`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/Salsa20.cry). +SAW allows you to import standalone Cryptol `.cry` files by using the `import` +command: + +``` +$include 4-4 code/salsa20/salsa20-reference.saw +``` + +As an aside, note that we have also checked in a +[`code/salsa20/salsa20-reference.saw`](https://github.com/GaloisInc/saw-script/tree/master/doc/rust-tutorial/code/salsa20/salsa20-reference.saw), +which contains a complete SAW file. We encourage you _not_ to look at this file +for now, since following along with the tutorial is meant to illustrate the +"a-ha moments" that one would have in the process of writing the proofs. In you +become stuck while following along and absolutely need a hint, however, then +this file can help you become unstuck. + +### Verifying our first `salsa20` function + +Now it's time to start verifying some `salsa20` code. But where do we start? +It's tempting to start with `apply_keystream`, which is our end goal. This is +likely going to be counter-productive, however, as `apply_keystream` is a +large function with several moving parts. Throwing SAW at it immediately is +likely to cause it to spin forever without making any discernible progress. + +For this reason, we will instead take the approach of working from the +bottom-up. That is, we will first verify the functions that `apply_keystream` +transitively invokes, and then leverage compositional verification to verify a +proof of `apply_keystream` using overrides. This approach naturally breaks up +the problem into smaller pieces that are easier to understand in isolation. + +If we look at the implementation of `apply_keystream`, we see that it invokes +the `round` function, which in turn invokes the `quarter_round` function: + +``` {.rs} +$include 122-142 code/salsa20/src/core.rs +``` + +`quarter_round` is built on top of the standard library functions +[`wrapping_add`](https://doc.rust-lang.org/std/primitive.usize.html#method.wrapping_add) +and +[`rotate_left`](https://doc.rust-lang.org/std/primitive.usize.html#method.rotate_left), +so we have finally reached the bottom of the call stack. This makes +`quarter_round` a good choice for the first function to verify. + +The implementation of the Rust `quarter_round` function is quite similar to the +Cryptol `quarterround` function in `Salsa20.cry`: + +``` +$include 10-16 code/salsa20/Salsa20.cry +``` + +The Cryptol `quarterround` function doesn't have anything like the `state` +argument in the Rust `quarter_round` function, but let's not fret about that +too much yet. Our SAW spec is going to involve `quarterround` _somehow_—we just +have to figure out how to make it fit. + +Let's start filling out the SAW spec for `quarter_round`: + +``` +$include 6-6 code/salsa20/salsa20-quarter_round-fail1.saw +``` + +We are going to need some fresh variables for the `a`, `b`, `c`, and `d` +arguments: + +``` +$include 7-10 code/salsa20/salsa20-quarter_round-fail1.saw +``` + +We will also need to allocate a reference for the `state` argument. The +reference's underlying type is `STATE_WORDS` (`16`) elements long: + +``` +$include 11-13 code/salsa20/salsa20-quarter_round-fail1.saw +``` + +Finally, we will need to pass these arguments to the function: + +``` +$include 15-21 code/salsa20/salsa20-quarter_round-fail1.saw +``` + +With that, we have a spec for `quarter_round`! It's not very interesting just +yet, as we don't specify what `state_ref` should point to after the function +has returned. But that's fine for now. When developing a SAW proof, it can be +helpful to first write out the "skeleton" of a function spec that only contains +the call to `mir_execute_func`, without any additional preconditions or +postconditions. We can add those later after ensuring that the skeleton works +as expected. + +Let's check our progress thus far by running this through SAW: + +``` +$ saw salsa20.saw +... +[23:16:05.080] Type errors: + salsa20.saw:12:39-12:68: Unbound variable: "STATE_WORDS" (salsa20.saw:12:49-12:60) +Note that some built-in commands are available only after running +either `enable_deprecated` or `enable_experimental`. + + salsa20/salsa20.saw:11:31-11:60: Unbound variable: "STATE_WORDS" (salsa20.saw:11:41-11:52) +Note that some built-in commands are available only after running +either `enable_deprecated` or `enable_experimental`. +``` + +We've already run into some type errors. Not too surprising, considering this +was our first attempt. The error message contains that `STATE_WORDS` is +unbound. This makes sense if you think about it, as `STATE_WORDS` is defined in +the Rust code, but not in the SAW file itself. Let's fix that by adding this +line to `salsa20.saw`: + +``` +$include 6-6 code/salsa20/salsa20-quarter_round-fail2.saw +``` + +That change fixes the type errors in `quarter_round_spec`. Hooray! Let's press +on. + +Next, we need to add a call to `mir_verify`. In order to do this, we need to +know what the full identifier for the `quarter_round` function is. Because it +is defined in the `salsa20` crate and in the `core.rs` file, so we would expect +the identifier to be named `salsa20::core::quarter_round`: + +``` +$include 25-26 code/salsa20/salsa20-quarter_round-fail2.saw +``` + +However, SAW disagrees: + +``` +[00:22:56.970] Stack trace: +"mir_verify" (salsa20.saw:26:3-26:13) +Couldn't find MIR function named: salsa20::core::quarter_round +``` + +Ugh. This is a consequence of how `mir-json` disambiguates identifiers. Because +there is a separate `core` crate in the Rust standard libraries, `mir-json` +uses "`core#1`", a distinct name, to refer to the `core.rs` file. You can see +this for yourself by digging around in the MIR JSON file, if you'd like. (In a +future version of SAW, one will be able to [look this name +up](https://github.com/GaloisInc/saw-script/issues/1980) more easily.) + +Once we change the identifier: + +``` +$include 25-26 code/salsa20/salsa20-quarter_round-fail3.saw +``` + +We can run SAW once more. This time, SAW complains about a different thing: + +``` +[01:00:19.697] Verifying salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[01:00:19.714] Simulating salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[01:00:19.717] Checking proof obligations salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[01:00:19.739] Subgoal failed: salsa20/10e438b3::core#1[0]::quarter_round[0] index out of bounds: the length is move _10 but the index is _9 +[01:00:19.739] SolverStats {solverStatsSolvers = fromList ["SBV->Z3"], solverStatsGoalSize = 53} +[01:00:19.739] ----------Counterexample---------- +[01:00:19.739] a: 2147483648 +``` + +Here, SAW complains that we have an `index out of bounds`. Recall that we are +indexing into the `state` array, which is of length 16, using the +`a`/`b`/`c`/`d` arguments. Each of these arguments are of type `usize`, and +because we are declaring these to be symbolic, it is quite possible for each +argument to be 16 or greater, which would cause the index into `state` to be +out of bounds. + +In practice, however, the only values of `a`/`b`/`c`/`d` that we will use are +less than 16. We can express this fact as a precondition: + +``` +$include 13-16 code/salsa20/salsa20-quarter_round-fail4.saw +``` + +That is enough to finally get SAW to verify this very stripped-down version of +`quarter_round_spec`. Some good progress! But we aren't done yet, as we don't +yet say what happens to the value that `state` points to after the function +returns. This will be a requirement if we want to use `quarter_round_spec` in +compositional verification (and we do want this), so we should address this +shortly. + +Recall that unlike the Rust `quarter_round` function, the Cryptol +`quarterround` function doesn't have a `state` argument. This is because the +Rust function does slightly more than what the Cryptol function does. The Rust +function will look up elements of the `state` array, use them to perform the +computations that the Cryptol function does, and then insert the new values +back into the `state` array. To put it another way: the Rust function can be +thought of as a wrapper around the Cryptol function that also performs an +in-place bulk update of the `state` array. + +In Cryptol, one can look up elements of an array using the `(@@)` function, +and one can perform in-place array updates using the `updates` function. +This translates into a postcondition that looks like this: + +``` +$include 28-30 code/salsa20/salsa20-quarter_round-fail4.saw +``` + +What does SAW think of this? Someone surprisingly, SAW finds a counterexample: + +``` +[01:43:30.065] Verifying salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[01:43:30.078] Simulating salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[01:43:30.084] Checking proof obligations salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[01:43:30.801] Subgoal failed: salsa20/10e438b3::core#1[0]::quarter_round[0] Literal equality postcondition + +[01:43:30.801] SolverStats {solverStatsSolvers = fromList ["SBV->Z3"], solverStatsGoalSize = 1999} +[01:43:30.802] ----------Counterexample---------- +[01:43:30.802] a: 13 +[01:43:30.802] b: 3 +[01:43:30.802] c: 0 +[01:43:30.802] d: 0 +[01:43:30.802] state: [3788509705, 0, 0, 3223325776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1074561051, 0, 0] +``` + +Note that in this counterexample, the values of `c` and `d` are the same. In +the Rust version of the function, each element in `state` is updated +sequentially, so if two of the array indices are the same, then the value that +was updated with the first index will later be overwritten by the value at the +later index. In the Cryptol version of the function, however, all of the +positions in the array are updated simultaneously. This implicitly assumes that +all of the array indices are disjoint from each other, an assumption that we +are not encoding into `quarter_round_spec`'s preconditions. + +At this point, it can be helpful to observe _how_ the `quarter_round` function +is used in practice. The call sites are found in the `rounds` function: + +``` {.rs} +$include 92-102 code/salsa20/src/core.rs +``` + +Here, we can see that the values of `a`/`b`/`c`/`d` will only ever be chosen +from a set of eight possible options. We can take advantage of this fact to +constrain the possible set of values for `a`/`b`/`c`/`d`. The latest iteration +of the `quarter_round_spec` is now: + +``` +$include 10-38 code/salsa20/salsa20-reference.saw +``` + +Note that: + +* The `indices` value is constrained (via a precondition) to be one of the set + of values that is chosen in the `rounds` function. (Note that `\/` is the + logical-or function in Cryptol.) Each of these are concrete values that are + less than `STATE_WORDS` (`16`), so we no longer need a precondition stating + `a < `STATE_WORDS /\ ...`. + +* Because we now reference `indices` in the preconditions, we have moved its + definition up. (Previously, it was defined in the postconditions section.) + +With this in place, will SAW verify `quarter_round_spec` now? + +``` +[02:14:02.037] Verifying salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[02:14:02.051] Simulating salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[02:14:02.057] Checking proof obligations salsa20/10e438b3::core#1[0]::quarter_round[0] ... +[02:14:18.616] Proof succeeded! salsa20/10e438b3::core#1[0]::quarter_round[0] +``` + +At long last, it succeeds. Hooray! SAW does have to think for a while, however, +as this proof takes about 17 seconds to complete. It would be unfortunate to +have to wait 17 seconds on every subsequent invocation of SAW, and since we +still have other functions to verify, this is a very real possibility. For this +reason, it can be helpful to temporarily turn this use of `mir_verify` into a +`mir_unsafe_assume_spec`: + +``` +$include 40-44 code/salsa20/salsa20-reference.saw +``` + +Once we are done with the entire proof, we can come back and remove this use of +`mir_unsafe_assume_spec`, as we're only using it as a time-saving measure. + +### Verifying the `rounds` function + +Now that we've warmed up, let's try verifying the `rounds` function, which is +where `quarter_round` is invoked. Here is the full definition of `rounds`: + +``` {.rs} +$include 90-108 code/salsa20/src/core.rs +``` + +First, `rounds` performs `COUNT` rounds on the `state` argument. After this, it +takes each element of `self.state` and adds it to the corresponding element in +`state`. + +Linking back at the Salsa20 spec, we can see that the `rounds` function is +_almost_ an implementation of the Salsa20(x) hash function. The only notable +difference is that while the Salsa20(x) hash function converts the results to +little-endian form, the `rounds` function does not. `Salsa20.cry` implements +this part of the spec here: + +``` +$include 139-147 code/salsa20/Salsa20.cry +``` + +Where `Salsa20` is the hash function, and `Salsa20_rounds` is the part of the +hash function that excludes the little-endian conversions. In other words, +`Salsa20_rounds` precisely captures the behavior of the Rust `rounds` function. + +One aspect of the `rounds` function that will make verifying it slightly +different from verifying `quarter_rounds` is that `rounds` is defined in an +`impl` block for the `Core` struct. This means that the `&mut self` argument in +`rounds` has the type `&mut Core`. As such, we will have to look up the +`Core` ADT in SAW using `mir_find_adt`. + +This raises another question, however: when looking up `Core`, what type +should we use to instantiate `R`? As noted above, our choices are `R8`, `R12`, +and `R20`, depending on how many rounds you want. For now, we'll simply +hard-code it so that `R` is instantiated to be `R8`, but we will generalize +this a bit later. + +Alright, enough chatter—time to start writing a proof. First, let's look up the +`R8` ADT. This is defined in the `salsa20` crate in the `rounds.rs` file, so +its identifier becomes `salsa20::rounds::R8`: + +``` +$include 46-46 code/salsa20/salsa20-rounds-take-1.saw +``` + +Next, we need to look up the `PhantomData` ADT, which is used in the +`rounds` field of the `Core` struct. This is defined in `core::marker`: + +``` +$include 47-47 code/salsa20/salsa20-rounds-take-1.saw +``` + +Finally, we must look up `Core` itself. Like `quarter_round`, the `Core` +struct` is defined in `salsa20::core#1`: + +``` +$include 48-48 code/salsa20/salsa20-rounds-take-1.saw +``` + +Now that we have the necessary prerequisites, let's write a spec for the +`rounds` function. First, we need to allocate a reference for the `self` +argument: + +``` +$include 50-51 code/salsa20/salsa20-rounds-take-1.saw +``` + +Next, we need to create symbolic values for the fields of the `Core` struct, +which `self_ref` will point to. The `self.state` field will be a fresh array, +and the `self.rounds` field will be a simple, empty struct value: + +``` +$include 52-53 code/salsa20/salsa20-rounds-take-1.saw +``` + +Finally, putting all of the `self` values together: + +``` +$include 54-55 code/salsa20/salsa20-rounds-take-1.saw +``` + +Next, we need a `state` argument (not to be confused with the `self.state` +field in `Core`). This is handled much the same as it was in +`quarter_round_spec`: + +``` +$include 57-59 code/salsa20/salsa20-rounds-take-1.saw +``` + +Lastly, we cap it off with a call to `mir_execute_func`: + +``` +$include 61-62 code/salsa20/salsa20-rounds-take-1.saw +``` + +(Again, we're missing some postconditions describing what `self_ref` and +`state_ref` point to after the function returns, but we'll return to that in a +bit.) + +If we run SAW at this point, we see that everything in `rounds_spec` +typechecks, so we're off to a good start. Let's keep going and add a +`mir_verify` call. + +Here, we are faced with an interesting question: what is the identifier for +`rounds::`? The `rounds` function is defined using generics, so we can't +verify it directly—we must instead verify a particular instantiation of +`rounds`. At present, there isn't a good way to look up what the identifiers +for instantiations of generic functions are (there [will be in the +future](https://github.com/GaloisInc/saw-script/issues/1980)), but it turns out +that the identifier for `rounds::` is this: + +``` +$include 64-65 code/salsa20/salsa20-rounds-take-1.saw +``` + +Note that we are using `quarter_round_ov` as a compositional override. Once +again, SAW is happy with our work thus far: + +``` +[03:12:35.990] Proof succeeded! salsa20/10e438b3::core#1[0]::{impl#0}[0]::rounds[0]::_inst6e4a2d7250998ef7[0] +``` + +Nice. Now let's go back and fill in the missing postconditions in +`rounds_spec`. In particular, we must declare what happens to both `self_ref` +and `state_ref`. A closer examination of the code in the Rust `rounds` function +reveals that the `self` argument is never modified at all, so that part is +easy: + +``` +$include 63-63 code/salsa20/salsa20-rounds-take-2.saw +``` + +The `state` argument, on the other hand, is modified in-place. This time, our +job is made easier by the fact that `Salsa20_rounds` implements _exactly_ what +we need. Because we are instantiating `rounds` at type `R8`, we must explicitly +state that we are using 8 rounds: + +``` +$include 64-64 code/salsa20/salsa20-rounds-take-2.saw +``` + +Once again, SAW is happy with our work. We're on a roll! + +Now let's address the fact that we are hard-coding everything to `R8`, which is +somewhat uncomfortable. We can make things better by allowing the user to +specify the number of rounds. The first thing that we will need to change is +the `r_adt` definition, which is response for looking up `R8`. We want to turn +this into a function that, depending on the user input, will look up `R8`, +`R12`, or `R20`: + +``` +$include 46-46 code/salsa20/salsa20-rounds-take-3.saw +``` + +Where `str_concat` is a SAW function for concatenating strings together: + +``` +sawscript> :type str_concat +String -> String -> String +``` + +We also want to parameterize `phantom_data_adt` and `core_adt`: + +``` +$include 47-48 code/salsa20/salsa20-rounds-take-3.saw +``` + +Next, we need to parameterize `rounds_spec` by the number of rounds. This will +require changes in both the preconditions and postconditions. On the +preconditions side, we must pass the number of rounds to the relevant +functions: + +``` +$include 50-56 code/salsa20/salsa20-rounds-take-3.saw +``` + +And on the postconditions side, we must pass the number of rounds to the +Cryptol `Salsa20_rounds` function: + +``` +$include 66-67 code/salsa20/salsa20-rounds-take-3.saw +``` + +Finally, we must adjust the call to `rounds_spec` in the context of +`mir_verify` so that we pick `8` as the number of rounds: + +``` +$include 69-70 code/salsa20/salsa20-rounds-take-3.saw +``` + +SAW is happy with this generalization. To demonstrate that we have generalized +things correctly, we can also verify the same function at `R20` instead of +`R8`: + +``` +$include 71-72 code/salsa20/salsa20-rounds-take-3.saw +``` + +The only things that we had to change were the identifier and the argument to +`rounds_spec`. Not bad! + +### Verifying the `counter_setup` function + +We're very nearly at the point of being able to verify `apply_keystream`. +Before we do, however, there is one more function that `apply_keystream` calls, +which we ought to verify first: `counter_setup`. Thankfully, the implementation +of `counter_setup` is short and sweet: + +``` {.rs} +$include 83-86 code/salsa20/src/core.rs +``` + +This updates the elements of the `state` array at indices `8` and `9` with the +lower 32 bits and the upper 32 bits of the `counter` argument, respecitvely. +At a first glance, there doesn't appear to be any function in `Salsa20.cry` +that directly corresponds to what `counter_setup` does. This is a bit of a +head-scratcher, but the answer to this mystery will become more apparent as we +get further along in the proof. + +For now, we should take matters into our own hands and write our own Cryptol +spec for `counter_setup`. To do this, we will create a new Cryptol file named +`Salsa20Extras.cry`, which imports from `Salsa20.cry`: + +``` +$include 1-3 code/salsa20/Salsa20Extras.cry +``` + +The Cryptol implementation of `counter_setup` will need arrays of length +`STATE_WORDS`, so we shall define `STATE_WORDS` first: + +``` +$include 5-5 code/salsa20/Salsa20Extras.cry +``` + +Note that we preceded this definition with the `type` keyword. In Cryptol, +sequence lengths are encoded at the type level, so if we want to use +`STATE_WORDS` at the type level, we must declare it as a `type`. + +Finally, we can write a Cryptol version of `counter_setup` using our old friend +`updates` to perform a bulk sequence update: + +``` +$include 8-10 code/salsa20/Salsa20Extras.cry +``` + +Note that `counter` is a 64-bit word, but the elements of the `state` sequence +are 32-bit words. As a result, we have to explicitly truncate `counter` and +`counter >> 32` to 32-bit words by using the `drop` function, which drops the +first 32 bits from each word. + +Returning to `salsa20.saw`, we must now make use of our new Cryptol file by +`import`ing it at the top: + +``` +$include 5-5 code/salsa20/salsa20-reference.saw +``` + +With the `counter_setup` Cryptol implementation in scope, we can now write +a spec for the Rust `counter_setup` function. There's not too much to remark +on here, as the spec proves relatively straightforward to write: + +``` +$include 74-90 code/salsa20/salsa20-reference.saw +``` + +We can now verify `counter_setup` against `counter_setup_spec` at lengths `8` +and `20`: + +``` +$include 92-95 code/salsa20/salsa20-reference.saw +``` + +That wasn't so bad. It's a bit unsatisfying that we had to resort to writing a +Cryptol function not found in `Salsa20.cry`, but go along with this for now—it +will become apparent later why this needed to be done. + +### Verifying the `apply_keystream` function (first attempt) + +It's time. Now that we've verified `rounds` and `counter_setup`, it's time to +tackle the topmost function in the call stack: `apply_keystream`: + +``` {.rs} +$include 68-80 code/salsa20/src/core.rs +``` + +There aren't _that_ many lines of code in this function, but there is still +quite a bit going on. Let's walk through `apply_keystream` in more detail: + +1. The `output` argument represents the message to encrypt (or decrypt). + `output` is a slice of bytes, so in principle, `output` can have an arbitrary + length. That being said, the first line of `apply_keystream`'s implementation + checks that `output`'s length is equal to `BLOCK_SIZE`: + + ``` {.rs} + $include 69-69 code/salsa20/src/core.rs + ``` + + Where `BLOCK_SIZE` is defined here: + + ``` {.rs} + $include 82-83 code/salsa20/src/lib.rs + ``` + + So in practice, `output` must have exactly 64 elements. + +2. Next, `apply_keystream` invokes the `counter_setup` and `rounds` functions + to set up the keystream (the local `state` variable). + +3. Finally, `apply_keystream` combines the keystream with `output`. It does + so by chunking `output` into a sequence of 4 bytes, and then it XOR's the + value of each byte in-place with the corresponding byte from the keystream. + This performs little-endian conversions as necessary. + +The fact that we are XOR'ing bytes strongly suggests that this is an +implementation of the Salsa20 encryption function from the spec. There is an +important difference between how the Salsa20 spec defines the encryption +function versus how `apply_keystream` defines it, however. In the Salsa20 spec, +encryption is a function of a key, nonce, and a message. `apply_keystream`, on +the other hand, is a function of `self`'s internal state, a counter, and a +message. The two aren't _quite_ the same, which is makes it somewhat tricky to +describe one in terms of the other. + +`Salsa20.cry` defines a straightforward Cryptol port of the Salsa20 encryption +function from the spec, named `Salsa20_encrypt`. Because it takes a key and a +nonce as an argument, it's not immediately clear how we'd tie this back to +`apply_keystream`. But no matter: we can do what we did before and define our +own Cryptol version of `apply_keystream` in `Salsa20Extras.cry`: + +``` +$include 12-17 code/salsa20/Salsa20Extras.cry +``` + +This implementation builds on top of the Cryptol `counter_setup` and +`Salsa20_rounds` functions, which we used as the reference implementations for +the Rust `counter_setup` and `rounds` functions, respectively. We also make +sure to define a `BLOCK_SIZE` type alias at the top of the file: + +``` +$include 6-6 code/salsa20/Salsa20Extras.cry +``` + +Now let's write a SAW spec for `apply_keystream`. Once again, we will need to +reference `BLOCK_SIZE` when talking about the `output`-related parts of the +spec, so make sure to define `BLOCK_SIZE` at the top of the `.saw` file: + +``` +$include 8-8 code/salsa20/salsa20-reference.saw +``` + +First, we need to declare all of our arguments, which proceeds as you would +expect: + +``` +$include 120-136 code/salsa20/salsa20-reference.saw +``` + +What about the postconditions? We have two mutable references to contend with: +`self_ref` and `output_ref`. The postcondition for `self_ref` is fairly +straightforward: the only time it is ever modified is when `counter_setup` is +called. This means that after the `apply_keystream` function has returned, +`self_ref` will point to the results of calling the `counter_setup` Cryptol +function: + +``` +$include 138-140 code/salsa20/salsa20-reference.saw +``` + +`output_ref` is where the interesting work happenings. After the Rust +`apply_keystream` function has returned, it will point to the results of +calling the Cryptol `apply_keystream` function that we just defined: + +``` +$include 141-142 code/salsa20/salsa20-reference.saw +``` + +Finally, we can put this all together and verify `apply_keystream` against +`apply_keystream_spec` at lengths `8` and `20`: + +``` +$include 144-148 code/salsa20/salsa20-reference.saw +``` + +SAW will successfully verify these. We've achieved victory... or have we? +Recall that we had to tailor the Cryptol `apply_keystream` function to +specifically match the behavior of the corresponding Rust code. This makes the +proof somewhat underwhelming, since the low-level implementation is nearly +identical to the high-level spec. + +A more impressive proof would require linking `apply_keystream` to a Cryptol +function in the `Salsa20.cry` file, which was developed independently of the +Rust code. As we mentioned before, however, doing so will force us to reconcile +the differences in the sorts of arguments that each function takes, as +`apply_keystream` doesn't take a key or nonce argument. Time to think for a +bit. + +### Verifying the `new_raw` function + +At this point, we should ask ourselves: _why_ doesn't `apply_keystream` take a +key or nonce argument? The reason lies in the fact that the `salsa20` crate +implements Salsa20 in a stateful way. Specifically, the `Core` struct stores +internal state that is used to compute the keystream to apply when hashing. In +order to use this internal state, however, we must first initialize it. The +`new` function that is responsible for this initialization: + +``` {.rs} +$include 17-20 code/salsa20/src/core.rs +``` + +Sure enough, this function takes a key and a nonce as an argument! This is a +critical point that we overlooked. When using the `salsa20` crate, you wouldn't +use the `apply_keystream` function in isolation. Instead, you would create an +initial `Core` value using `new`, and _then_ you would invoke +`apply_keystream`. The Salsa20 spec effectively combines both of these +operations in is encryption function, whereas the `salsa20` splits these two +operations into separate functions altogether. + +Strictly speaking, we don't need to verify `new` in order to verify +`apply_keystream`, as the latter never invokes the former. Still, it will be a +useful exercise to verify `new`, as the insights we gain when doing so will +help us write a better version of `apply_keystream_spec`. + +All that being said, we probably to verify `new_raw` (a lower-level helper +function) rather than `new` itself. This is because the definitions of `Key` +and `Nonce` are somewhat involved. For instance, `Key` is defined as: + +``` {.rs} +$include 27-27 code/salsa20/src/salsa.rs +``` + +[`GenericArray`](https://docs.rs/generic-array/latest/generic_array/struct.GenericArray.html) +is a somewhat complicated abstraction. Luckily, we don't really _need_ to deal +with it, since `new_raw` deals with simple array references rather than +`GenericArray`s: + +``` {.rs} +$include 22-23 code/salsa20/src/core.rs +``` + +The full implementation of `new_raw` is rather long, so we won't inline the +whole thing here. At a high level, it initializes the `state` array of a `Core` +value by populating each element of the array with various things. Some +elements of the array are populated with `key`, some parts are populated with +`iv` (i.e., the nonce), and other parts are populated with an array named +`CONSTANTS`: + +``` {.rs} +$include 91-92 code/salsa20/src/lib.rs +``` + +The comment about `"expand 32-byte k"` is a strong hint that `new_raw` is +implementing a portion of the Salsa20 expansion function from the spec. (No +really, the spec literally says to use the exact string `"expand 32-byte +k"`—look it up!) The `Salsa20.cry` Cryptol file has an implementation of this +portion of the expansion function, which is named `Salsa20_init`: + +``` +$include 182-189 code/salsa20/Salsa20.cry +``` + +Note that we were careful to say a _portion_ of the Salsa20 expansion function. +There is also a Cryptol implementation of the full expansion function, named +`Salsa20_expansion`: + +``` +$include 179-180 code/salsa20/Salsa20.cry +``` + +This calls `Salsa20_init` followed by `Salsa20`, the latter of which performs +hashing. Importantly, `new_raw` does _not_ do any hashing on its own, just +initialization. For this reason, we want to use `Salsa20_init` as the reference +implementation of `new_raw`, not `Salsa20_expansion`. + +Alright, time to write a SAW spec. The first part of the spec is straightforward: + +``` +$include 97-106 code/salsa20/salsa20-new_raw-fail1.saw +``` + +As is usually the case, the postconditions are the tricky part. We know that +the behavior of `new_raw` will roughly coincide with the `Salsa20_init` +function, so let's try that first: + +``` +$include 108-112 code/salsa20/salsa20-new_raw-fail1.saw +``` + +If we attempt to verify this using `mir_verify`: + +``` +$include 115-118 code/salsa20/salsa20-new_raw-fail1.saw +``` + +SAW complains thusly: + +``` +Cryptol error: +[error] at salsa20.saw:109:45--109:54: + Type mismatch: + Expected type: 16 + Inferred type: 8 + Context: [ERROR] _ + When checking type of 2nd tuple field +``` + +Here, the 2nd tuple field is the `nonce_arr` in `Salsa20_init(key_arr, +nonce_arr)`. And sure enough, `Salsa20_init` expects the 2nd tuple field to be +a sequence of 16 elements, but `nonce_arr` only has 8 elements. Where do we get +the remaining 8 elements from? + +The answer to this question can be found by looking at the implementation of +`new_raw` more closely. Let's start at this code: + +``` {.rs} +$include 35-36 code/salsa20/src/core.rs +``` + +This will chunk up `iv` (the nonce) into two 4-byte chunks and copies them over +to the elements of `state` array at indices `6` and `7`. This is immediately +followed by two updates at indices `8` and `9`, which are updated to be `0`: + +``` {.rs} +$include 39-40 code/salsa20/src/core.rs +``` + +If you take the two 4-bytes chunks of `iv` and put two 4-byte `0` values after +them, then you would have a total of 16 bytes. This suggests that the nonce +value that `Salsa20_init` expects is actually this: + +``` +nonce_arr # zero : [16][8] +``` + +Where `zero : [8][8]` is a Cryptol expression that returns all zeroes, and +`(#)` is the Cryptol operator for concatenating two sequences together. Let's +update `new_raw_spec` to reflect this: + +``` +$include 109-109 code/salsa20/salsa20-new_raw-fail2.saw +``` + +This is closer to what we want, but not quite. SAW still complains: + +``` +could not match specified value with actual value: + ... + type of actual value: [u32; 16] + type of specified value: [u8; 64] +``` + +This is because `Salsa20_init` returns something of type `[64][8]`, which +corresponds to the Rust type `[u8; 64]`. `self.state`, on the other hand, is of +type `[u32; 16]`. These types are very close, as they both contain the same +number of bytes, but they are chunked up differently. Recall the code that +copies the nonce value over to `self.state`: + +``` {.rs} +$include 35-36 code/salsa20/src/core.rs +``` + +In order to resolve the type differences between `iv` and `state`, this code +needed to explicitly convert `iv` to little-endian form using the +[`u32::from_le_bytes`](https://doc.rust-lang.org/std/primitive.u32.html#method.from_le_bytes) +function. There is a similar Cryptol function in `Salsa20.cry` named +`littleendian_state`: + +``` +$include 131-132 code/salsa20/Salsa20.cry +``` + +Note that `[64][8]` is the Cryptol equivalent of `[u8; 64]`, and `[16][32]` is +the Cryptol equivalent of `[u32; 16]`. As such, this is exactly the function +that we need to resolve the differences in types: + +``` +$include 109-109 code/salsa20/salsa20-reference.saw +``` + +With that change, SAW is finally happy with `new_raw_spec` and successfully +verifies it. + +There is an interesting connection between the `new_raw` and `counter_setup` +functions. Both functions perform in-place updates on `state` at indices `8` +and `9`. Whereas `new_raw` always sets these elements of `state` to `0`, +`counter_setup` will set them to the bits of the `counter` argument (after +converting `counter` to little-endian form). This means that if you invoke +`counter_setup` right after `new_raw`, then `counter_setup` would overwrite the +`0` values with the `counter` argument. In order words, it would be tantamount +to initializing `state` like so: + +``` +littleendian_state (Salsa20_init(key, nonce # littleendian_inverse counter)) +``` + +Where `littleendian_inverse` (a sibling of `littleendian_state`) converts a +`[64]` value to a `[8][8]` one. This pattern is a curious one... + +### Verifying the `apply_keystream` function (second attempt) + +Let's now return to the problem of linking `apply_keystream` up to +`Salsa20_encrypt`. In particular, let's take a closer look at the definition of +`Salsa20_encrypt` itself: + +``` +$include 198-201 code/salsa20/Salsa20.cry +``` + +Does anything about this definition strike you as interesting? Take a look at +the `v#(littleendian_inverse i)` part—we _just_ saw a use of +`littleendian_inverse` earlier in our discussion about initializing the +`state`! Moreover, `v` is the nonce argument, so it is becoming clearer that +`Sals20_encrypt` is creating an initial state is much the same way that +`new_raw` is. + +A related question: what is the `i` value? The answer is somewhat technical: +the Salsa20 encryption function is designed to work with messages with +differing numbers of bytes (up to `2^^70` bytes, to be exact). Each 8-byte +chunk in the message will be encrypted with a slightly difference nonce. For +instance, the first 8-byte chunk's nonce will have its lower 32 bits set to +`0`, the second 8-byte chunk's nonce will have its lower 32 bits set to `1`, +and so on. In general, the `i`th 8-byte chunk's nonce will have its lower 32 +bits set to `i`, and this corresponds exactly to the `i` in the expression +`littleendian_inverse i`. + +Note, however, that `apply_keystream` only ever uses a message that consists of +exactly eight 8-byte chunks. This means that `Salsa20_encrypt` will only ever +invoke `Salsa20_expansion` once with a nonce value where the lower 32 bits are +set to `0`. That is, it will perform encryption with an initial state derived +from: + +``` +Salsa20_init(k, v#(littleendian_inverse zero)) +``` + +Which can be further simplified to `Salsa20_init(k, v # zero)`. This is very +nearly what we want, as this gives us the behavior of the Rust `new_raw` +function. There's just one problem though: it doesn't take the behavior of +`counter_setup` into account. How do we go from `zero` to `littleendian_inverse +counter`? + +While `Salsa20_encrypt` doesn't take counters into account at all, it is not +too difficult to generalize `Salsa20_encrypt` in this way. There is a variant +of `Salsa20_encrypt` in the same file named `Salsa20_encrypt_with_offset`, +where the offset argument `o` serves the same role that `counter` does in +`counter_setup`: + +``` +$include 191-196 code/salsa20/Salsa20.cry +``` + +(Observe that `Salsa20_encrypt(count, k, v, m)` is equivalent to +`Salsa20_encrypt_with_offset(count, k, v, 0, m)`.) + +At long last, we have discovered the connection between `apply_keystream` and +the Salsa20 spec. If you assume that you invoke `new_raw` beforehand, then the +behavior of `apply_keystream` corresponds exactly to that of +`Salsa20_encrypt_with_offset`. This insight will inform us how to write an +alternative SAW spec for `apply_keystream`: + +``` +$include 149-160 code/salsa20/salsa20-apply_keystream_alt-fail1.saw +``` + +Observe the following differences between `apply_keystream_alt_spec` and our +earlier `apply_keystream_spec`: + +1. In `apply_keystream_alt_spec`, we declare fresh `key` and `nonce` values, + which weren't present at all in `apply_keystream_spec`. + +2. In `apply_keystream_alt_spec`, we no longer make `self_state` a fresh, + unconstrained value. Instead, we declare that it must be the result of + calling `Salsa20_init` on the `key`, `nonce`, and `counter` values. This + is the part that encodes the assumption that `new_raw` was invoked + beforehand. + +The parts of the spec relating to `output` remain unchanged: + +``` +$include 162-167 code/salsa20/salsa20-apply_keystream_alt-fail1.saw +``` + +The postconditions are slightly different in `apply_keystream_alt_spec`. While +the parts relating to `self_ref` remain unchanged, we now have `output_ref` +point to the results of calling `Salsa20_encrypt_with_offset`: + +``` +$include 169-172 code/salsa20/salsa20-apply_keystream_alt-fail1.saw +``` + +Tying this all together, we call `mir_verify`, making sure to use compositional +overrides involving `counter_setup` and `rounds`: + +``` +$include 175-178 code/salsa20/salsa20-apply_keystream_alt-fail1.saw +``` + +At long last, it is time to run SAW on this. When we do, we see this: + +``` +[15:11:44.576] Checking proof obligations salsa20/10e438b3::core#1[0]::{impl#0}[0]::apply_keystream[0]::_inst6e4a2d7250998ef7[0] ... +``` + +After this, SAW loops forever. Oh no! While somewhat disheartening, this is a +reality of SMT-based verification that we must content with. SMT solvers are +extremely powerful, but their performance can sometimes be unpredictable. The +task of verifying `apply_keystream_alt_spec` is _just_ complicated enough that +Z3 cannot immediately figure out that the proof is valid, so it resorts to much +slower algorithms to solve proof goals. + +We could try waiting for Z3 to complete, but we'd be waiting for a long time. +It's not unheard of for SMT solvers to take many hours on especially hard +problems, but we don't have that many hours to spare. We should try a slightly +different approach instead. + +When confronted with an infinite loop in SAW, there isn't a one-size-fits-all +solution that will cure the problem. Sometimes, it is worth stating your SAW +spec in a slightly different way such that the SMT solver can spot patterns +that it couldn't before. Other times, it can be useful to try and break the +problem up into smaller functions and use compositional verification to handle +the more complicated subfunctions. As we mentioned before, the performance of +SMT solvers in unpredictable, and it's not always obvious what the best +solution is. + +In this example, however, the problem lies with Z3 itself. As it turns out, +Yices (a different SMT solver) _can_ spot the patterns needed to prove +`apply_keystream_alt_spec` immediately. Fortunately, SAW includes support for +both Z3 and Yices. In order to switch from Z3 to Yices, swap out the `z3` proof +script with `yices`: + +``` +$include 175-178 code/salsa20/salsa20-reference.saw +``` + +After doing this, SAW is leverage Yices to solve the proof goals almost +immediately: + +``` +[15:22:00.745] Proof succeeded! salsa20/10e438b3::core#1[0]::{impl#0}[0]::apply_keystream[0]::_instfa33e77d840484a0[0] +``` + +And with that, we're finally done! You've successfully completed a non-trivial +SAW exercise in writing some interesting proofs. Give yourself a well-deserved +pat on the back. + +The process of developing these proofs was bumpy at times, but that is to be +expected. You very rarely get a proof correct on the very first try, and when +SAW doesn't accept your proof, it is important to be able to figure out what +went wrong and how to fix it. This is a skill that takes some time to grow, but +with enough time and experience, you will be able to recognize common pitfalls. +This case study showed off some of these pitfalls, but there are likely others. + +## A final word + +Like everything else in the `saw-script` repo, this tutorial is being +maintained and developed. If you see something in the tutorial that is wrong, +misleading, or confusing, please file an issue about it +[here](https://github.com/GaloisInc/saw-script/issues).