Download presentation
Presentation is loading. Please wait.
Published byDonte Robey Modified over 10 years ago
1
Automated Software Verification with a Permission-Based Logic 20 th June 2014, Zürich Malte Schwerhoff, ETH Zürich
2
Outline 1.Motivation 2.Permissions 3.Viper 4.Demo
3
‐ We have ‐ Mutable state (heap locations) ‐ Method calls, loops ‐ Concurrency ‐ We want: ‐ Automated static verification ‐ Modularity 3 Automated Software Verification
4
4 Example class Cell { var v: int method add(c: Cell) { v := v + c.v } } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 }
5
5 Modularity class Cell { var v: int method add(c: Cell) { v := v + c.v } } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 } ?
6
6 Specifications class Cell { var v: int method add(c: Cell) requires c != null ensures v == old(v) + old(c.v) { v := v + c.v } } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 }
7
7 Reasoning with Specifications class Cell { var v: int method add(c: Cell) requires c != null ensures v == old(v) + old(c.v) { v := v + c.v } } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 } ?
8
8 An Incorrect Implementation class Cell { var v: int method add(c: Cell) requires c != null ensures v == old(v) + old(c.v) { v := v + c.v c.v := 0 } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 }
9
9 Strengthening Specifications class Cell { var v: int method add(c: Cell) requires c != null ensures v == old(v) + old(c.v) ensures c.v == old(c.v) { v := v + c.v c.v := 0 } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 }
10
10 Strengthening Specifications method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 } class Cell { var v: int method add(c: Cell) requires c != null ensures v == old(v) + old(c.v) ensures c.v == old(c.v) { v := v + c.v } } ?
11
11 Aliasing class Cell { var v: int method add(c: Cell) requires c != null ensures v == old(v) + old(c.v) ensures c.v == old(c.v) { v := v + c.v } } method client() { var c1 := new Cell c1.v := 1 var c2 := new Cell c2.v := 2 c1.add(c1) // ensures c1.v == 1 + 1 // ensures c1.v == 1 assert c1.v == 3 assert c2.v == 2 }
12
Reason about Shared State & Control Aliasing 12 Challenges
13
‐ Use permissions to control access to shared state ‐ Permissions only exist conceptually, not at run-time ‐ Permissions ‐ Per field x.f ‐ Exclusive write permissions (allows reading as well) ‐ Non-exclusive read permissions 13 Permission-Based Verification
14
‐ Permissions to a location x.f can be ‐ Split into multiple read permissions ‐ Transferred between methods (or threads) ‐ Recombined again 14 Permission-Based Verification
15
15 Fractional Permissions client(x) add(x)
16
16 Splitting & Transferring Fractional Permissions ? client(x) add(x)
17
17 Merging Fractional Permissions ? client(x) add(x)
18
‐ Assumptions such as x.f == 0 can only be made if permissions to x.f are available ‐ If all permissions to x.f are lost, assumptions about x.f must be havoced (forgotten) 18 Permission-Based Verification
19
‐ Permissions can be split: acc(x.f, 1) ⇔ acc(x.f, 1/2) && acc(x.f, 1/2) ‐ Write permissions are exclusive: acc(x.f, 1) && acc(y.f, 1) ⇒ x ≠ y ‐ Write permissions are “maximal”: acc(x.f, 1) && acc(y.f, 1/100000) ⇒ x ≠ y 19 Syntax, Separating Conjunction
20
20 Return of the Example 20 method add(c: Cell) requires acc(v) && acc(c.v, 1/2) ensures acc(v) && acc(c.v, 1/2) ensures v == old(v) + c.v method client() { var c1 := new Cell // acc(c1.v) c1.v := 1 // c1.v == 1 var c2 := new Cell // acc(c2.v) c2.v := 2 // c2.v == 2 c1.add(c2) assert c1.v == 3 && c2.v == 2 } ?
21
21 Return of the Example 21 method add(c: Cell) requires acc(v) && acc(c.v, 1/2) ensures acc(v) && acc(c.v, 1/2) ensures v == old(v) + c.v method client() { var c1 := new Cell // acc(c1.v, 1) c1.v := 1 // c1.v == 1 var c2 := new Cell // acc(c2.v, 1) c2.v := 2 // c2.v == 2 c1.add(c2) assert c1.v == 3 && c2.v == 2 } Reason about call by exhaling precondition followed by inhaling postcondition
22
22 Return of the Example 22 method add(c: Cell) requires acc(v) && acc(c.v, 1/2) ensures acc(v) && acc(c.v, 1/2) ensures v == old(v) + c.v method client() {... // c1.add(c2) // acc(c1.v, 1) && c1.v == 1 && acc(c2.v, 1) && c2.v == 2 exhale acc(c1.v) && acc(c2.v, 1/2) // && acc(c2.v, 1/2) && c2.v == 2 inhale acc(c1.v) && acc(c.v, 1/2) // acc(c1.v, 1) && acc(c2.v, 1) && c2.v == 2 inhale c1.v == old(c1.v) + c2.v // acc(c1.v, 1) && c1.v == 3 && acc(c2.v, 1) && c2.v == 2 assert c1.v == 3 && c2.v == 2 }
23
23 Viper Silver SiliconCarbon Boogie (Microsoft) Z3 (Microsoft) verified by queries Verification Condition Generation Symbolic Execution
24
24 Silver ‐ Silver is an intermediate verification language ‐ Encode source languages (with specs) in Silver ‐ Use Silver verifier to verify encoding ‐ Simple: ‐ Objects, fields (heap), methods, loops, if-then-else ‐ Rudimentary type system (primitives + Ref) ‐ Verification features such as specifications ‐ No concurrency primitives ‐ Silver programs can be used for ‐ Verification ‐ Specification inference
25
25 Demo
26
26 Symbolic Execution with Silicon - Symbolically each method (method-modular) - At each statement: - query state (and prover) to decide if statement is executable - update state by exhaling precondition and inhaling postcondition - Branch over conditionals ProgramVerifier verifies maintains Symbolic State σ Prover uses σ1σ1 σ2σ2 σ3σ3 σ4σ4 σ5σ5 queries
27
Symbolic state σ comprises ‐ γ:Store mapping local variables to symbolic values (terms) c1 ↦ tc1, c2 ↦ tc2 ‐ h:Heap recording permissions to and values of fields in the form of heap chunks tc1.v ↦ tv1 # p1, tc2 ↦ tv2 # p2 ‐ π: Path conditions with assumptions about values tc1 ≠ null, tv1 > 0 27 Symbolic Execution with Silicon
28
28 Slide of the Undead Example 28 method client() {... // γ: c1 ↦ tc1, c2 ↦ tc2 // h: tc1.v ↦ tv1 # 1, tc2.v ↦ tv2 # 1 // π: tv1 == 1, tv2 == 2 exhale acc(c1.v) && acc(c2.v, 1/2) // h: tc2.v ↦ tv2 # 1/2 // π: tv1 == 1, tv2 == 2 inhale acc(c1.v) && acc(c.v, 1/2) // h: tc1.v ↦ tv1 # 1, tc2.v ↦ tv3 # 1 // π: tv1 == 1, tv2 == 2 inhale c1.v == old(c1.v) + c2.v // π: tv1 == 1, tv2 == 2, tv3 == tv1 + tv2 assert c1.v == 3 && c2.v == 2 // π ⊢ tv3 == 3 && tv2 == 2 }
29
‐ Information hiding and abstraction ‐ Recursive data structures ‐ Opposite of permissions: obligations ‐ Translation of high-level features ‐ Immutable data (vs. permissions) ‐ Lazy evaluation (vs. permissions) ‐ Closures ‐ Actor-based concurrency ‐ Specification inference 29 Outlook
30
30 Questions?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.