370 likes | 460 Views
Verifying Safety Policies with Size Properties and Alias Controls. Wei Ngan Chin 1,2 , Siau-Cheng Khoo 1 , Shengchao Qin 3 , Corneliu Popeea 1 , Huu Hai Nguyen 2 1 National University of Singapore 2 Singapore-MIT Alliance 3 University of Durham. analyseand verify. Background.
E N D
Verifying Safety Policies with Size Properties and Alias Controls Wei Ngan Chin1,2, Siau-Cheng Khoo1, Shengchao Qin3, Corneliu Popeea1, Huu Hai Nguyen2 1 National University of Singapore 2 Singapore-MIT Alliance 3 University of Durham
analyseand verify Background • Uses of Size Analysis : • array bound check elimin. [Xi-Pfenning'98] • data structure invariance [Xi-Pfenning'99] • termination analysis [Lee-Jones'01] • space complexity [Hofman-Jost'03] • Current Status : • mostly for declarative languages (functional + logic) • restricted imperative language (e.g. Xanadu)
Our Goal • Static Verification for Object-Based Programs • Main Challenges : • objects may mutate • objects may be aliased • Our ApproachUse size analysis and alias controls to specify and verify safety policies
value True --> b=1 value False --> b=0 value 3 --> n=3 Type System for Size Analysis • Uses annotated types ::= c<s1,…,sm> • Types are annotated with size properties that capture: Values : bool<b>, int<n> Lengths : Array<s>, List<n>, Tree<s,h>
Methods with Size Annotation mn (1 v1, … , n vn) where pre ; post{ body } • Examples int<r>add (int<a> x, int<b>y) where true ; (r=a+b) { x+y } int<r> sub (Array<s> A, int<i> i) where (0is) ; true { A[i] }
def - size definition element value left sub-tree right sub-tree inv - AVL Tree is height-balanced AVL’s invariant is preserved after node insertion Object with Size Invariant • AVL Tree: s – number of nodes in tree h – height of tree adt AVL<s,h> where s=1+s1+s2Æ h=1+max(h1,h2) ; s¸0 Æ h¸0 Æ -1·h1-h2·1 { int<v> val ; AVL<s1,h1> left ; AVL<s2,h2> right; … } void insert (AVL<s,h> t, int<n> n) where true ; s’=s+1 Æ h·h’·h+1 { ... }
tail of the list Mutability & Aliasing • Problem with aliasing and mutability : List<x> a = new List(5,new List(6,null)); // x’=2 List<y> b = a; // y’=x Æ x’=x setNext(b,null); // y’=1 Æ x’=x Unsound conclusion: x’=2 Æ y’=1 adt List<n> where n=m+1 ; n0 { int<v> val ; List<m> next; void setNext (List<n> x, List<l> y) where n>0 ; n’=l+1 { x.next = y } …}
Alias Controls Adopted annotations : Immutability + Uniqueness Each reference (field/param/local var) is marked: • Read-Only (R) : always refers to the same object. • Unique (U) : sole reference to an object. • Shared (S) : maybe globally aliased. • Lent-Once (L) : unique parameter temporarily lent. Goal: precisely and soundly capture size-properties.
List<a>@S x; List<b>@S y; x=y; y.val=4; y.next=x; freely shared and trackable Size Property for List (1) List with Read-Only (R) tail. adt List<n> where n=m+1 ; n¸0 { int<v>@S val ; List<m>@R next ; : } read-only
MList<a>@U x; MList<b>@U y; x=y; x.next=.. …y… y loses its uniqueness Size Property for List (2) List with Unique (U) tail. adt MList<n> where n=m+1 ; n¸0 { int<v>@S val ; MList<m>@U next ; : } mutable but unique
lent & unique Lending Annotation Properties of a Lent-once reference : • value does not escape the method • has exclusive/unique access to the object void append (MList<m>@L xs, MList<n>@U ys) where m>0 ; m'=m+n { if xs.next==null then xs.next=ys else append(xs.next,ys) }
MList<a>@U x; MList<b>@U y; append(x,y); …x.next… …y.next… uniqueness of x is lent uniqueness of y is consumed Lending Annotation void append (MList<m>@L xs, MList<n>@U ys) where m>0 ; m'=m+n { … }
Classification of Size-Variables Three possible groups Vobj(hs*i) = (SI,ST,SN) • Size-Immutable (freely shared) (ii) Trackable (mutable and unique) (iii) Non-Trackable (mutable and globally aliased)
Outline • Background on Size Analysis • Size Tracking with Alias Controls • Kernel Language and Protocol Specification • Type System for Verification • Implementation and Conclusion.
source program pre/post states define size size invariant Presburger size constraint annotated types expression oriented language Kernel Language
How are Safety Policies Specified? • Popular approach - finite state machine. • Our approach : ADT with (i) Object’s Size Invariant. (ii) Methods’ Preconditions. • Benefits: Relational Properties Infinite-State Policies
File Protocol Safety policy : Read/Write after Successful Open. read new close open 1 2 3 open File state 1 - uninitialized 2 - opened 3 - closed write
successful file open must be opened closed state File Protocol • Specified using sized typing.
n,c 2,c 1,c 0,c Bounded Buffer Protocol Safety policy : Buffer does not Under/Overflow. s<c ; s’=s+1 Æ c’=c add n>0 ; s’=0 Æ c’=n s,c new get Buffer state s - no of elements c - capacity s>0 ; s’=s-1 Æ c’=c
Outline • Background on Size Analysis • Size Tracking with Alias Controls • Kernel Language and Protocol Specification • Type System for Verification • Implementation and Conclusion.
expression to type-check pre/post states type environment Type System for Verification Type judgement
size of b corresponds to what branch is taken type of v path-sensitivity for size information using disjunction Rule for IF: path-sensitivity
substitution from formal to actual parameters types for actual parameters method declaration precondition checked poststate effect Rule for Call
Correctness of Type System • Type Preservation – size type property is correctly preserved during reduction. • Progress – a well-typed program never goes wrong. Safety policies are guaranteed for well-typed programs.
Implementation • Prototype built using • Haskell language (GHC) • Omega Presburger solver • Accepts a Java-like language (without concurrency and exceptions). • Is this method viable? • Verification is fast because of modular type-checking. • Annotation is less than 5% of source code.
Related Work Size analysis for immutable data structures [Hughes et.al'96, Xi-Pfenning'98,'99, Jost-Hofman'03] Alias controls for program reasoning [Chan-Boyland'98, Aldrich-Kostadinov-Chambers'02] Other approaches to verification: • Finite type-state: Vault, Fugue [Fahndrich-DeLine'02,'04] • Theorem proving: ESC (may be unsound) [Flanagan-Leino-Lillibridge-Nelson et.al'02] • Model checking: Bogor (requires test harness) [Robby-Dwyer-Hatcliff-Rodriguez'03,'04]
Conclusion • Formulate a precise relational size analysis for object-based programs. • Use alias controls to track mutable size properties. • Automatic verification for: Safety policies - files, bounded-buffers. Data invariants - lists, AVL trees. • Working towards inference of alias and size annotations (for methods).
Experiments JOlden benchmarks
fields can only be accessed via methods size definition Object Declaration adt Cell<n> where n=v ; true { int<v> val ; void incr(Cell<n> x) where true ; n’=n+1 {x.val =x.val + 1} …} Development: a client is based on ADT’s interface (the implementation details are hidden). Modular analysis: correct usage of ADT verified against ADT’s interface. Why use ADTs ?
new value old value Mutable Size Properties • Example with aliasing and mutability : Cell<x> a = new Cell(5); // x’=5 Cell<y> b = a; // y’=x Æ x’=x incr(b); // y’=y+1 Æ x’=x // x’=5 Æ y’=6 unsound! adt Cell<n> where n=v ; true { int<v> val ; void incr(Cell<n> x) where true ; n’=n+1 {x.val =x.val + 1} …}
where true ; p1’=xÆp2’=p2 size definition r@U (,{r1,r2},) Pair ({p2},{p1},) fst@S snd@R ({s2},,) (,{s1},) int int ({s1},,) ({s2},,) Pair Example adt Pair<p1,p2> where p1=s1Æp2=s2 ; true { int<s1>@S fst; int<s2>@R snd; void setFst(Pair<p1,p2>@L p, int<x>@S x) { p.fst=x } } Pair<r1,r2>@U r = new Pair(…); r.setFst(…);
where true ; p2’=p2 m@S n@S (,{n2},{n1}) (,{m2},{m1}) Pair Example adt Pair<p1,p2> where p1=s1Æp2=s2 ; true { int<s1>@S fst; int<s2>@R snd; void setFst(Pair<p1,p2>@ p, int<x>@S x) { p.fst=x } } Pair<m1,m2>@S m = new Pair(…); Pair<n1,n2>@S n = m; m.setFst(…); n.setFst(…); S Pair ({p2},{p1},) fst@S snd@R ({s2},,) (,{s1},) int int ({s1},,) ({s2},,)
no bounds violation size never change Array Protocol Safety policy : No Array Bounds Violation. • Implementation: array primitive operations (that need no runtime tests). sub(A,i) … A[i] update(A,i,v) … A[i] = v
safety preconditions Buffer Protocol Safety policy : Buffer does not Under/Overflow. • Implemented using a cyclic array. • Implementation checked to comply with Array protocol.
Lock Protocol Safety policy : No double lock/unlock operations.
AVL Tree adt AVL<s,h> where s=1+s1+s2Æ h=1+max(h1,h2) ; s¸0 Æ h¸0 Æ -1·h1-h2·1 { int<v>@S val ; AVL<s1,h1>@U left ; AVL<s2,h2>@U right; void insert (AVL<ts,th>@L t, int<n>@S n) where true ; ts’=ts+1 Æ th·th’·th+1 { ... } }