Abstract
Rust's type system ensures memory safety: well-typed Rust programs are guaranteed to not exhibit problems such as dangling pointers, data races, and unexpected side effects through aliased references. Ensuring correctness properties beyond memory safety, for instance, the guaranteed absence of assertion failures or more-general functional correctness, requires static program verification. For traditional system programming languages, formal verification is notoriously difficult and requires complex specifications and logics to reason about pointers, aliasing, and side effects on mutable state. This complexity is a major obstacle to the more-widespread verification of system software.
In this paper, we present a novel verification technique that leverages Rust's type system to greatly simplify the specification and verification of system software written in Rust. We analyse information from the Rust compiler and synthesise a corresponding core proof for the program in a flavour of separation logic tailored to automation. To verify correctness properties beyond memory safety, users can annotate Rust programs with specifications at the abstraction level of Rust expressions; our technique weaves them into the core proof to verify modularly whether these specifications hold. Crucially, our proofs are constructed and checked automatically without exposing the underlying formal logic, allowing users to work exclusively at the level of abstraction of the programming language. As such, our work enables a new kind of verification tool, with the potential to impact a wide audience and allow the Rust community to benefit from state-of-the-art verification techniques. We have implemented our techniques for a subset of Rust; our evaluation on several thousand functions from widely-used Rust crates demonstrates its effectiveness.
Supplemental Material
- Martìn Abadi and Marcelo Fiore. 1996. Syntactic Considerations on Recursive Types. In Logic in Computer Science (LICS). IEEE Computer Society, 242–252.Google Scholar
- Vytautas Astrauskas, Peter Müller, Federico Poli, and Alexander J. Summers. 2019a. Artefact containing the prototype implementation. Google Scholar
Digital Library
- Vytautas Astrauskas, Peter Müller, Federico Poli, and Alexander J. Summers. 2019b. Leveraging Rust Types for Modular Specification and Verification . Technical Report. ETH Zurich.Google Scholar
- Alexander Bakst and Ranjit Jhala. 2016. Predicate Abstraction for Linked Data Structures. In Verification, Model Checking, and Abstract Interpretation (VMCAI) (Lecture Notes in Computer Science) , Barbara Jobstmann and K. Rustan M. Leino (Eds.), Vol. 9583. Springer, 65–84.Google Scholar
- Marek Baranowski, Shaobo He, and Zvonimir Rakamarić. 2018. Verifying Rust Programs with SMACK. In Automated Technology for Verification and Analysis (ATVA) (Lecture Notes in Computer Science) , Shuvendu K. Lahiri and Chao Wang (Eds.), Vol. 11138. Springer, 528–535.Google Scholar
- Mike Barnett, Manuel Fähndrich, K. Rustan M. Leino, Peter Müller, Wolfram Schulte, and Herman Venter. 2011. Specification and Verification: The Spec# Experience. Commun. ACM 54, 6 (June 2011), 81–91.Google Scholar
Digital Library
- Kevin Bierhoff. 2011. Automated Program Verification Made SYMPLAR: Symbolic Permissions for Lightweight Automated Reasoning. In Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software (Onward! 2011). ACM, 19–32.Google Scholar
Digital Library
- John Boyland. 2003. Checking Interference with Fractional Permissions. In Static Analysis Symposium (SAS) (Lecture Notes in Computer Science) , Radhia Cousot (Ed.), Vol. 2694. Springer, 55–72.Google Scholar
- John Boyland, James Noble, and William Retert. 2001. Capabilities for Sharing: A Generalisation of Uniqueness and Read-Only. In European Conference on Object-Oriented Programming (ECOOP) (Lecture Notes in Computer Science), Jørgen Lindskov Knudsen (Ed.), Vol. 2072. Springer, 2–27.Google Scholar
Cross Ref
- Sylvan Clebsch, Sophia Drossopoulou, Sebastian Blessing, and Andy McNeil. 2015. Deny Capabilities for Safe, Fast Actors. In International Workshop on Programming Based on Actors, Agents, and Decentralized Control (AGERE! 2015). ACM, 1–12.Google Scholar
- Clippy contributors. 2019. Clippy. https://github.com/rust-lang/rust-clippy Accessed April 4, 2019.Google Scholar
- Ernie Cohen, Markus Dahlweid, Mark A. Hillebrand, Dirk Leinenbach, Michal Moskal, Thomas Santen, Wolfram Schulte, and Stephan Tobies. 2009. VCC: A Practical System for Verifying Concurrent C. In Theorem Proving in Higher Order Logics (TPHOLs) (Lecture Notes in Computer Science) , Stefan Berghofer, Tobias Nipkow, Christian Urban, and Makarius Wenzel (Eds.), Vol. 5674. Springer, 23–42.Google Scholar
- Coq Team. 2014. The Coq Proof Assistant Reference Manual. http://coq.inria.fr .Google Scholar
- Karl Crary, Robert Harper, and Sidd Puri. 1999. What is a Recursive Module?. In Programming Language Design and Implementation (PLDI) , Barbara G. Ryder and Benjamin G. Zorn (Eds.). ACM, 50–63.Google Scholar
- Leonardo Mendonça de Moura, Soonho Kong, Jeremy Avigad, Floris van Doorn, and Jakob von Raumer. 2015. The Lean Theorem Prover (System Description). In Automated Deduction (CADE) (Lecture Notes in Computer Science), Amy P. Felty and Aart Middeldorp (Eds.), Vol. 9195. Springer, 378–388.Google Scholar
- Robert Dockins, Adam Foltzer, Joe Hendrix, Brian Huffman, Dylan McNamee, and Aaron Tomb. 2016. Constructing Semantic Models of Programs with the Software Analysis Workbench. In Verified Software. Theories, Tools, and Experiments (VSTTE) (Lecture Notes in Computer Science) , Sandrine Blazy and Marsha Chechik (Eds.), Vol. 9971. 56–72.Google Scholar
- J. Nathan Foster, Michael B. Greenwald, Jonathan T. Moore, Benjamin C. Pierce, and Alan Schmitt. 2005. Combinators for Bi-directional Tree Transformations: A Linguistic Approach to the View Update Problem. SIGPLAN Not. 40, 1 (Jan. 2005), 233–246.Google Scholar
Digital Library
- Jean-Yves Girard. 1987. Linear Logic. Theor. Comput. Sci. 50, 1 (Jan. 1987), 1–102.Google Scholar
Digital Library
- Colin S. Gordon, Matthew J. Parkinson, Jared Parsons, Aleks Bromfield, and Joe Duffy. 2012. Uniqueness and Reference Immutability for Safe Parallelism. SIGPLAN Not. 47, 10 (Oct. 2012), 21–40.Google Scholar
Digital Library
- Florian Hahn. 2015. Rust2Viper: Building a static verifier for Rust. Master’s thesis. ETH Zurich.Google Scholar
- Philipp Haller and Martin Odersky. 2010. Capabilities for Uniqueness and Borrowing. In European Conference on ObjectOriented Programming (ECOOP) (Lecture Notes in Computer Science) , Theo D’Hondt (Ed.), Vol. 6183. Springer, 354–378.Google Scholar
- Chris Hawblitzel, Jon Howell, Manos Kapritsos, Jacob R. Lorch, Bryan Parno, Michael L. Roberts, Srinath Setty, and Brian Zill. 2015. IronFleet: Proving Practical Distributed Systems Correct. In Symposium on Operating Systems Principles (SOSP), Ethan L. Miller and Steven Hand (Eds.). ACM, 1–17.Google Scholar
Digital Library
- Chris Hawblitzel, Jon Howell, Jacob R. Lorch, Arjun Narayan, Bryan Parno, Danfeng Zhang, and Brian Zill. 2014. Ironclad Apps: End-to-End Security via Automated Full-System Verification. In Operating Systems Design and Implementation (OSDI) , Jason Flinn and Hank Levy (Eds.). USENIX Association, 165–181.Google Scholar
- Stefan Heule, K. Rustan M. Leino, Peter Müller, and Alexander J. Summers. 2013. Abstract Read Permissions: Fractional Permissions without the Fractions. In Verification, Model Checking, and Abstract Interpretation (VMCAI) (Lecture Notes in Computer Science) , Vol. 7737. Springer, 315–334.Google Scholar
- Cliff B. Jones. 1983. Specification and design of (parallel) programs. In IFIP Congress. 321–332.Google Scholar
- Ralf Jung, Jacques-Henri Jourdan, Robbert Krebbers, and Derek Dreyer. 2018. RustBelt: Securing the Foundations of the Rust Programming Language. PACMPL 2, POPL (2018), 66:1–66:34.Google Scholar
Digital Library
- Ralf Jung, David Swasey, Filip Sieczkowski, Kasper Svendsen, Aaron Turon, Lars Birkedal, and Derek Dreyer. 2015. Iris: Monoids and Invariants as an Orthogonal Basis for Concurrent Reasoning. ACM SIGPLAN Notices 50, 1 (2015), 637–650.Google Scholar
Digital Library
- Shuanglong Kan, David Sanán, Shang-Wei Lin, and Yang Liu. 2018. K-Rust: An Executable Formal Semantics for Rust. CoRR abs/1804.07608 (2018). arXiv: 1804.07608 http://arxiv.org/abs/1804.07608Google Scholar
- Ioannis T. Kassios. 2011. The Dynamic Frames Theory. Formal Aspects of Computing 23, 3 (2011), 267–289.Google Scholar
Digital Library
- Gerwin Klein, Kevin Elphinstone, Gernot Heiser, June Andronick, David Cock, Philip Derrin, Dhammika Elkaduwe, Kai Engelhardt, Rafal Kolanski, Michael Norrish, Thomas Sewell, Harvey Tuch, and Simon Winwood. 2009. seL4: Formal Verification of an OS Kernel. In Symposium on Operating Systems Principles (SOSP), Jeanna Neefe Matthews and Thomas E. Anderson (Eds.). ACM, 207–220.Google Scholar
Digital Library
- Gary T. Leavens, Erik Poll, Curtis Clifton, Yoonsik Cheon, Clyde Ruby, David Cok, Peter Müller, Joseph Kiniry, Patrice Chalin, Daniel M. Zimmerman, and Werner Dietl. 2011. JML Reference Manual. http://www.jmlspecs.org/ .Google Scholar
- K. Rustan M. Leino. 2010. Dafny: An Automatic Program Verifier for Functional Correctness. In Logic for Programming, Artificial Intelligence, and Reasoning (LPAR) (Lecture Notes in Computer Science) , Edmund M. Clarke and Andrei Voronkov (Eds.), Vol. 6355. Springer, 348–370.Google Scholar
- K. Rustan M. Leino and Peter Müller. 2004. Object Invariants in Dynamic Contexts. In European Conference on Object-Oriented Programming (ECOOP) (Lecture Notes in Computer Science) , M. Odersky (Ed.), Vol. 3086. Springer, 491–516.Google Scholar
- K. Rustan M. Leino and Greg Nelson. 2002. Data Abstraction and Information Hiding. ACM Trans. Program. Lang. Syst. 24, 5 (2002), 491–553.Google Scholar
Digital Library
- Marcus Lindner, Jorge Aparicius, and Per Lindgren. 2018. No Panic! Verification of Rust Programs by Symbolic Execution. In Industrial Informatics (INDIN). IEEE, 108–114.Google Scholar
- Maroua Maalej, Tucker Taft, and Yannick Moy. 2018. Safe Dynamic Memory Management in Ada and SPARK. (2018).Google Scholar
- Nicholas D. Matsakis. 2018a. MIR-based borrow check (NLL) status update. http://smallcultfollowing.com/babysteps/blog/ 2018/06/15/mir-based-borrow-check-nll-status-update Accessed April 4, 2019.Google Scholar
- Nicholas D. Matsakis. 2018b. MIR-based borrowck is almost here. http://smallcultfollowing.com/babysteps/blog/2018/10/ 31/mir-based-borrowck-is-almost-here/ Accessed April 4, 2019.Google Scholar
- Nicholas D. Matsakis and Felix S. Klock II. 2014. The Rust language. In ACM SIGAda Ada Letters, Vol. 34. ACM, 103–104.Google Scholar
- Bertrand Meyer. 1992. Design by Contract. In Advances in object-oriented software engineering, Dino Mandrioli and Bertrand Meyer (Eds.). Prentice Hall, 1–50.Google Scholar
- P. Müller. 2002. Modular Specification and Verification of Object-Oriented Programs. Lecture Notes in Computer Science, Vol. 2262. Springer.Google Scholar
Cross Ref
- Peter Müller, Malte Schwerhoff, and Alexander J. Summers. 2016. Viper: A Verification Infrastructure for Permission-Based Reasoning. In VMCAI (Lecture Notes in Computer Science), Barbara Jobstmann and K. Rustan M. Leino (Eds.), Vol. 9583. Springer, 41–62.Google Scholar
- Peter W. O’Hearn. 2004. Resources, Concurrency and Local Reasoning. In Concurrency Theory (CONCUR) (Lecture Notes in Computer Science) , Philippa Gardner and Nobuko Yoshida (Eds.), Vol. 3170. Springer, 49–67.Google Scholar
- Peter W. O’Hearn, John C. Reynolds, and Hongseok Yang. 2001. Local Reasoning about Programs that Alter Data Structures. In Computer Science Logic (CSL) (Lecture Notes in Computer Science), Laurent Fribourg (Ed.), Vol. 2142. Springer, 1–19.Google Scholar
- Susan Owicki and David Gries. 1976. Verifying Properties of Parallel Programs: An Axiomatic Approach. Commun. ACM 19, 5 (May 1976), 279–285.Google Scholar
Digital Library
- Matthew J. Parkinson and Gavin M. Bierman. 2005. Separation logic and abstraction. In Principles of Programming Languages (POPL) , Jens Palsberg and Martín Abadi (Eds.). ACM, 247–258.Google Scholar
- Matthew J. Parkinson and Alexander J. Summers. 2012. The Relationship Between Separation Logic and Implicit Dynamic Frames. Logical Methods in Computer Science 8, 3:01 (2012), 1–54.Google Scholar
Cross Ref
- Eric W. Reed. 2015. Patina: A Formalization of the Rust Programming Language. Technical Report UW-CSE-15-03-02. University of Washington.Google Scholar
- John C. Reynolds. 2002. Separation Logic: A Logic for Shared Mutable Data Structures. In Logic in Computer Science (LICS). IEEE Computer Society, 55–74.Google Scholar
- Patrick M. Rondon, Ming Kawaguci, and Ranjit Jhala. 2008. Liquid Types. SIGPLAN Not. 43, 6 (June 2008), 159–169.Google Scholar
Digital Library
- Rosetta Code contributors. 2018. Rosetta Code. https://rosettacode.org/wiki/Category:Rust Accessed November 5, 2018.Google Scholar
- Rust community. 2017. Non-Lexical Lifetimes RFC. https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md Accessed November 4, 2018.Google Scholar
- Rust community. 2018a. The Rust community’s crate registry. https://crates.io Downloaded on November 2, 2018.Google Scholar
- Rust community. 2018b. Rust: The Reference — Place Expressions and Value Expressions. https://doc.rust-lang.org/ reference/expressions.html#place-expressions-and-value-expressions Accessed November 4, 2018.Google Scholar
- Rust community. 2019. Learn Rust by writing Entirely Too Many Linked Lists. https://rust-unofficial.github.io/too-manylists/first-final.html Accessed April 4, 2019.Google Scholar
- Rust contributors. 2019a. The Polonius Reference Implementation for the Rust Borrow-Checker. https://github.com/rustlang/polonius Accessed April 4, 2019.Google Scholar
- Rust contributors. 2019b. The Rustonomicon: Working with Unsafe. https://doc.rust-lang.org/nomicon/working-withunsafe.html Accessed April 4, 2019.Google Scholar
- Rust contributors. 2019c. Tracking issue for generalized two-phase borrows. https://github.com/rust-lang/rust/issues/49434 Accessed April 4, 2019.Google Scholar
- Malte Schwerhoff and Alexander J. Summers. 2015. Lightweight Support for Magic Wands in an Automatic Verifier. In European Conference on Object-Oriented Programming (ECOOP) (LIPIcs) , J. T. Boyland (Ed.), Vol. 37. Schloss Dagstuhl, 614–638.Google Scholar
- Jan Smans, Bart Jacobs, and Frank Piessens. 2009. Implicit Dynamic Frames: Combining Dynamic Frames and Separation Logic. In European Conference on Object-Oriented Programming (ECOOP) (Lecture Notes in Computer Science), Sophia Drossopoulou (Ed.), Vol. 5653. Springer, 148–172.Google Scholar
- Jan Smans, Bart Jacobs, and Frank Piessens. 2010. Heap-Dependent Expressions in Separation Logic. In Formal Techniques for Distributed Systems (FMOODS/FORTE) (Lecture Notes in Computer Science) , John Hatcliff and Elena Zucca (Eds.), Vol. 6117. Springer, 170–185.Google Scholar
- Sven Stork, Karl Naden, Joshua Sunshine, Manuel Mohr, Alcides Fonseca, Paulo Marques, and Jonathan Aldrich. 2014. AEMinium: A Permission-Based Concurrent-by-Default Programming Language Approach. ACM Trans. Program. Lang. Syst. 36, 1 (March 2014), 2:1–2:42.Google Scholar
Digital Library
- Alexander J. Summers and Sophia Drossopoulou. 2013. A Formal Semantics for Isorecursive and Equirecursive State Abstractions. In European Conference on Object-Oriented Programming (ECOOP) (Lecture Notes in Computer Science), Giuseppe Castagna (Ed.), Vol. 7920. Springer, 129–153.Google Scholar
- John Toman, Stuart Pernsteiner, and Emina Torlak. 2015. Crust: A Bounded Verifier for Rust (N). In Automated Software Engineering (ASE) , Myra B. Cohen, Lars Grunske, and Michael Whalen (Eds.). IEEE, 75–80.Google Scholar
- Sebastian Ullrich. 2016. Simple Verification of Rust Programs via Functional Purification. Master’s thesis. Karlsruhe Institute of Technology.Google Scholar
- Feng Wang, Fu Song, Min Zhang, Xiaoran Zhu, and Jun Zhang. 2018. KRust: A Formal Executable Semantics of Rust. CoRR abs/1804.10806 (2018). arXiv: 1804.10806 http://arxiv.org/abs/1804.10806Google Scholar
- Aaron Weiss, Daniel Patterson, and Amal Ahmed. 2018. Rust Distilled: An Expressive Tower of Languages. arXiv preprint arXiv:1806.02693 (2018).Google Scholar
Index Terms
Leveraging rust types for modular specification and verification
Recommendations
Verus: Verifying Rust Programs using Linear Ghost Types
The Rust programming language provides a powerful type system that checks linearity and borrowing, allowing code to safely manipulate memory without garbage collection and making Rust ideal for developing low-level, high-assurance systems. For such ...
Flux: Liquid Types for Rust
We introduce Flux, which shows how logical refinements can work hand in glove with Rust's ownership mechanisms to yield ergonomic type-based verification of low-level pointer manipulating programs. First, we design a novel refined type system for Rust ...
Efficient Verification of Sequential and Concurrent C Programs
There has been considerable progress in the domain of software verification over the last few years. This advancement has been driven, to a large extent, by the emergence of powerful yet automated abstraction techniques such as predicate abstraction. ...






Comments