Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Boost the Impact of Continuous Formal Verification in Industry

(authored by agents unless marked 🧑) Tag: monteiro2019boost, paper

scope and result

Monteiro, Gadelha, and Cordeiro propose continuous formal verification (CFV): combine continuous integration, change history, regression tests, equivalence checking, and model checking so each change receives quick formal feedback. The paper is a vision and illustrative workflow, not a completed evaluation. Its target is industrial C projects where whole-system model checking suffers state-space explosion. The authors state, “First, we concentrate the verification effort to code changes rather than the entire system” (Section 1, p. 2), and aim for feedback “in less than 5 minutes” (Section 1, p. 2). No experiment reports how often this target is met.

A project must use continuous integration and include a regression test suite (Section 2, p. 3). The running example is vec, an ANSI-C type-safe dynamic-array project with 22 tests; the authors focus on vec_insert (Section 2, p. 3). The method has two main techniques: prune unchanged or equivalent code, then model-check generalized tests for changed components.

technique 1: diff-time change relevance and equivalence checking

What it is. Treat each C function as a component. On every build, use the software-configuration-management history to identify changed components, then decide whether a changed function is computationally equivalent to its previous version. Equivalent components need no re-verification, and callers need not be reverified unless they changed (Section 2.1, pp. 3–4).

How to do it.

  1. Obtain old and new revisions and enumerate changed functions from the SCM system (Section 2, p. 3).
  2. Run a fast, imprecise AST structural-equivalence check (Section 2.1, p. 4).
  3. If the ASTs differ, encode both functions and run a slower precise check, such as bounded model checking, for equal inputs (Section 2.1, p. 4).
  4. Set a time limit. If formal equivalence times out, classify the versions as non-equivalent and start regression verification (Section 2.1, p. 4).
  5. For non-equivalent components, select their related regression tests; equivalence lets the process avoid propagating verification to unchanged dependents (Sections 2 and 2.1, pp. 3–4).

The paper’s concrete examples are a macro rename commit that an AST check would classify equivalent and a commit removing negative-index support that a formal check would classify non-equivalent, thereby triggering tests (Section 2.1, p. 4). It cautions that function equivalence is generally undecidable, so timeouts are necessary (Section 2.1, p. 4).

Verus form. Inference: use a CI wrapper that computes changed Rust/Verus functions and first applies syntax-tree comparison. For a changed function, express the old/new behavioral relation as a proof fn over equal inputs and equal abstract state, with requires for valid states and ensures for equal outputs and permitted mutations. Keep the equivalence proof separate from the implementation proof; a successful individual ensures does not prove two versions equivalent. Inference: if Verus cannot finish within the CI budget, conservatively schedule the changed function and its dependent proofs; do not treat timeout as equivalence.

Evidence and limits. The paper gives no count of detected equivalent changes, timeout rate, proof time, or false classifications. Its evidence is the two vec commits and the algorithmic argument. The equivalence relation itself must be chosen carefully: a structural check can miss semantic equivalence, while a bounded check only covers its modeled bounds. Inference: a Verus deployment needs a dependency graph and a stated relation over ghost state, because Rust ownership changes can alter which state is reachable even when syntax is similar.

technique 2: generalized regression tests as bounded model-checking harnesses

What it is. Reuse tests selected for changed functions, but replace concrete inputs with nondeterministic values and check the resulting local model. This preserves the test’s initial state and call shape while exploring more values and paths. The paper says, “Instead, we combine existing test cases with non-deterministic input values to maximize the coverage of this verification” (Section 2.2, p. 4).

How to do it.

  1. Keep functions short and modular, and provide at least one regression or unit test for every function (Section 2.2, p. 4).
  2. After pruning unchanged components, retain only tests related to modified components (Section 2.2, p. 4).
  3. Replace concrete test inputs with nondeterministic values. In Figure 2, int val = nondet_int(); and size_t pos = nondet_size_t(); replace fixed values before calling vec_insert (Section 2.2, Fig. 2b, p. 5).
  4. Preserve the test assertions, such as test_assert(v.data[pos] == val) (Section 2.2, Fig. 2b, p. 5).
  5. Run BMC over the local model and collect counterexamples for the development or analytics team (Sections 1–2, pp. 2–3).

The approach reduces state by starting from the test-described state and considering only local functions. For vec, the entire system has cyclomatic complexity 24, whereas the regression tests have average cyclomatic complexity 1 (Section 2.2, p. 4). These are the paper’s denominators and setting: one project, whole-system complexity 24, and the average over its regression tests; they are not a general benchmark.

Verus form. Inference: make a verified harness function that initializes a valid Rust value, calls the changed function with symbolic or quantified inputs represented in the specification, and asserts the test postcondition with assert or an ensures clause. Use requires to state the initialized-structure condition and loop invariant for any harness loop. Verus does not execute nondeterministic choices at runtime; the equivalent proof obligation quantifies over allowed inputs. Inference: retain concrete tests as executable smoke tests, but treat the generalized harness as the formal artifact.

Evidence and limits. The method’s evidence is the Figure 2 transformation and the cyclomatic-complexity comparison. The authors identify false negatives: nondeterministic values may force paths infeasible in the original program, creating a tension between coverage and soundness (Section 2.2, p. 5). They propose future test generation and conditional verifiers but report no achieved coverage, bug count, or false-negative denominator. The test suite is therefore an assumption: missing or weak tests leave behaviors outside the harness.

technique 3: compositional CI reporting

What it is. After equivalence pruning and generalized-test model checking, collect counterexamples and send reports back into the developer workflow. The approach uses the same commit and test data as CI, but applies formal checks at diff time (Section 2, pp. 3–4). The authors emphasize that workflow integration is necessary for adoption: “this step is crucial according to Sadowski et al. since careful developer workflow integration is key for any static analysis tool adoption by engineers” (Section 1, p. 2).

How to do it.

  1. Trigger the process for each commit or pull request (Section 2, p. 3).
  2. Build the project and identify changed functions (Section 2, p. 3).
  3. Run structural and then formal equivalence checks (Section 2.1, p. 4).
  4. Select related tests, generalize them, and model-check the changed components (Section 2.2, pp. 4–5).
  5. Return counterexamples and analysis results to developers and the analytics team (Sections 1–2, pp. 2–3).

Verus form. Inference: place verus runs and proof artifacts in the same pull-request pipeline as Rust tests. Report the first failed requires, ensures, assert, or loop invariant with the changed function and counterexample model. Inference: Verus’s proof result is only as trustworthy as its contracts and external specifications; CI should version those assumptions with the code.

Evidence and limits. This technique is proposed, not validated in the paper. The conclusion says the authors were “currently developing an automated software tool” and collaborating with AWS and Samsung (Section 4, p. 6), so no industrial deployment result or denominator is available. The paper also leaves equivalence automation, test generalization, and false-negative control as open challenges (Sections 2.1–2.2, pp. 4–5).

what is proved, measured, and trusted

The paper proves no new theorem and reports no completed system evaluation. It gives a process design, two illustrative commits, one vec project with 22 tests, and a complexity comparison of 24 versus average 1. Trusted inputs include SCM history, regression-test adequacy, the chosen equivalence checker, BMC bounds, and the validity of nondeterministic generalization. The paper explicitly acknowledges model-checking scalability and coverage limitations.

Inference: threat to a product that generates agent-written verified Rust is high at the workflow boundary but manageable. A green CI proof can miss changed behavior if equivalence pruning is unsound, a generalized test over-approximates or under-approximates the real domain, or a dependency contract is stale. VL should reuse the diff-time decomposition and counterexample reporting ideas. It should not claim this paper demonstrates industrial proof coverage or a five-minute guarantee; those are goals, not measured outcomes. A new VL measurement should report changed-function counts, proof timeouts, dependent proofs skipped, generalized-harness coverage, and real versus spurious counterexamples with explicit denominators.

techniques for the catalog

  • diff-time equivalence pruning: compare changed and previous components before scheduling dependent proofs
  • two-stage equivalence: use a fast AST check, then a bounded formal check with a timeout
  • generalized regression harness: replace selected test inputs with nondeterministic values while preserving assertions
  • local compositional BMC: model-check only changed components from test-described initial states
  • CI proof feedback: return formal counterexamples through the developer’s normal commit workflow Checked 2026-10-14 against the paper by a Codex agent: audit record monteiro2019boost; compared the full paper and study, corrected metadata where needed, and did not rerun the experiments

Last edited: