an introduction to automated program verification with permission logics 15 th may 2015, systems...
DESCRIPTION
3 Initial Example (Pseudo Java) class Cell { int v void add(Cell c) { v = v + c.v } } void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2 } Goal: Check assertions statically Challenges: − Whole-code analysis is expensive − Dynamic dispatch (inheritance; open-world assumption)TRANSCRIPT
An Introduction to Automated Program
Verification with Permission Logics
15th May 2015, Systems Group, ETH Zurich
Uri Juhasz, Ioannis Kassios, Peter Müller, Milos Novacek,Malte Schwerhoff, Alex Summers (and several students)
3
Initial Example (Pseudo Java)class Cell { int v
void add(Cell c) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2}
Goal: Check assertions statically
Challenges:−Whole-code analysis is expensive−Dynamic dispatch (inheritance; open-world
assumption)
4
Modularityclass Cell { int v
void add(Cell c) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2}
?
5
Specificationsclass Cell { int v
void add(Cell c) requires c != null ensures v == old(v) + old(c.v) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2}
6
Reasoning with Specificationsclass Cell { int v
void add(Cell c) requires c != null ensures v == old(v) + old(c.v) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2} ?
7
An Incorrect Implementationclass Cell { int v
void add(Cell c) requires c != null ensures v == old(v) + old(c.v) { v = v + c.v c.v = 0 }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2}
8
Strengthening Specificationsclass Cell { int v
void add(Cell c) requires c != null ensures v == old(v) + old(c.v) ensures c.v == old(c.v) { v = v + c.v c.v = 0 }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2}
9
Strengthening Specificationsvoid client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2 c1.add(c2) assert c1.v == 3 assert c2.v == 2}
class Cell { int v
void add(Cell c) requires c != null ensures v == old(v) + old(c.v) ensures c.v == old(c.v) { v = v + c.v }}
?
10
Aliasingclass Cell { int v
void add(Cell c) requires c != null ensures v == old(v) + old(c.v) ensures c.v == old(c.v) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell 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}
11
Reason about Shared State(Including Data Races)
andControl Aliasing
Challenges
13
Modular Static Verification + Shared State
foo(x) bar(x)
14
Modular Static Verification + Shared State
foo(x) bar(x)
?
15
Modular Static Verification + Shared State
foo(x) bar(x)
??
?
16
Permissions
foo(x) bar(x)
17
Permission Transfer
foo(x) bar(x)
?
18
Permission Transfer
foo(x) bar(x)
??
19
Fractional Permissions
foo(x) bar(x)
20
Splitting Fractional Permissions
foo(x) bar(x)
?
21
Merging Fractional Permissions
foo(x) bar(x)
?
22
Silver: Assertion Language Basics
Accessibility predicates denote permissions
Assertions may be heap-dependent
Fractional permissions
Conjunction sums up permissions(similar to ∗ in separation logic)
Write permission is exclusive(similar to ∗ in separation logic)
acc(c.f, ½) && acc(c.f,
½)
acc(c.f)
acc(c.f) && c.f == 0
acc(c.f, ½)
acc(c1.f) && acc(c2.f,ε) ⇒ c1 != c2
23
Demo
24
Permission Transfer Reloaded
Idea of permission transfer generalises−Fork-join (transfer between threads)−Locks (transfer to/from lock invariant)−Message passing (pass permissions)
Common operations−Gain permissions−Lose permissions
foo(x) bar(x)
?
25
Silver: Inhale and Exhale Statements
Statement inhale A means−Gain permissions required by A (e.g. acc(x.f))−Assume logical constraints in A (e.g. x.f != 0)
Statement exhale A means−Assert and remove permissions required by A−Assert logical constraints in A−Havoc locations to which all permissions were
removed(i.e. forget their values)
26
ConcurrencyExamples
27
Fork-Join Concurrency (Pseudo-Java)class Cell { int v
void add(Cell c) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2
Token tk = fork c1.add(c2) // ... join tk
assert c1.v == 3 assert c2.v == 2}
28
Locks and @GuardedBy Annotations (Pseudo-Java)
class SharedPair { @GuardedBy(“this”) int x, y
void inc(int dx, int dy) { synchronized(this) { x = x + dx y = y + dy } }
void swap() { int t = x x = y y = t }}
29
Lock Invariants (Pseudo-Java)class SharedPair { @GuardedBy(“this”, “x < y”) int x, y
void inc(int dx, int dy) { synchronized(this) { assert x < y x = x + dx y = y + dy assert x < y } }}
30
Lock Invariants (Pseudo-Java)class SharedPair { @GuardedBy(“this”, “x < y”) int x, y
void inc(int dx, int dy) { assert dx <= dy synchronized(this) { assert x < y x = x + dx y = y + dy assert x < y } }}
31
Viper: Our Verification Infrastructure
Silver:−Intermediate Verification
Language−Few (but expressive)
constructs−Designed with verification
and inference in mind
Back-ends: Two verifiers;plans to develop inference, slicer
Front-ends (proof of concept):
−Chalice (concurrency research)
−Scala (very small subset)−Java (VerCors, U Twente)−OpenCL (VerCors, U Twente)
Silver(IVL)
Front-endBack-ends
Automaticprover
Front-endFront-endFront-ends
32
Silver AST
Viper: Our Verification Infrastructure
SiliconCarbon
Boogie(Microsoft)
Z3(Microsoft)
verified by
encodes in
queries
queries
generate
Static Analysis
infer additionalspecifications
ChaliceOpenCL
(U Twente)
ScalaJava(U
Twente)
33
Query prover once with full information (Carbon)
Verification Condition Generation vs. Symbolic Execution
Program Verifierread by calculates Provergiven toWPs
one weakest precondition per
methodVCG
Query prover often with limited information (Silicon)
Program Verifier read
bymaintains Symbolic State
σ
symbolically executeevery path through
each method
query prover at every step if next statement is
executable
Proverused by
σ1
σ2
σ3
σ4
σ5
SE
34
Outlook
Information hiding, abstraction and inheritance
Unbounded (recursive) data structures
Obligations – the dual to permissions
Specification inference
Encoding of high-level features−Immutable data (vs. permissions)−Lazy evaluation (vs. permissions)−Closures/higher order functions−Actor-based concurrency−Fine-grained locking, lock-free algorithms
35
Silver AST
www.pm.inf.ethz.ch/research/viper.html
SiliconCarbon
Boogie(Microsoft)
Z3(Microsoft)
verified by
encodes in
queries
queries
generate
Static Analysis
infer additionalspecifications
ChaliceOpenCL
(U Twente)
ScalaJava(U
Twente)
36
You shouldn’t even be here!
37
Fork-Join Concurrency (Pseudo-Java)class Cell { int v
void add(Cell c) { v = v + c.v }}
void client() { Cell c1 = new Cell() c1.v = 1 Cell c2 = new Cell() c2.v = 2
Token tk = fork c1.add(c2) // ... join tk
assert c1.v == 3 assert c2.v == 2}
38
Fork-Join Concurrency (Silver)field v: Int
method add(this: Ref, c: Ref) requires acc(this.v) && acc(c.v, ½) ensures acc(this.v) && acc(c.v, ½) ensures this.v == old(this.v) + old(c.v) { this.v := this.v + c.v}
method client() { // instantiate cells c1, c2; initialise with 1, 2 // Token tk = fork c1.add(c2) exhale acc(c1.v) && acc(c2.v, ½)
// join tk inhale acc(c1.v) && acc(c2.v, ½) inhale c1.v == 1 + 2
assert c1.v == 3 && c2.v == 2}
39
Locks and @GuardedBy Annotations (Pseudo-Java)
class SharedPair { @GuardedBy(“this”) int x, y
void inc(int dx, int dy) { synchronized(this) { x = x = dx y = y = dy } }
void swap() { int t = x x = y y = t }}
40
Locks and @GuardedBy Annotations (Silver)field x: Intfield y: Int
define inv(this) acc(this.x) && acc(this.y)
method inc(this: Ref, dx: Int, dy: Int) { // begin synchronize(this) inhale inv(this)
this.x := this.x + dx this.y := this.y + dy
// end synchronize(this) exhale inv(this)}
method swap(this: Ref) { var t: Int := this.x this.x == this.y this.y == t}
41
Lock Invariants (Pseudo-Java)class SharedPair { @GuardedBy(“this”, “x < y”) int x, y
void inc(int dx, int dy) { synchronized(this) { assert x < y
x = x = dx y = y = dy
assert x < y } }}
42
Lock Invariants (Pseudo-Java)class SharedPair { @GuardedBy(“this”, “x < y”) int x, y
void inc(int dx, int dy) { assert dx <= dy
synchronized(this) { assert x < y
x = x = dx y = y = dy
assert x < y } }}
43
Lock Invariants (Silver)field x: Intfield y: Int
define inv(this) acc(this.x) && acc(this.y) && this.x <= this.y
method inc(this: Ref, dx: Int, dy: Int) requires dx <= dy{ // begin synchronize(this) inhale inv(this)
this.x := this.x + dx this.y := this.y + dy
// end synchronize(this) exhale inv(this)}