580 likes | 736 Views
Dependable Software via Automated Verification. Huu Hai Nguyen (NUS) Cristina David (NUS) Shengchao Qin (Durham, UK) Wei-Ngan Chin (NUS) . Goal. Verify shapely and mutable data structures with invariants involving size properties. Challenges.
E N D
Dependable Software via Automated Verification Huu Hai Nguyen (NUS) Cristina David (NUS) Shengchao Qin (Durham, UK) Wei-Ngan Chin (NUS)
Goal Verify shapely and mutable data structures with invariants involving size properties
Challenges • Strong updates in the presence of aliasing • Entailment checking with recursive predicates • Emphasis : practical verification
Separation Logic • Foundations • O’Hearn and Pym, “The Logic of Bunched Implications”, Bulletin of Symbolic Logic 1999 • Reynolds, “Separation Logic: A Logic for Shared Mutable Data Structures”, LICS 2002 • Extension to Hoare logic to reason about shared mutable data structures. • : spatial conjunction -- : spatial implication
x 3,y x 3 x y 3 3 x 3,y y 3,x x y x 3 y x 3,y y 3,x Examples (Reynolds LICS 2002) y
Outline • Background • Our Approach • How to Verify? • Entailment • Approximation • Expressiveness • Multiple Pre/Post • Set of States • Coercion Rules
Our Work • Size properties • Data structure with derived size properties and invariant. • Length, height-balanced, sortedness etc. • User-defined inductive predicates • predicates are custom designed • Sound entailment checking (but incomplete)
Overview Shape Predicate Coercion Rule Code Pre/Post entailment prover code verifier
Example Predicates derived attribute (c.f. model field) Singly-linked list self null lln self=null n=0 self::node_,r r::lln-1 inv n0 user-supplied invariant Non-empty sorted list sortln,min,max self::nodemin,null min=max Æ n=1 self::nodemin,q q::sortln-1,k,max mink inv n1 Æ min·max
Example Predicates self p List Segment lsegn,p self=p n=0 self::node_,r r::lsegn-1,p inv n0 Non-empty Circular list clistn self::node_,r r::lsegn-1,self inv n1 self r
Example Predicates AVL Tree (near-balanced tree) avlh self = null Æ h = 0 Ç self::nodeh,h, p, qi p::avlhh1i q::avlhh2i Æ-1 · h1-h2 · 1Æ h = max(h1,h2) + 1 inv h¸0
What Can Be Written? • Heap part • Describes shapes using separation logic • Pure part • Size properties (arithmetic constraints) • Pointer constraint • self points to the “root” of data structure • A “root” pointer is a pointer from which every node is reachable.
Ensuring Automation & Termination • Well-formed • A predicate captures a set of nodes reachable from self. • Applied to predicate defns + specifications • Well-founded • self bound to a data node, not predicate • At most one data node for each conjunct in a predicate • Applied to predicate defns
Outline • Background • Our Approach • How to Verify? • Entailment • Approximation • Expressiveness • Multiple Pre/Post • Set of States • Coercion Rules
Verification • Methods and loops are annotated with pre- and post-conditions. • Entailment checks • Precondition at call site • Postcondition at end of method
Insert into a Sorted List node insert(node x, node vn) requires x::sortln, sm,lgvn::nodev,_ensures res::sortln+1,min(v,sm),max(v,lg) {if (vn.val≤x.val) { vn.next = x; return vn; } else if (x.next=null) then { x.next = vn; vn.next = null; return x; } else {x.next = insert(x.next, vn); return x; } }
{ x’::sortl<n,mi.mx> vn’::node<v,_> } if (vn.val <= x.val) { {(x’::node<mi,null> n=1 Æ mi=mx x’::node<mi,q> q::sortl<n-1,k,mx> mik n2) vn’::node<v, _>vmi } vn.next = x; {(x’::node<mi,null> n=1 mi=mx x’::node<mi,q> q::sortl<n-1,k,mx> mik n2) vn’::node<v,x’> vmi } return vn; {(x’::node<mi,null> n=1 mi=mx x’::node<mi,q> q::sortl<n-1,k,mx> mik n2) vn’::node<v,x’> vmi Æres=vn’ } } { res::sortl<n+1,min(v,mi),max(v,mx)> }
Outline • Background • Our Approach • How to Verify? • Entailment • Approximation • Expressiveness • Multiple Pre/Post • Set of States • Coercion Rules
Entailment 1`2 3 • 1 “subsumes” all heap nodes “present” in 2. • Remaining nodes are kept in 3. • ALGO : Cover all nodes in 2 that are subsumed by 1, then convert to an arithmetic implication check. • A smart “frame inferring” prover.
Key Steps of Entailment • Matching • Aliased data nodes/predicates are matched and their components/arguments unified • Unfolding • Replaces a predicate on LHS by its definition to match a node on the RHS • Folding • Triggered by a predicate on the RHS and a data node on the LHS. • Recursive invocation.
free var defn moved to current state in LHS Matching x::llhniÆ n>1 `9 m ¢x::llhmiÆ m>0 matching n>1 ` n>0 x::llhniÆ n>1 ` x::llhmiÆ m>0 matching n=m Æ n>1 ` n>0
Preserving Free Variables Specification void insert(node x, int v) requires x::llhniÆ n>0 ensuresx::llhn+1i Call x = new node(0, null); insert(x, 1); free variable linking pre and post conditions Preconditioncheck x’::nodeh0,nulli` x’::llhniÆ n>0 n=1 ` n>0 Programstateafter addingpostcondition x’::llhn+1iÆ n=1
Unfolding x::llhniÆ n>1 ` 9r, m ¢ x::nodeh_,ri r::llhmiÆ m>0 Unfolding 9q ¢ x::nodeh_, qi q::llhn-1iÆ n>1 ` 9r, m ¢ x::nodeh_, ri r::llhmiÆ m>0 Matching q1::llhn-1iÆ n>1 ` 9m ¢ q1::ll<m> Æ m>0
Folding: Base Case y=null ` y::llhmi Æ m=0 Recursive entailment y=null ` y=null Æm=0 Ç y::nodeh_,ri r::llhm-1i Back y=null Æm=0` m=0
Folding: Recursive Case x::nodeh_, riÆ r=null ` x::llhniÆ n>0 Recursive entailment x::nodeh_, riÆ r=null ` 9q,k ¢ x::nodeh_,qi q::llhkiÆ k=n-1 Ç x=null Æ n=0 r=null `9k ¢ r::llhkiÆk=n-1 Back r=null Æn-1=0` n>0
Outline • Background • Our Approach • Why Verification? • Entailment • Approximation • Expressiveness • Multiple Pre/Post • Set of States • Coercion Rules
Approximation • Each predicate is approximated by a pure constraint. • When the consequent’s heap is empty, the antecedent is approximated by a pure constraint. • Entailment is reduced to entailment of pure constraints.
Approximation: Examples • XPure(x::nodeh i y::nodeh i) = ex i. x=i Æ i>0 ex j. x=j Æ j>0 = i,j. (x=i Æ i>0 Æ y=j Æ j>0 Æ ij) • XPure0(x::llhni) = n ¸ 0 (too weak) • XPure1(x::llhni) = i. (x=0 Æ n=0 Ç x=i Æ i>0 Æ n>0)
Outline • Background • Our Approach • How to Verify? • Entailment • Approximation • Expressiveness • Multiple Pre/Post • Set of States • Coercion Rules
Multiple Pre/Post • Each method may have multiple pre/post conditions. node append (node x, node y) requires x::llny::llm ensures res::lln+m Ærequires x::sortln,a1,a2y::sortlm,b1,b2 & a2 · b1 ensures res::sortln+m,a1,b2 {if x=null then { return y} else { x.next = append(x.next,y); return x; } }
Multiple Pre/Post • More pre/post for append possible! node append (node x, node y) requires x::llnÆx=y Æ n>0 ensures res::clistn Ærequires x::sortln,a1,a2Æ y=null ensures res::sortln,a1,a2 … requires x::llnÆxy ensures res::lsegn,y
Set of States 1`2 {3,.., n} • {3,.., n} denotes non-deterministic outcome from proof search. • { } means entailment has failed. • Modified Floyd-Hoare style forward reasoning : {}code {1,..,n}
Related Predicates • Some predicates may be related. lln self=null n=0 self::node_,r r::lln-1 inv n0 sortln,min,max self::nodemin,null min=max Æ n=1 self::nodemin,q q::sortln-1,k,max mink inv n1 Æ min·max • Every sorted list is also an unsorted list. sortln,min,max ) self::lln This coercion is used in bubble sorting.
Coercion Rules Allowed Implication c1v1* )9 v*¢ self::c2v2* Æ Reverse-Implication c1v1* (9 v*¢ self::c2v2* Æ Equivalence c1v1* ,9 v*¢ self::c2v2* Æ
Equivalence Coercion Definition of list segment is inadequate basic definition lsegn,p self=p n=0 self::node_,r r::lsegn-1,p inv n0 Important to have equivalence coercion : extra property Termination ensured by well-formed and well-founded property
match … ` [n/m,p/r] … fold lsegm,r unfold lsegn,p x::lsegi,q q::lsegj,p Æ n=i+j … ` x::lsegm,r … x::lsegn,p … `x::lsegi,q q::lsegj,r Æ m=i+j Proof Search via Equiv. Coercion x::lsegn,p … ` x::lsegm,r …
Conclusion • User-defined data structures with size-based invariants • Sound and terminating entailment checking • Expressive verification with proof search and coercion rules. • Future work: inference + debugging + extensions.
Termination • Each step reduces consequent or antecedent. • No infinite unfolding • self must point to a data node • Consequent is reduced with after each unfold • No infinite folding • Antecedent is reduced with each folding.
Verification of Shared Mutable Data Structures • Hoare and He, “A Trace Model for Pointers and Objects”, ECOOP 1999 • The complexity of pointer swing • “perhaps a crippling disadvantage” • Bornat, “Proving Pointer Programs in Hoare Logic”, MPC 2000 • Aliasing • Inductive formulae • Complexity of proof
Example: how to compare these two? • x::ll<1> |- x::ll<m> & m>0 • Precondition • m must be a fresh variable • x::ll<1> |- ex m. x::ll<m> & m>0
Folding • Summarize a heap configuration to a predicate • May result in multiple instances of the predicate • All resulted possibilities are explored
Example • x::ll<n> & n>1 |- ex r. x::node<_,r> & r!=null