A Recipe for Modular Verification of Generic Tree Traversals
Data structures based on trees and tree traversals are ubiquitous in computer systems. Many low-level programs, including some implementations of critical systems like page tables and the web browser DOM, rely on \emph{generic} tree-traversal functions that traverse tree nodes in a pre-determined order, applying a client-provided operation to each visited node. Developing a general approach to specifying and verifying such traversals is tricky since the client-provided per-node operation can be stateful and may potentially depend on or modify the structure of the tree being traversed.
In this paper, we present a \emph{recipe} for (semi-)automated verification of such generic, stateful tree traversals. Our recipe is (a)~\emph{general}: it applies to a range of tree traversals, in particular, pre-, post- and in-order depth-first traversals; (b)~\emph{modular}: parts of a traversal’s proof can be reused in verifying other similar traversals; (c)~\emph{expressive}: using the specification of a tree traversal, we can verify clients that use the traversal in a variety of different ways; and (d)~\emph{automatable}: many proof obligations can be discharged automatically.
At the heart of our recipe is a novel use of tree \emph{zippers} to represent a logical abstraction of the tree traversal state, and zipper transitions as an abstraction of traversal steps. We realize our recipe in the RefinedC framework in Rocq, which allows us to verify a number of different tree traversals and their clients written in C.