VS3: Verification and Synthesis using SMT Solvers SMT Solvers for Program Verification Saurabh Srivastava * Sumit Gulwani ** Jeffrey S. Foster * * University of Maryland, College Park ** Microsoft Research, Redmond What VS3 will let you do! A. Discover invariants with arbitrary quantification and boolean structure – ∀: E.g. Sortedness ∀k1,k2 k1 k2 .. – ∀∃: E.g. Permutation k ∀k∃j .... j Aold Anew Selection Sort: for i = 0…n { for j = i…n { find min index } if (min ≠ i) swap A[min], A[i] } What VS3 will let you do! A. Discover invariants with arbitrary quantification and boolean structure – ∀: E.g. Sortedness ∀k1,k2 k1 k2 .. j:=i k ∀k∃j .... i:=0 i<n – ∀∃: E.g. Permutation j Selection Sort: Output array Aold Anew j<n Find min index if (min != i) swap A[i], A[min] Verification: Proving Programs Correct true Selection Sort: Input state i:=0 Iouter i<n j:=i Output state Sortedness Permutation Output array Iinner j<n Find min index if (min != i) swap A[i], A[min] The difficult task is program state (invariant) inference: Iinner, Iouter, Input state, Output state Verification: Proving Programs Correct true Selection Sort: Input state ∀k1,k2 : 0≤k1<k2<n ∧ k1<i => A[k1] ≤A[k2] i:=0 i<j i<n j:=i Output state Sortedness Permutation Output array ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] i ≤ min < n ∀k1,k2 : 0≤k1<k2<n ∧ k1<i => A[k1] ≤A[k2] ∀k2 : 0≤k2∧i≤k2<j => A[min] ≤A[k2] j<n Find min index if (min != i) swap A[i], A[min] The difficult task is program state (invariant) inference: Iinner, Iouter, Input state, Output state Verification: Proving Programs Correct true Selection Sort: Input state (---1-------------) => A[k A[k111]] ≤A[k ≤A[k222]] ∀k11,k22 : 0≤k 1<k22<n ∧ k11<i => i:=0 (------------------i<j i ≤ min < n ) 0≤k1<k2<n ∧ k1<i => => A[k A[k11]] ≤A[k ≤A[k22]] ∀k1,k2 : (---------------) i<n j:=i Output state Sortedness Permutation Output array ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ∀k2 : 0≤k (-----------) 2∧i≤k2<j => A[min] ≤A[k2] j<n Find min index if (min != i) swap A[i], A[min] The difficult task is program state (invariant) inference: Iinner, Iouter, Input state, Output state Verification: Proving Programs Correct true Selection Sort: Input state ∀k2 : (-----------) => A[min] ≤A[k2] i:=0 (------------------) ∀k1,k2 : (---------------) => A[k1] ≤A[k2] i<n j:=i Output state Sortedness Permutation Output array ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] (------------------) ∀k1,k2 : (----------------) => A[k1] ≤A[k2] ∀k2 : (-----------) => A[min] ≤A[k2] j<n Find min index if (min != i) swap A[i], A[min] The difficult task is program state (invariant) inference: Iinner, Iouter, Input state, Output state Verification: Proving Programs Correct Bubble Sort: (------------------) ∀k1,k2 : (----------------) => A[k1] ≤A[k2] ∀k1,k2 : (----------) => A[k1] ≤A[k2] i:=n-1 i>0 j:=0 Output array ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] j<i (------------------) ∀k1,k2 : (---------------) => A[k1] ≤A[k2] ∀k1,k2 : (----------) => A[k1] ≤A[k2] if (a[j] > a[j+1]) swap A[j], A[j+1] User Input:Templates and Predicates • Templates k1,k2 : () () Unknown holes k1k2 : () () – Intuitive and simple • Depending on the property being proved; form straight-forward • Limited to the quantification and disjunction • Predicate Abstraction – Enumerate predicates of the form Program variables, array elements – E.g., {i<j, i>j, i≤j, i≥j… } x opr y Relational operator <, ≤, >, ≥ … Tool architecture Microsoft’s Phoenix Compiler C Program Cut-Set VS3 Verification Conditions CFG Templates for invariants Predicate Sets Iterative Fixed-point GFP/LFP Candidate Solutions Constraintbased Fixed-Point SMT Solver Boolean Constraint SAT Solver Preconditions Postconditions Invariants Fixed-point Computation • Constraint-based (VMCAI’09) – Separately encode each VC as SAT constraint • Local constraints SAT clauses – Use SAT solver to do fixed-point computation – Compare against trivial approach: 1.6e14 minutes • Iterative (PLDI’09) – Facts do not form a lattice, but power-set does – We ensure that if there exists an invariant we find it – Intelligent lattice search: SMT solver for tx-functions Weakest Preconditions Weakest conditions on input? k1 k2 < i:=0 i<n j:=i Output array Worst case behavior: swap every time it can j<n Find min index if (min != i) swap A[i], A[min] Example analyses • Tool can verify: – Sorting algorithms: • Selection, Insertion, Bubble, Quick, Merge Sort – Properties • Output is Sorted • Output contains all and only elements from the input • Tool can infer preconditions: – Worst case input (precondition) for sorting: • Reverse sorted array, all but Selection Sort • Selection Sort: sorted array except last elem is smallest – Inputs for functional correctness: • Binary search requires sorted array • Merge in merge sort expect sorted inputs • Missing initializers Demo: Selection Sort true Selection Sort: Input state ∀k1,k2 : 0≤k1<k2<n ∧ k1<i => A[k1] ≤A[k2] i:=0 i<j i<n j:=i Output state Sortedness Permutation Output array ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] i ≤ min < n ∀k1,k2 : 0≤k1<k2<n ∧ k1<i => A[k1] ≤A[k2] ∀k2 : 0≤k2∧i≤k2<j => A[min] ≤A[k2] j<n Find min index if (min != i) swap A[i], A[min] The difficult task is program state (invariant) inference: Iinner, Iouter, Input state, Output state Demo: Program Demo: Output Conclusions • VS3: Verification tool over predicate abstraction • Verification – Can infer quantified invariants • Maximally-weak preconditions • Builds on SMT Solvers, so exploits their power • Project Webpage http://www.cs.umd.edu/~saurabhs/pacs Future work Recent extension: Synthesis • Verification tool for quantified invariants – Reasoning about full functional specifications possible • What if we had missing program fragments? – Still possible to verify if we allow the tool to plug-in equality predicates over program variables – Equality predicates translated to statements • We can synthesize – Strassen’s Matrix Multiplication! – Sorting algorithms! Constraint-based over Predicate Abstraction pre vc(pre,I1) I1 vc(I1,post) vc(I1,I2) I2 post vc(I2,I2) vc(I2,I1) Constraint-based over Predicate Abstraction pred(I1) vc(pre,I1) vc(I1,post ) vc(I1,I2) b11,b21…br1 p1,p2…pr vc(I2,I1) b12,b22…br2 boolean indicators p1,p2…pr predicates unknown 2 unknown 1 k : () () vc(I2,I2) VCs are FOL formulae over unknowns I1, I2 If we find assignments bji = T/F Then we are done! I1 template Constraint-based over Predicate Abstraction pred(A) : A to unknown predicate indicator variables vc(pre,I1) vc(I1,post ) vc(I1,I2) vc(I2,I1) vc(I2,I2) VCs are FOL formulae over unknowns I1, I2 pred(I1) Constraint-based over Predicate Abstraction SAT formulae over predicate indicators Program VC to boolean constraint pred(A) : A to unknown predicate indicator variables vc(pre,I1) boolc(pred(I1)) vc(I1,post ) vc(I1,I2) boolc(pred(I1)) vc(I2,I1) boolc(pred(I2), pred(I1)) vc(I2,I2) boolc(pred(I1), pred(I2)) boolc(pred(I2)) VCs are FOL formulae over unknowns I1, I2 Local reasoning ∧ Invariant soln Boolean constraint to satisfying soln (SAT Solver) Fixed-Point Computation VC to Boolean Constraint ( I1 ∧ i≥n ) => ( sorted array ) i:=0 i<n I1 j:=i Output sorted array j<n I2 Find min index if (min != i) swap A[i], A[min] VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) i:=0 i<n I1 j:=i Output sorted array j<n I2 Find min index if (min != i) swap A[i], A[min] VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) template Φ: (∀k1,k2 : ??1 => ??2 Predicates k1,k2 : () () positive p1 p2 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) negative ✗ Trivial search: k x 2|Predicates| queries VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) template Φ: (∀k1,k2 : ??1 => ??2 Predicates k1,k2 : () () positive ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) negative Φ[ p1 ] p2 ⊤ Φ[p1 ] contains only negative unknowns Query the SMT solver for the maximally weakest value of negative unknown ??2 There might be multiple maximally weakest N1 N1’ ⊥ N1’’ … VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) template Φ: (∀k1,k2 : ??1 => ??2 Predicates k1,k2 : () () positive ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) negative Φ[ p1 ] N1, N1’, N1’’… Φ[ p2 ] N2, N2’, N2’’… VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) template Φ: (∀k1,k2 : ??1 => ??2 Predicates k1,k2 : () () positive ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) negative p1 N1, N1’, N1’’… p2 N2, N2’, N2’’… bp1 => bN1 ∨ bN1’ ∨ bN1’’ ∨… VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) template Φ: (∀k1,k2 : ??1 => ??2 Predicates k1,k2 : () () positive ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) negative p1 N1, N1’, N1’’… bp1 => bN1 ∨ bN1’ ∨ bN1’’ ∨… p2 N2, N2’, N2’’… bp2 => bN2 ∨ bN2’ ∨ bN2’’ ∨… VC to Boolean Constraint ( I1 ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) template Φ: (∀k1,k2 : ??1 => ??2 Predicates k1,k2 : () () positive ∧ i≥n ) => ( ∀k1,k2 : 0≤k1<k2<n => A[k1] ≤A[k2] ) negative p1 N1, N1’, N1’’… bp1 => bN1 ∨ bN1’ ∨ bN1’’ ∨… p2 N2, N2’, N2’’… bp2 => bN2 ∨ bN2’ ∨ bN2’’ ∨… Boolean SAT formula Constraint-based over Predicate Abstraction Program VC to boolean constraint ✓ SAT formulae over predicate indicators pred(A) : A to unknown predicate indicator variables vc(pre,I1) boolc(pred(I1)) vc(I1,post ) vc(I1,I2) boolc(pred(I1)) vc(I2,I1) boolc(pred(I2), pred(I1)) vc(I2,I2) boolc(pred(I1), pred(I2)) boolc(pred(I2)) VCs are FOL formulae over unknowns I1, I2 Local reasoning ∧ Invariant soln Boolean constraint to satisfying soln (SAT Solver) Fixed-Point Computation Engineering: Interface to SMT Solvers Explicit skolemization functions Solvers are not very good at handling ∀x∃y:f(x,y) queries • In program verification such queries have specific forms • Easy to find explicit skolemization functions: skl • Convert ∀x∃y:f(x,y) ∀x:f(x,skl(x)) • Tool SMT query SMT Solver Axiomatic support, e.g. reachability for lists Engineering: Interface to SMT Solvers Explicit skolemization functions Lift inductive facts Tool SMT query SMT Solver Axiomatic support, e.g. reachability for lists • • • • Induction facts arise in program verification E.g. ∀x : x>0 => f(x)=>f(x+1) SMT solvers can’t handle Lift to induction result: ∀x : x>0 => f(1)=>f(x) Engineering: Interface to SMT Solvers Explicit skolemization functions Lift inductive facts Tool SMT query SMT Solver Domain specific patterns • • • Axiomatic support, e.g. reachability for lists • For efficient SMT solving it is advisable to provide patterns for quantified facts E.g. ∀x : x>0 => f(x)<f(x+1) If possible say, pattern set { x>0, f(x)<f(x+1) } Easy to heuristically find relevant patterns for verif. Engineering: Interface to SMT Solvers Explicit skolemization functions Lift inductive facts Tool SMT query SMT Solver Domain specific patterns Axiomatic support, e.g. reachability for lists Runtimes: Sortedness 16 Tool can prove sortedness for all sorting algorithms! 14 12 seconds 10 LFP 8 GFP CFP 6 4 2 0 Selection Sort Insertion Sort Bubble Sort (n2) Bubble Sort (flag) Quick Sort Merge Sort Runtimes: Permutation … 94.42 … no loss/no gain part of permutation too! 40 35 30 seconds 25 LFP 20 GFP CFP 15 10 5 0 ∞ Selection Sort ∞ Insertion Sort Bubble Sort (n2) Bubble Sort (flag) Quick Sort Merge Sort Runtimes (GFP): Inferring worst case inputs for sorting 45 Tool infers worst case inputs for all sorting algorithms! 40 35 seconds 30 25 Nothing to infer as all inputs yield the same behavior 20 15 10 5 0 Selection Sort Insertion Sort Bubble Sort (n2) Bubble Sort (flag) Quick Sort Merge Sort