Solving Constrained Horn Clauses Using shara
Verifying that a given program satisfies a given safety property (i.e., a property that specifies executions that should not happen) can be reduced to solving a class of logic-programming problems called Constrained Horn Clauses (CHCs). CHCs can express safety-verification problems of imperative programs, recursive programs, some concurrent programs, and functional programs.
shara
is a CHC solver. It operates purely on CHC systems, and does
not require them to correspond to programs in particular languages, or
particular safety properties.
Determining satisfiability of a CHC system
For example, consider the following implementation of the Fibonacci function:
int fib(int n) {
int i = 2;
int prev = 1;
int cur = 1;
while (i < n) {
cur = prev + cur;
prev = cur;
i++; }
return cur;
}
Proving that fib
always returns a non-zero value can be reduced to
solving the following CHC system:
i = 2 /\ prev = cur = 1 => R5(prev, cur, i, n)
R5(n, i, prev, cur), i < n => R5(n, i + 1, cur, prev + cur)
R5(n, i, prev, cur), i >= n => cur != 0
where a solution is an interpretation of the relational predicate
symbol R5
as a formula over variables n
, i
, prev
, and cur
such that each of the entailments given above holds. One such solution
interprets R5
as prev > 0 /\ cur > 0
.
shara
, given such a system, reports that it has a solution.
Determining unsatisfiability of a CHC system
Not every CHC system has a solution. In particular, for program P
and property Q
such that P
does not satisfy Q
, any CHC system
that corresponds to the problem of verifying that P
satisfies Q
will not have a solution.
For example, consider the following erroneous implementation of the Fibonacci function:
int buggy_fib(int n) {
int i = 2;
int prev = 0;
int cur = 0;
while (i < n) {
cur = prev + cur;
prev = cur;
i++; }
return cur;
}
The corresponding CHC system
i = 2 /\ prev = cur = 0 => R5(prev, cur, i, n)
R5(n, i, prev, cur), i < n => R5(n, i + 1, cur, prev + cur)
R5(n, i, prev, cur), i >= n => cur != 0
has no solution. shara
, given such a system, reports that it has no
solution.
Building shara
shara
is implemented as an alternative version of the z3
automatic
theorem prover. To build, run the following commands in package’s
main directory SHARA_DIR
:
$ python scripts/mk_make.py
$ cd build
$ make
When successful, the build system generates an implementation
Using shara
shara
, given a CHC system S
in SMT2 format, attempts to determine
if S
has a solution.
After building shara
in directory SHARA_DIR
, to determine if a CHC
system in file chcs.smt2
has a solution, run the command
$ SHARA_DIR/z3 chcs.smt2
Implementation
shara
is implemented as a fork of the
z3
automatic theorem prover . It
supports an interface identical to that supported by the interface
supported by z3
4.5.
The internal behavior of z3
and shara
differ only when shara
is
given a CHC system. The entire implementation of shara
is
represented by alternative implementations of a solving algorithm used
within z3
’s solver.
References
shara
implements a novel algorithm for solving recursion-free
CHCs, which is based on the observation that a novel class of
recursion-free CHCs can be solved efficiently. A technical report on
the algorithm implemented in shara
is publicly available.
Qi Zhou and William Harris. Solving Constrained Horn Clauses Using Dependence-Disjoint Expansions. arxiv