Skip to content

--export-json: a failed, empty, or partial run can serialize as a clean pass #4731

Description

@ivmat

--export-json is a -Z-gated, currently-undocumented output. Using it as a CI pass/fail
oracle in a standard-library verification effort, we hit several cases where the exported file
does not faithfully represent the run: a run that failed, was skipped, matched nothing, or
wasn't fully measured can be read as a clean, complete pass
by a consumer that trusts the file.

These are reporting-fidelity issues in an unstable output — none changes a verification
verdict, a property status, or Kani's exit code. Grouped below by how each is best fixed.

Driver bugs — pre-existing (predate #4472), surfaced but not caused by --export-json; tracked as two small standalone PRs

A. A filter that matches zero harnesses runs to a completed / 0 failed export.
determine_targets only bails on a missing filter under --exact (metadata.rs:112); the
generic "no harnesses matched" bail lives in print_final_summary (harness_runner.rs:302),
which runs after the export is written — so a filter typo yields Ok([]), a clean-looking
export, and exit 0. Same area, independent of --export-json: print_final_summary
early-returns under --quiet (harness_runner.rs:255) before that bail, so
kani --quiet --harness <typo> skips the "no harnesses matched" error and exits 0.
Fix in determine_targets, before codegen and before any export.

B. --fail-fast drops the harnesses it skipped (#4729).
Root cause: collect::<Result<Vec<_>>>() (harness_runner.rs:105) short-circuits on the first
Err and discards already-completed Ok results. The lost harnesses are then absent from the
per-harness details, and the plain-text summary and SARIF under-report too — not only the JSON.
Fix the collect (#4729), not the reporter.

Deferred to RFC #4727

  • Stale export is never invalidated. A run that reuses an existing --export-json path and
    dies before the write leaves the previous complete-looking file in place. The completeness
    mechanism (atomic temp-file + rename, "file exists ⇒ complete") is a schema/design decision
    specified in RFC RFC: Structured verification results (export-json) #4727, not a writer patch.
  • No leaf-value / semantic validation of the exported file. Pending the RFC's open question
    on shipping a JSON Schema (schemars) vs. a homegrown validator.
  • cbmc_stats parsing is brittle (exact strip_prefix/strip_suffix; a malformed duplicate
    can clobber a valid value; overflow/absence collapse to null). Pending the RFC decision on
    whether CBMC statistics remain in the schema at all.

Schema (with the RFC)

  • harness_id == pretty_name can misattribute across a workspace. pretty_name can collide
    between two crates, so the metadata↔details join can attribute a result to the wrong harness
    (confirmed with a workspace carrying duplicate harness names). Fix: make harness_id
    crate-qualified (mangled_name / crate::pretty) — the consumer-facing id, not only the join.

The paired implementation PR #4732 is closed in favor of this decomposition: the two driver PRs,
the RFC, and crate-qualified harness_id.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions