Practical, low-effort equivalence verification of real code
Verifying code equivalence is useful in many situations, such
as checking: yesterday’s code against today’s, different implementations
of the same (standardized) interface, or an optimized routine against a
reference implementation. We present a tool designed to easily check the
equivalence of two arbitrary C functions. The tool provides guarantees
far beyond those possible with testing, yet it often requires less work
than writing even a single test case. It automatically synthesizes inputs
to the routines and uses bit-accurate, sound symbolic execution to verify
that they produce equivalent outputs on a finite number of paths, even
for rich, nested data structures. We show that the approach works well,
even on heavily-tested code, where it finds interesting errors and gets
high statement coverage, often exhausting all feasible paths for a given
input size. We also show how the simple trick of checking equivalence
of identical code turns the verification tool chain against itself, finding
errors in the underlying compiler and verification tool.
1 Introduction
2011-cav-Practical, low-effort equivalence verification of real code.pdf — PDF document, 205 kB (210481 bytes)