Table of Contents
Fetching ...

Gradual C0: Symbolic Execution for Gradual Verification

Jenna DiVincenzo, Ian McCormack, Hemant Gouni, Jacob Gorenburg, Jan-Paul Ramos-Dávila, Mona Zhang, Conrad Zimmerman, Joshua Sunshine, Éric Tanter, Jonathan Aldrich

TL;DR

This paper introduces Gradual C0, the first practicable gradual verifier for recursive heap data structures in the C0 language, built on the Viper verification framework and powered by symbolic execution to handle imprecise specifications. By allowing partial specifications and generating minimized runtime checks, Gradual C0 enables a spectrum between static and dynamic verification, reducing upfront auxiliary specification burden while preserving soundness. Empirical evaluation shows that Gradual C0 reduces run-time overhead by an average of 11-34% compared to fully dynamic verification, with predictable worst-case costs, and demonstrates the approach's practical viability and extensibility to other languages through its two-pipeline design (C0 frontend and Gradual Viper backend). The work signals a significant step toward usable, scalable verification of programs that manipulate recursive heap structures, enabling earlier feedback and broader adoption in practice.

Abstract

Current static verification techniques support a wide range of programs. However, such techniques only support complete and detailed specifications, which places an undue burden on users. To solve this problem, prior work proposed gradual verification, which handles complete, partial, or missing specifications by soundly combining static and dynamic checking. Gradual verification has also been extended to programs that manipulate recursive, mutable data structures on the heap. Unfortunately, this extension does not reward users with decreased dynamic checking as specifications are refined. In fact, all properties are checked dynamically regardless of any static guarantees. Additionally, no full-fledged implementation of gradual verification exists so far, which prevents studying its performance and applicability in practice. We present Gradual C0, the first practicable gradual verifier for recursive heap data structures, which targets C0, a safe subset of C designed for education. Static verifiers supporting separation logic or implicit dynamic frames use symbolic execution for reasoning; so Gradual C0, which extends one such verifier, adopts symbolic execution at its core instead of the weakest liberal precondition approach used in prior work. Our approach addresses technical challenges related to symbolic execution with imprecise specifications, heap ownership, and branching in both program statements and specification formulas. We also deal with challenges related to minimizing insertion of dynamic checks and extensibility to other programming languages beyond C0. Finally, we provide the first empirical performance evaluation of a gradual verifier, and found that on average, Gradual C0 decreases run-time overhead between 11-34% compared to the fully-dynamic approach used in prior work. Further, the worst-case scenarios for performance are predictable and avoidable.

Gradual C0: Symbolic Execution for Gradual Verification

TL;DR

This paper introduces Gradual C0, the first practicable gradual verifier for recursive heap data structures in the C0 language, built on the Viper verification framework and powered by symbolic execution to handle imprecise specifications. By allowing partial specifications and generating minimized runtime checks, Gradual C0 enables a spectrum between static and dynamic verification, reducing upfront auxiliary specification burden while preserving soundness. Empirical evaluation shows that Gradual C0 reduces run-time overhead by an average of 11-34% compared to fully dynamic verification, with predictable worst-case costs, and demonstrates the approach's practical viability and extensibility to other languages through its two-pipeline design (C0 frontend and Gradual Viper backend). The work signals a significant step toward usable, scalable verification of programs that manipulate recursive heap structures, enabling earlier feedback and broader adoption in practice.

Abstract

Current static verification techniques support a wide range of programs. However, such techniques only support complete and detailed specifications, which places an undue burden on users. To solve this problem, prior work proposed gradual verification, which handles complete, partial, or missing specifications by soundly combining static and dynamic checking. Gradual verification has also been extended to programs that manipulate recursive, mutable data structures on the heap. Unfortunately, this extension does not reward users with decreased dynamic checking as specifications are refined. In fact, all properties are checked dynamically regardless of any static guarantees. Additionally, no full-fledged implementation of gradual verification exists so far, which prevents studying its performance and applicability in practice. We present Gradual C0, the first practicable gradual verifier for recursive heap data structures, which targets C0, a safe subset of C designed for education. Static verifiers supporting separation logic or implicit dynamic frames use symbolic execution for reasoning; so Gradual C0, which extends one such verifier, adopts symbolic execution at its core instead of the weakest liberal precondition approach used in prior work. Our approach addresses technical challenges related to symbolic execution with imprecise specifications, heap ownership, and branching in both program statements and specification formulas. We also deal with challenges related to minimizing insertion of dynamic checks and extensibility to other programming languages beyond C0. Finally, we provide the first empirical performance evaluation of a gradual verifier, and found that on average, Gradual C0 decreases run-time overhead between 11-34% compared to the fully-dynamic approach used in prior work. Further, the worst-case scenarios for performance are predictable and avoidable.
Paper Structure (9 sections, 1 equation, 4 figures)

This paper contains 9 sections, 1 equation, 4 figures.

Figures (4)

  • Figure 1: Non-empty linked list insertion in C0
  • Figure 2: The static verification of insertLast from Fig. \ref{['ex:ll-insert']}
  • Figure 3: The incremental verification of insertLast from Fig. \ref{['ex:ll-insert']}
  • Figure 4: System design of Gradual C0