Automated Software Verification with Implicit Dynamic Frames 5 th December 2013, Leuven Malte Schwerhoff, ETH Zürich/KU Leuven.

Slides:



Advertisements
Similar presentations
A Framework for describing recursive data structures Kenneth Roe Scott Smith.
Advertisements

Joint work with Mike Barnett, Robert DeLine, Manuel Fahndrich, and Wolfram Schulte Verifying invariants in object-oriented programs K. Rustan M. Leino.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 18 Program Correctness To treat programming.
Technologies for finding errors in object-oriented software K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 1 Summer school on Formal Models.
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Automated Verification with HIP and SLEEK Asankhaya Sharma.
Semantics Static semantics Dynamic semantics attribute grammars
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
A Program Transformation For Faster Goal-Directed Search Akash Lal, Shaz Qadeer Microsoft Research.
ICE1341 Programming Languages Spring 2005 Lecture #6 Lecture #6 In-Young Ko iko.AT. icu.ac.kr iko.AT. icu.ac.kr Information and Communications University.
Verifying Executable Object-Oriented Specifications with Separation Logic Stephan van Staden, Cristiano Calcagno, Bertrand Meyer.
Constraint Semantics for Abstract Read Permissions 28 th July 2014, FTfJP, Uppsala John Tang Boyland (UW-Milwaukee/ETH Zurich) Peter Müller, Malte Schwerhoff,
Automated Software Verification with a Permission-Based Logic 20 th June 2014, Zürich Malte Schwerhoff, ETH Zürich.
A survey of techniques for precise program slicing Komondoor V. Raghavan Indian Institute of Science, Bangalore.
Copyright © 2006 Addison-Wesley. All rights reserved.1-1 ICS 410: Programming Languages Chapter 3 : Describing Syntax and Semantics Axiomatic Semantics.
ISBN Chapter 3 Describing Syntax and Semantics.
Changing perspective can be useful Relating alternative logics for automatic software verification Alex Summers (ETH Zurich) partly based on joint work.
Fractional Permissions without the Fractions Alex Summers ETH Zurich Joint work with: Stefan Heule, Rustan Leino, Peter Müller ETH Zurich MSR Redmond ETH.
ECI 2007: Specification and Verification of Object-Oriented Programs Lecture 2 Courtesy: K. Rustan M. Leino and Wolfram Schulte.
Lecture 2 Towards a Verifying Compiler: Logic of Object oriented Programs Wolfram Schulte Microsoft Research Formal Methods 2006 Objects, references, heaps,
ESC Java. Static Analysis Spectrum Power Cost Type checking Data-flow analysis Model checking Program verification AutomatedManual ESC.
Static and Dynamic Contract Verifiers For Java Hongming Liu.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 18 Program Correctness To treat programming.
ESC Java. Static Analysis Spectrum Power Cost Type checking Data-flow analysis Model checking Program verification AutomatedManual ESC.
CS 330 Programming Languages 09 / 16 / 2008 Instructor: Michael Eckmann.
Well-cooked Spaghetti: Weakest-Precondition of Unstructured Programs Mike Barnett and Rustan Leino Microsoft Research Redmond, WA, USA.
Describing Syntax and Semantics
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Caltech Pasadena, CA 12 November 2009.
TODAY’S LECTURE Review Chapter 2 Go over exercises.
K. Rustan M. Leino RiSE, Microsoft Research, Redmond joint work with Peter Müller and Jan Smans Lecture 0 1 September 2009 FOSAD 2009, Bertinoro, Italy.
K. Rustan M. Leino RiSE, Joint work with: Peter Müller (ETH Zurich) Jan Smans (KU Leuven) Special thanks to Mike Barnett VMCAI, Madrid, Spain, 18 January.
Computer Science School of Computing Clemson University Discrete Math and Reasoning about Software Correctness Murali Sitaraman
Crowfoot: a verifier for higher order store programs Billiejoe (Nathaniel) Charlton Ben Horsfall Bernhard Reus University of Sussex VMCAI 2012.
1 Debugging and Testing Overview Defensive Programming The goal is to prevent failures Debugging The goal is to find cause of failures and fix it Testing.
Aquinas Hobor and Cristian Gherghina (National University of Singapore) TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.:
1 Program Correctness CIS 375 Bruce R. Maxim UM-Dearborn.
CSI 3125, Axiomatic Semantics, page 1 Axiomatic semantics The assignment statement Statement composition The "if-then-else" statement The "while" statement.
K. Rustan M. Leino RiSE, Microsoft Research 1 Dec 2008 Invited talk, working group meeting COST Action IC0701, Formal Verification of Object-Oriented Software.
20 th December 2012, Dagstuhl Comparing Verification Condition Generation with Symbolic Execution Malte Schwerhoff, ETH Zürich Joint work with Yannis Kassios,
ISBN Chapter 3 Describing Semantics -Attribute Grammars -Dynamic Semantics.
Computer Science School of Computing Clemson University Discrete Math and Reasoning about Software Correctness Joseph E. Hollingsworth
Viper A Verification Infrastructure for Permission-Based Reasoning 1 st March 2015, ECOOP’15 PC Meeting, Zurich Uri Juhasz, Ioannis Kassios, Peter Müller,
Viper A Verification Infrastructure for Permission-Based Reasoning 24 th March 2015, JML Workshop, Leiden Uri Juhasz, Ioannis Kassios, Peter Müller, Milos.
Rustan Leino RiSE, Microsoft Research, Redmond MIT 5 June 2009 Joint work with: Peter Müller, ETH Zurich Jan Smans, KU Leuven.
Cristian Gherghina 1, Cristina David 1, Shengchao Qin 2, Wei-Ngan Chin 1 1 National University of Singapore 2 University of Teesside Structured Specifications.
A Universe-Type-Based Verification Technique for Mutable Static Fields and Methods Alexander J Summers Sophia Drossopoulou Imperial College London Peter.
Chapter 3 Part II Describing Syntax and Semantics.
Semantics In Text: Chapter 3.
1 CSCD 326 Data Structures I Software Design. 2 The Software Life Cycle 1. Specification 2. Design 3. Risk Analysis 4. Verification 5. Coding 6. Testing.
Spec# Andreas Vida. Motivation Correct and maintainable software Correct and maintainable software Cost effective software production Cost effective software.
ANU COMP2110 Software Design in 2003 Lecture 10Slide 1 COMP2110 Software Design in 2004 Lecture 12 Documenting Detailed Design How to write down detailed.
Lightweight Support for Magic Wands in an Automatic Verifier Malte Schwerhoff and Alexander J. Summers 10 th July 2015, ECOOP, Prague.
An Introduction to Automated Program Verification with Permission Logics 15 th May 2015, Systems Group, ETH Zurich Uri Juhasz, Ioannis Kassios, Peter Müller,
PROGRAMMING PRE- AND POSTCONDITIONS, INVARIANTS AND METHOD CONTRACTS B MODULE 2: SOFTWARE SYSTEMS 13 NOVEMBER 2013.
Static Techniques for V&V. Hierarchy of V&V techniques Static Analysis V&V Dynamic Techniques Model Checking Simulation Symbolic Execution Testing Informal.
VSTTE’12 29 th January 2012, Philadelphia Comparing Verification Condition Generation with Symbolic Execution Malte Schwerhoff, ETH Zurich Joint work with.
ESOP 2010, Paphos, Cyprus, 22 March 2010 K. Rustan M. Leino (RiSE group, Microsoft Research) Peter Müller (ETH Zurich) Jan Smans (KU Leuven)
DBC NOTES. Design By Contract l A contract carries mutual obligations and benefits. l The client should only call a routine when the routine’s pre-condition.
Spring 2017 Program Analysis and Verification
A Verification Infrastructure for Permission-based Reasoning
The Relationship Between Separation Logic and Implicit Dynamic Frames
The Relationship Between Separation Logic and Implicit Dynamic Frames
Modular Verification of Message Passing Programs
Stateful Manifest Contracts
The Metacircular Evaluator
Programming Languages 2nd edition Tucker and Noonan
A Verification Infrastructure for Permission-Based Reasoning
Programming Languages and Compilers (CS 421)
Programming Languages 2nd edition Tucker and Noonan
A Considerate Specification of the Composite Pattern
Presentation transcript:

Automated Software Verification with Implicit Dynamic Frames 5 th December 2013, Leuven Malte Schwerhoff, ETH Zürich/KU Leuven

A long time ago, in a galaxy far, far away...

Outline 1.Implicit Dynamic Frames 2.Our Tool Chain 3.Supporting Magic Wands

‐ SL: Points-to relations and logical variables requires x.f |-> ?v & * & v > 0 ‐ IDF: Access predicates and heap access requires acc(x.f) && x.f > 0 ‐ IDF-Assertions must be self-framing, i.e., only talk about locations to which access is requested requires acc(x.f) && x.f > 0  self-framing requires x.f > 0  not self-framing requires x.f > 0 && acc(x.f)  neither (technical reason) (SL-assertions are self-framing by design) 4 Heap-Dependent Expressions

Separation Logic 5 Example method inc(c: Cell) requires c.f |-> ?v & * & v > 0 ensures c.f |-> v + 1 { c.f = c.f + 1 } old(e) evaluates to the value e had in the pre-heap of the method call Implicit Dynamic Frames method inc(c: Cell) requires acc(c.f) && c.f > 0 ensures acc(c.f) && c.f == old(c.f) + 1 { c.f = c.f + 1 }

6 Data Abstraction SL: Abstract Predicates predicate Cell(c: Cell; v: Int) { c.f |-> v} method inc(c: Cell) requires Cell(c, ?v) & * & v > 0 ensures Cell(c, v + 1) { open Cell(c, v) c.f = c.f + 1 close Cell(c, v + 1) } ‐ Ghost statements open/close guide the verifier; erased at runtime ‐ Opening a predicate instance means consuming the instance and producing its body (closing is the inverse operation)

7 Data Abstraction IDF: Abstract Predicates and Pure Functions predicate Cell(c: Cell) { acc(c.f) } function get(c: Cell): Int requires acc(Cell(c)) { unfolding Cell(c) in c.f } method inc(c: Cell) requires acc(Cell(c)) && get(c) > 0 ensures acc(Cell(c) && get(c) == old(get(c)) + 1 { unfold Cell(c) c.f = c.f + 1 fold Cell(c) } Ghost expression unfolding P in e makes the body of P temporarily available

‐ SL: Predicates have in- and out-parameters; out-parameters are uniquely determined by the in- parameters and the predicate body ‐ IDF: Predicates have in-parameters, functions replace the out-parameters 8 Predicates and Functions Separation Logic predicate Cell(c: Cell; v: Int) = c.f |-> v Implicit Dynamic Frames predicate Cell(c: Cell) { acc(c.f) } function get(c: Cell): Int requires acc(Cell(c)) { unfolding Cell(c) in c.f }

9 Predicates and Functions Implicit Dynamic Frames predicate Node(n: Node) { acc(n.val) && acc(n.nxt) && (n.nxt != null ==> acc(Node(n.nxt))) } function length(n: Node): Int requires acc(Node(n)) { unfolding Node(n) in 1 + (n.nxt == null ? 0 : length(n.nxt)) } function elems(n: Node): Seq[Int] requires acc(Node(n)) { unfolding Node(n) in n.val :: (n.nxt == null ? Nil : elems(n.nxt)) } ‐ SL: length and elems could be out-parameters ‐ Adding additional out-parameters later on potentially entails lots of code changes ‐ Adding new functions in subclasses feels “natural” ‐ IDF: Separate heap shape description from abstractions

10 Functions Implicit Dynamic Frames if (length(node) > 2)... ‐ IDF: Functions can be used in code, too! ‐ SL: Predicate arguments and methods are needed Separation Logic predicate Cell(c: Cell; v: Int) { c.f |-> v} method length(c: Cell): Int requires Cell(c, ?v) ensures result == v { open Cell(c, v) return c.f close Cell(c, v) }

Outline 1.Implicit Dynamic Frames 2.Our Tool Chain 3.Supporting Magic Wands

12 SIL and Silicon SIL Silicon Z3 (Microsoft) ‐ SIL is an intermediate verification language; programs with specifications can be encoded in SIL ‐ Objects, fields, methods, if-else, loops ‐ Simple: rudimentary type system (primitives + Ref), no inheritance (yet?), no concurrency ‐ IDF-based assertion language; fractional permissions; sequences, sets, multisets; quantifiers; custom theories ‐ Silicon is a symbolic-execution-based verifier for SIL ‐ Z3 is used to discharge Boolean proof obligations verified by queries

13 Encoding in SIL SIL Chalice2S il (BSc thesis) Scala2Sil (MSc thesis) Chalice is a research language for concurrency ‐ Objects, fields, loops,... ‐ Fork-join concurrency ‐ Communication via channels (message passing) ‐ Locking with lock invariants ‐ Deadlock-avoidance Scala is a OO+FP hybrid language for the JVM ‐ … with crazily many features ‐ Only translated basics, including ‐ val x = e (≈ final fields in Java) ‐ lazy val x = e (evaluated on first read) encode in

14 Verification of SIL code SIL SiliconCarbon Boogie (Microsoft) Z3 (Microsoft) verified by encode in queries encode in Verification Condition Generation Symbolic Execution

Query prover once with full information (VeriCool) 15 Short deviation: VCG vs SE ProgramVerifier read bycalculates Prover given to WPs one weakest precondition per method VCG Query prover often with limited information (VeriFast) ProgramVerifier read by maintains Symbolic State σ symbolically execute every path through every method query prover at every step if next statement is executable Prover used by σ1σ1 σ2σ2 σ3σ3 σ4σ4 σ5σ5 SE

16 Verification of SIL code SIL SiliconCarbon Boogie (Microsoft) Z3 (Microsoft) verified by encode in queries encode in Parallel approach allows experimenting with new features and encodings; it helps uncovering weaknesses or performance problems

17 Overview SIL SiliconCarbon Boogie (Microsoft) Z3 (Microsoft) Chalice2S il (BSc thesis) Scala2Sil (BSc thesis) verified by encode in queries encode in

Outline 1.Implicit Dynamic Frames 2.Our Tool Chain 3.Supporting Magic Wands (joint work with Alexander J. Summers)

‐ Boolean implication A ⇒ B “If A holds in the current state, then B also holds“ Modus Ponens: A ∧ (A ⇒ B) ⊨ B ‐ Separating implication: A —∗ B “If A is added to the current state, then B also holds“ (Kind of) Modus Ponens: A ∗ (A —∗ B) ⊨ B ‐ A —∗ B Can be read as an exchange promise “If A is given up, then B is guaranteed to hold“ 19 Magic Wands

‐ Semantics of the Wand: h ⊨ A —∗ B ⇔ ∀ h’ h · (h’ ⊨ A ⇒ h ⊎ h’ ⊨ B) ‐ Quantification over states, hence typically not supported in automated verifiers ‐ Used in proofs by hand, for example, when verifying linked lists with views (generalised iterators) ‐ The promise-interpretation lends itself to specifying partial data structures, for example, “Give up a list segment and you’ll get back the whole linked list“ 20 Magic Wands, Anyone? ⊢

21 Iterating Over Recursively-Defined Data Structures var val: Int var next: Ref predicate List(ys: Ref) { acc(ys.val) && acc(ys.next) && (ys.next != null ==> acc(List(ys.next))) } function sum_rec(ys: Ref): Int requires acc(List(ys)) { unfolding List(ys) in ys.val + (ys.next == null ? 0 : sum_rec(ys.next)) } method sum_it(ys: Ref) returns (sum: Int) /* Iteratively compute the sum of the linked list s.t. * the result equals sum_rec(ys) */

22 Iterating Over Recursively-Defined Data Structures method sum_it(ys: Ref) returns (sum: Int) requires ys != null && acc(List(ys)) ensures acc(List(ys)) && sum == old(sum_rec(ys)) { var xs: Ref := ys /* Pointer to the current node in the list */ sum := 0 /* Sum computed so far */ while (xs != null) invariant xs != null ==> acc(List(xs)) invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next } ~~~~~~~~~~~~~~ How to bookkeep permissions to the “list seen so far”? /* ??? */

—∗

24 Our Solution var xs: Ref := ys /* Pointer to the current node in the list */ sum := 0 /* Sum computed so far */ /* Short-hands to keep the specifications concise */ define A xs != null ==> acc(List(xs)) define B acc(List(ys)) Here, A —∗ B reflects the promise “If you give up the current tail of the list ( xs ), then you’ll get back the whole list ( ys )”

25 Our Solution define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B } apply A --* B

Establish wand 26 Our Solution define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B } apply A --* B

X 27 Our Solution define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B } apply A --* B Carry wand

28 Update wand } Our Solution define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B apply A --* B

Use wand 29 Our Solution define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B } apply A --* B

‐ Lifecycle of wand and predicate instances are similar ‐ Created (packaged/folded) ‐ Passed around (loop invariants, postconditions) ‐ Destroyed (applied/unfolded) ‐ Unfolding a predicate gives assumptions about the heap ‐ Sound, because the permissions that frame these assumptions are consumed when the predicate is folded (and the assumptions are checked) ‐ These permissions are the footprint of a predicate ‐ What is the footprint of a wand? 30 Lifecycle

31 Footprints ‐ Examples ‐ true —∗ acc(x.f)| acc(x.f) ‐ acc(x.f) —∗ acc(x.f)| emp ‐ acc(x.f, 1/3) —∗ acc(x.f, 1/1)| acc(x.f, 2/3) ‐ acc(x.f) —∗ acc(x.g)| acc(x.g) ‐ The footprint of A —∗ B is the delta between A and B ‐ Consumed when A —∗ B is packaged and produced when A —∗ B is applied

32 Footprints and Assumptions ‐ Examples ‐ σ: acc(x.f) && x.f = 1 package true —∗ acc(x.f) && x.f = 1 ‐ σ: acc(x.f) && x.f = 1 package acc(x.f) —∗ acc(x.f) && x.f = 1 ‐ σ: acc(x.f) && x.f = 1 && acc(x.g) && x.g = 2 package acc(x.f) && x.f =2 —∗ acc(x.f) && acc(x.g) && x.f = x.g ‐ When checking assumptions of the RHS, use the assumptions from the LHS, and those of the current state if framed by the footprint ‐ Claim: sound, regardless of the computed footprint   

‐ Circularity problem ‐ Footprint is determined by permissions requested by the RHS (and not provided by the LHS) ‐ Permissions might be conditionally requested (if-then- else) ‐ Guards of these conditionals might be determined by the current heap ‐ Assumptions about the current heap can only be used if framed by the footprint ‐ … which we currently try to compute :-( 33 Footprints and Assumptions

‐ Compute footprint in parallel with checking the RHS ‐ Setup ‐ Let σ curr be the current heap ‐ Let σ foot be the initially empty footprint state ‐ Produce the LHS into emp to get σ lhs ‐ Algorithm ‐ Consume permissions requested by the RHS from σ lhs, and only from σ curr if σ lhs does not provide sufficient permissions ‐ If taken from σ curr, move effected permissions (and move/copy assumptions) into σ foot ‐ Check assumptions made by the RHS in the combination of σ lhs and σ foot 34 Our Solution

35 Update wand } Back to the Code define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B apply A --* B

36 Packaging Wands with Ghost Operations ys xs null List(xs) --* List(ys) List(xs) var zs := xs; unfold List(xs); xs := xs.next ys zs xs null List(zs) --* List(ys) List(xs) acc(zs.val) acc(zs.next) package List(xs) --* folding List(zs) in applying List(zs) --* List(ys) in List(ys) ys zs xs null List(xs) --* List(ys) List(xs)

‐ Interaction with the footprint: delta between permissions produced/consumed by ghost operations ‐ Prover hints only, created wand instance is List(xs) --* List(ys) ‐ Nicely blend into SIL, which has unfolding already 37 Packaging Wands with Ghost Operations ys zs xs null List(zs) --* List(ys) List(xs) acc(zs.val) acc(zs.next) package List(xs) --* folding List(zs) in applying List(zs) --* List(ys) in List(ys)

38 Code (Last Time, I Promise) define A xs != null ==> acc(List(xs)) define B acc(List(ys)) package A --* B while (xs != null) invariant (xs != null ==> acc(List(xs))) && A --* B invariant sum == old(sum_rec(ys)) - (xs == null ? 0 : sum_rec(xs)) { wand w := A --* B /* Give magic wand instance the name w */ var zs: Ref := xs unfold List(xs) sum := sum + xs.val xs := xs.next package A --* folding List(zs) in applying w in B } apply A --* B

‐ Implicit Dynamic Frames ‐ Allows for (relatively) nice specifications ‐ Simplifies contrasting VCG and SE ‐ Intermediate Verification Language SIL ‐ Potential to encode other languages into it looks promising ‐ VCG and SE backends facilitate experiments ‐ Magic Wands ‐ Useful for specifying partial data structures ‐ Lightweight support that nicely integrates into IDF 39 Conclusion

‐ Tool Chain ‐ Polish it (documentation, IDE, debugger) ‐ Release it (and merge various branches) ‐ Continue Scala2Sil ‐ Magic Wands ‐ Demonstrate other applications ‐ More examples ‐ Support in VCG? 40 Future Work

Questions?