Le Lever eragin aging g Rust Types es for Modular lar Speci cification and Verification Vytautas Astrauskas Peter Müller Federico Poli Alexander J. Summers Department of Computer Science
Analogy with C verification void client(list * a, list * b) Functional properties { int old_len = b->len; Memory Errors append(a, 100); assert(b->len == old_len); Aliasing } C Data Races 1
Verification Ingredients Predicates Memory * list(a) list(b) Auxiliary annotations Disjointness … acc(b.len) of memory Ownership / Permissions What is this like to use? 2
Verification Ingredients at Scale Owned field Predicate Requires an expert Auxiliary Owned field Disjointness Predicate annotation Disjointness Disjointness Owned field Predicate Disjointness Predicate Auxiliary Predicate Auxiliary annotation Owned field annotation Auxiliary annotation Auxiliary Owned field Predicate annotation Auxiliary Owned field annotation Auxiliary Disjointness Auxiliary annotation annotation Auxiliary Predicate annotation Disjointness Auxiliary Auxiliary annotation Predicate These steps are mandatory annotation Disjointness Auxiliary Auxiliary Disjointness Predicate annotation annotation Disjointness Auxiliary Auxiliary annotation annotation Auxiliary annotation Auxiliary Auxiliary Predicate Auxiliary annotation annotation annotation Auxiliary Predicate annotation Auxiliary annotation Auxiliary Auxiliary Predicate annotation annotation “Core proof” Auxiliary Auxiliary annotation annotation Predicate Disjointness 3
Rust, and its type system fn client(a: &mut List, b: &mut List) Functional properties { let old_len = b.len(); No Memory Errors Memory Errors? append(a, 100); assert!(b.len() == old_len); Controlled Aliasing Aliasing? } Rust No Data Races Data Races? Can we exploit this type system for verification ? 4
Wha What woul uld d we like? 5
Prusti: An Overview Specs Leveraging Rust Types for Modular Specification and Verification To appear at OOPSLA 2019, Athens, Greece (next week) 6 https://www.rust-lang.org/logos/rust-logo-blk.svg is licensed under CC BY 4.0
The Prusti Approach Rust Verification Ingredients Predicates and Types Ownership Signature Pre/postconditions Compiler analyses Auxiliary annotations (e.g. borrow checker) U s a n b o l n e User specifications - e b Functional specification x y p (optional) e r t s 7
Core Proofs: Behind the Scenes Owned field Ownership, Predicates, Annotations Predicate Requires an expert Auxiliary Owned field Disjointness Predicate annotation Disjointness Disjointness all generated automatically Owned field Predicate Disjointness Predicate Auxiliary Predicate Auxiliary annotation Owned field annotation Auxiliary annotation Auxiliary Owned field Predicate annotation Auxiliary Owned field annotation Auxiliary Disjointness Auxiliary annotation annotation Auxiliary Predicate annotation Disjointness Users write functional specifications Auxiliary Auxiliary annotation Predicate These steps are mandatory annotation Disjointness Auxiliary Auxiliary Disjointness (optionally) Predicate annotation annotation Disjointness Auxiliary Auxiliary annotation annotation Auxiliary annotation Auxiliary Auxiliary Predicate Auxiliary annotation annotation annotation Auxiliary Predicate annotation Auxiliary annotation Auxiliary Auxiliary Predicate annotation annotation Abstraction level: Rust expressions Auxiliary Auxiliary annotation annotation Predicate Disjointness 8
Type Encoding struct List { val: i32 , next: Option < Box <List>> } Rust predicate List(self: Ref ) List { acc (self.val) ⁎ i32 val acc (self.next) ⁎ self i32(self.val) ⁎ next OptionBoxList OptionBoxList(self.next) } Viper 9
Signature Encoding fn client(a: &mut List, b: &mut List) Rust * a: List b: List method client(a: Ref , b: Ref ) method client(a: Ref , b: Ref ) requires List(a) ⁎ List(b) requires List(a) ⁎ List(b) && a.sorted() && … ensures List(a) ⁎ List(b) ensures List(a) ⁎ List(b) && a.sorted() Viper 10
Reborrowing Challenges fn get(t: &mut BinaryTree) -> &mut BinaryTree { // traverse somehow; return a subtree } Rust Mutable Frozen For the caller: Mutable 11
Reborrowing Challenges fn get(t: &mut BinaryTree) -> &mut BinaryTree { // traverse somehow; return a subtree } Rust Permissions? Combined effect? 12
Reborrowing Challenges fn get(t: &mut BinaryTree) -> &mut BinaryTree { fn get(t: &mut BinaryTree) -> &mut BinaryTree { // return a subtree // traverse somehow; return a subtree } } Rust Permissions: magic wand Novel specification: pledges (see OOPSLA paper for details…) ( ) ꟷ * * s s 13
Evaluation (no specifications) 500 most 11’791 (21%) 100% of functions: downloaded supported core proof verifies packages (crates) functions No specification Total: ~40K loc Total: 1M lines of Viper Auxiliary annotations: 100K 14 https://www.rust-lang.org/logos/cargo.png is licensed under CC BY 4.0
Evaluation with specifications rosettacode.org + Specification 15
What else is in the paper? VIPER ENCODING AUTOMATION PLEDGES RUST SUBSET Leveraging Rust Types for Modular Specification and Verification To appear at OOPSLA 2019, Athens, Greece (next week) 16
Conclusion Plenty more to work on! e.g. closures, unsafe code, reference counting, standard libraries, … Dramatically simplifies Rust verification Enables verification by developers On the lookout for Master’s (ETH/UBC) and PhD students (UBC) - get in touch! prusti.ethz.ch 17
Recommend
More recommend