Exploiting Synchrony and Symmetry in Relational Verification

Relational safety specifications describe multiple runs of the same program or relate the behaviors of multiple programs. Approaches to automatic relational verification often compose the programs and analyze the result for safety, but a naively composed program can lead to difficult verification problems. We propose to exploit relational specifications for simplifying the generated verification subtasks. First, we maximize opportunities for synchronizing code fragments. Second, we compute symmetries in the specifications to reveal and avoid redundant subtasks. We have implemented these enhancements in a prototype for verifying k-safety properties on Java programs. Our evaluation confirms that our approach leads to a consistent performance speedup on a range of benchmarks.


Example: Equivalence Checking
Given programs P 1 , P 2 , that respectively have inputs x1, x2 and outputs y1, y2, prove x1 = x2 y1 = y2. P 1 P 2 Challenge 1: Loops Consider the loops in parallel instead.  Step 1. Check if current set can be executed in lockstep Step 2. Partition according to model (if necessary) Step 3 If you permute indices, you get the same problem.
Need a permutation π of indices that is a symmetry of the formulas (pre-and postconditions) and of the programs Example: Finding Symmetries of a Formula Step 1. Canonicalize Example: Finding Symmetries of a Formula Step 2. Create colored graph from AST Example: Finding Symmetries of a Formula Step 2. Create colored graph from ASTs Example: Finding Symmetries of a Formula Step 2. Create graph from ASTs Example: Finding Symmetries of a Formula Step 2. Create graph from ASTs Example: Finding Symmetries of a Formula Step 2. Create graph from ASTs Example: Finding Symmetries of a Formula Step 2. Create graph from ASTs Example: Finding Symmetries of a Formula Step 2. Create graph from ASTs Example: Finding Symmetries of a Formula Step 3. Find graph automorphisms Summary: Finding Symmetries of a Formula Automatically Step 1. Canonicalize Step 2. Create graph from AST Step 3. Find graph automorphisms 43 How to apply symmetry?

Instantiation of Strategies in Forward Analysis
We now describe an instantiation of our proposed strategies in a verification algorithm based on forward analysis using a strongest-postcondition computation. Other instantiations, e.g., on top of a Horn solver based on Property-Directed Reachability [24] are possible, but outside the scope of this work. Maintain sets of program copies that begin with conditionals (Ifs) and loops (Loops).
We now describe an instantiation of our proposed strategies in a verification algorithm based on forward analysis using a strongest-postcondition computation. Other instantiations, e.g., on top of a Horn solver based on Property-Directed Reachability [24] are possible, but outside the scope of this work.
1: procedure Verify(pre, Current, Ifs, Loops, post) 2: while Current 6 = ? do 3: if ProcessStatement(pre, P i , Ifs, Loops, post) = safe then return safe 4: if Loops 6 = ? then HandleLoops(pre, Loops, post) 5: else if Ifs 6 = ? then HandleIfs(pre, Ifs, Loops, post) 6: else return unsafe Given an RVP in the form of a Hoare triple {Pre} P 1 || · · · ||P k {Post}, where || denotes parallel composition, the top-level Verify procedure takes as input the relational specification pre = Pre and post = Post, the set of input programs Current = {P 1 , . . . , P k }, and empty sets Loops and Ifs. It uses a strongestpostcondition computation to compute the next Hoare triple at each step until it can conclude the validity of the original Hoare triple.
Synchronization. Throughout verification, the algorithm maintains three disjoint sets of programs: one for programs that are currently being processed (Current), one for programs that have been processed up until a loop (Loops), We now describe an instantiation of our proposed strategies in a verification algorithm based on forward analysis using a strongest-postcondition computation. Other instantiations, e.g., on top of a Horn solver based on Property-Directed Reachability [24] are possible, but outside the scope of this work.
1: procedure Verify(pre, Current, Ifs, Loops, post) 2: while Current 6 = ? do 3: if ProcessStatement(pre, P i , Ifs, Loops, post) = safe then return safe 4: if Loops 6 = ? then HandleLoops(pre, Loops, post) 5: else if Ifs 6 = ? then HandleIfs(pre, Ifs, Loops, post) 6: else return unsafe Given an RVP in the form of a Hoare triple {Pre} P 1 || · · · ||P k {Post}, where || denotes parallel composition, the top-level Verify procedure takes as input the relational specification pre = Pre and post = Post, the set of input programs Current = {P 1 , . . . , P k }, and empty sets Loops and Ifs. It uses a strongestpostcondition computation to compute the next Hoare triple at each step until it can conclude the validity of the original Hoare triple.
Synchronization. Throughout verification, the algorithm maintains three disjoint sets of programs: one for programs that are currently being processed (Current), one for programs that have been processed up until a loop (Loops), We now describe an instantiation of our proposed strategies in a verification algorithm based on forward analysis using a strongest-postcondition computation. Other instantiations, e.g., on top of a Horn solver based on Property-Directed Reachability [24] are possible, but outside the scope of this work. Given an RVP in the form of a Hoare triple {Pre} P 1 || · · · ||P k {Post}, where || denotes parallel composition, the top-level Verify procedure takes as input the relational specification pre = Pre and post = Post, the set of input programs Current = {P 1 , . . . , P k }, and empty sets Loops and Ifs. It uses a strongestpostcondition computation to compute the next Hoare triple at each step until it can conclude the validity of the original Hoare triple.
Synchronization. Throughout verification, the algorithm maintains three disjoint sets of programs: one for programs that are currently being processed (Current), one for programs that have been processed up until a loop (Loops), We now describe an instantiation of our proposed strategies in a verification algorithm based on forward analysis using a strongest-postcondition computation. Other instantiations, e.g., on top of a Horn solver based on Property-Directed Reachability [24] are possible, but outside the scope of this work.
1: procedure Verify(pre, Current, Ifs, Loops, post) 2: while Current 6 = ? do 3: if ProcessStatement(pre, P i , Ifs, Loops, post) = safe then return safe 4: if Loops 6 = ? then HandleLoops(pre, Loops, post) 5: else if Ifs 6 = ? then HandleIfs(pre, Ifs, Loops, post) 6: else return unsafe Given an RVP in the form of a Hoare triple {Pre} P 1 || · · · ||P k {Post}, where || denotes parallel composition, the top-level Verify procedure takes as input the relational specification pre = Pre and post = Post, the set of input programs Current = {P 1 , . . . , P k }, and empty sets Loops and Ifs. It uses a strongestpostcondition computation to compute the next Hoare triple at each step until it can conclude the validity of the original Hoare triple.
Synchronization. Throughout verification, the algorithm maintains three disjoint sets of programs: one for programs that are currently being processed (Current), one for programs that have been processed up until a loop (Loops), P 1,2 P 1,3 P 1,4 P 2,2 P 2,3 P 2,4 Current Ifs Loops P 3,2 P 3,3 P 3,4 We now describe an instantiation of our proposed strategies in a verification algorithm based on forward analysis using a strongest-postcondition computation. Other instantiations, e.g., on top of a Horn solver based on Property-Directed Reachability [24] are possible, but outside the scope of this work.
1: procedure Verify(pre, Current, Ifs, Loops, post) 2: while Current 6 = ? do 3: if ProcessStatement(pre, P i , Ifs, Loops, post) = safe then return safe 4: if Loops 6 = ? then HandleLoops(pre, Loops, post) 5: else if Ifs 6 = ? then HandleIfs(pre, Ifs, Loops, post) 6: else return unsafe Given an RVP in the form of a Hoare triple {Pre} P 1 || · · · ||P k {Post}, where || denotes parallel composition, the top-level Verify procedure takes as input the relational specification pre = Pre and post = Post, the set of input programs Current = {P 1 , . . . , P k }, and empty sets Loops and Ifs. It uses a strongestpostcondition computation to compute the next Hoare triple at each step until it can conclude the validity of the original Hoare triple.
Synchronization. Throughout verification, the algorithm maintains three disjoint sets of programs: one for programs that are currently being processed (Current), one for programs that have been processed up until a loop (Loops), We have seen approaches to addressing the following two challenges in relational verification: