Regression-Verification for C code

Regression Verification:
Proving the equivalence of similar programs
Benny Godlin
Ofer Strichman
Technion, Haifa, Israel
(This presentation is a subset of the invited cav’09 talk: ie.technion.ac.il/~ofers/presentations/rv1.ppt)
1
Functional Verification

The main pillar of the grand challenge [H’03].

Suppose we ignore completeness.

Still, there are two major problems:


Specification
Complexity
2
A more modest challenge: Regression Verification

Develop a method for formally verifying the equivalence of two
similar programs.

Pros:


Default specification = earlier version.
Computationally easier than functional verification.


Ideally, the complexity should depend on the semantic
difference between the programs, and not on their size.
Cons:

Defines a weaker notion of correctness.
3
Our notion of equivalence
Partial equivalence


Executions of P1 and P2 on equal inputs

…which terminate,

result in equal outputs.
Undecidable
5
Partial equivalence

Consider the call graphs:


A
B
Side 1
Side 2
… where A,B have:
 same prototype
 no loops
Prove partial equivalence of A, B

How shall we handle the recursion ?
6
Proving partial equivalence
//in[A]
A( . . . )
{
. . .
//in[call A]
call A(. . .);
//out[call A]
. . .
}
//out[A]
A
//in[B]
B( . . . )
{
. . .
// in[call B]
call B(. . .);
//out[call B]
. . .
}
//out[B]
B
7
Rule 1: Proving partial equivalence


Q: How can a verification condition for the premise look like?
A: Replace the recursive calls with calls to functions that



over-approximate A, B, and
are partially equivalent by construction
Natural candidates: Uninterpreted Functions
8
Proving partial equivalence

Let AUF , BUF be A,B, after replacing the recursive call with a
call to (the same) uninterpreted function.

We can now rewrite the rule:
The premise is
decidable
9
Using (PART-EQ-1): example
unsigned gcd1UF
(unsigned a, unsigned b)
b)
{ unsigned g;
if (b == 0)
g = a;
else {
a = a % b;
g = gcd1(b,
a);
U
}
return g;
}
?
=
unsigned gcd2UF
(unsigned x, unsigned y)
{ unsigned z;
z = x;
if (y > 0)
z = gcd2(y,
z % y);
U
}
return z;
z;
}
Transition functions
Tgcd1
Tgcd2
Inputs
a,b
g
x,y
z
Outputs
10
Rule 1: example
Transition functions
Tgcd1
Tgcd2
Inputs
a,b
x,y
Outputs
g
z
Equal
inputs
Equal
outputs
11
Partial equivalence: Generalization

Assume:



no loops;
1-1 mapping map between the recursive functions of both sides
 Mapped functions have the same prototype
Define:

For a function f, UF(f) is an uninterpreted function such that
 f and UF(f) have the same prototype

(f,g) 2 map , UF(f) = UF(g).
12
Partial equivalence: Generalization

Definition:
is called in A]
13
Partial equivalence: Example (1 / 3)
{(g,g’),(f,f’)} 2 map
g
g’
f
f’
Side 2
Side 1
Need to prove:
UF
f
=
UF
f’
g
UF
=
g’
UF
14
Partial equivalence: Example (2 / 3)
UF
g
f
Side 1

UF
g’
f’
Side 2
An improvement:


Find a map that intersects all cycles, e.g., (g,g’)
Only when calling functions in this map replace with
uninterpreted functions
15
Partial equivalence: Example (3 / 3)
g
f
h
UF
g’
f’
h’
UF
Side 1
Side 2
Connected SCCs…

Prove bottom-up

Abstract partially-equivalent functions

Inline
16
RVT: Decomposition algorithm
Legend:
Equivalent pair
Equivalence undecided yet
Could not prove equivalent
Syntactically equivalent pair
check
A:
check
Unpaired function
B:
f1()
f2()
U
f1’()
f2’()
f5()
U
f5’()
f7’()
U f3()
U f4()
f6()
U f3’()
U f4’()
17
RVT: Decomposition algorithm (with SCCs)
Legend:
Equivalent pair
Equivalence undecided yet
Could not prove equivalent
Syntactically equivalent pair
Equivalent if MSCC
A:
check
B:
f1()
f2() U
U f3()
f1’()
f2’()
U
U f5()
U f4()
f6()
U
U f3’()
U f5’()
U f4’()
f6’()
18
The Regression Verification Tool (RVT)

Given two C programs:
 loops  recursive functions.


Map functions, globals, etc.
After that:


Decompose to the granularity of pairs of functions
Use a C verification engine (CBMC) to discharge
19
The Regression Verification Tool (RVT)

CBMC: a C bounded model checker by Daniel Kroening

Our use:




No loops or recursion to unroll...
Use “assume(…)” construct to enforce equal inputs.
Use assert() to demand equal outputs.
Uninterpreted functions are implemented as C functions:

Return consistent nondeterminisitic values.
20
The Regression Verification Tool (RVT)

The premise of (PART-EQ) requires comparing arguments.

What if these arguments are pointers ?

What our system does:


Dynamic structures: creates an unrolled nondeterministic
structure
Arrays: attempts to find references to cells in the array.
21
RVT: User-defined equivalence specification

The user can define pairs of ‘checkpoints’:
side 1: <label1, cond1, exp1>
side 2: <label2, cond2, exp2>

In each side:


update an array with the value of exp each time it reaches label and
condition holds.
Assert that when executed on the same input…,

… these arrays are equivalent.
P1:
exp1
=
=
P2:
exp’1
exp’2
...
exp2
=
=
...
22
RVT
Version A
 result
 counterexample
feedback
Version B
RVT
C program
CBMC
 rename identical globals
 enforce equality of inputs.
 assert equality of outputs
 add checkpoints
 Supports:
 Decomposition
 Abstraction
 some static analysis
…
23
24
RVT: Experiments
We tested the Regression Verification Tool (RVT) with:

Automatically generated sizable programs with complex
recursive structures and loops.
 up-to thousands of lines of code

Limited-size industrial programs:
 Parts of TCAS - Traffic Alert and Collision Avoidance
System.
 Core of MicroC/OS - real-time kernel for embedded
systems.
 Matlab examples: parts of engine-fuel-injection simulation.
25
Testing RVT on programs: Conclusions

For equivalent programs, partial-equivalence checks were very
fast:


proving equivalence in minutes.
For non-equivalent programs:

RVT attempts to prove partial-equivalence but fails
 then RVT tries to prove k-equivalence
26
Summary


Regression verification is an important problem

A solution to this problem has a better chance to succeed in the
industry than functional verification

A grand challenge by its own right…
Lots of future research...
27
More Challenges

Q1: How can we generalize counterexamples ?

Q2: What is the ideal gap between two versions of the same
program, that makes Regression Verification most effective ?

Q3: How can functional verification and equivalence
verification benefit from each other ?
28
The end…

Thank you
29