Download presentation

Presentation is loading. Please wait.

Published byDonte Robey Modified about 1 year 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

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google