-
Notifications
You must be signed in to change notification settings - Fork 181
[kani] Upgrade verifier to 0.67.0 #3645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,19 +60,123 @@ usually sufficient. | |
| - **Purpose:** Use the | ||
| [Kani Rust Verifier](https://model-checking.github.io/kani/) to prove the | ||
| soundness of `unsafe` code or code relied upon by `unsafe` blocks. Unlike | ||
| testing, which checks specific inputs, Kani proves properties for *all* | ||
| possible inputs. | ||
| testing, which checks selected executions, Kani exhaustively checks a | ||
| harness's modeled state space. That state space is limited by the | ||
| harness's bounds and assumptions, its target and feature configuration, | ||
| and Kani's model of Rust. | ||
| - **How to Write Proofs:** | ||
| - **Harnesses:** Mark proof functions with `#[kani::proof]`. | ||
| - **Inputs:** Use `kani::any()` to generate arbitrary inputs. | ||
| - **Assumptions:** Use `kani::assume(condition)` to constrain inputs to | ||
| valid states (e.g., `align.is_power_of_two()`). | ||
| - **Assertions:** Use `assert!(condition)` to verify the properties you | ||
| want to prove. | ||
| - **CI:** Kani runs in CI using the `model-checking/kani-github-action` with | ||
| specific feature flags to ensure compatibility. | ||
| - **Oracles:** Every oracle must be independent of the implementation | ||
| under proof. Prefer a safe Rust language or standard-library | ||
| operation whose documented contract directly supplies the expected | ||
| behavior. Do not call the target, reuse its zerocopy helper or policy, | ||
| or manually reconstruct the same unchecked operation. For every | ||
| oracle, state its normative basis, why it is independent, and its | ||
| limitations. If no safe oracle exists, isolate the smallest manual | ||
| rule and cite its normative basis. If a predicate merely restates a | ||
| zerocopy acceptance policy, label it as a policy oracle rather than | ||
| evidence of Rust-level validity. | ||
| - **Factoring:** Share repeated case generation, oracle construction, | ||
| and postcondition checks within the proof module. Keep distinct | ||
| harnesses when they exercise different entry points or contracts. | ||
| - **Domain:** Document every scope dimension independently: the | ||
| symbolic input domain; concrete size, allocation, loop, and unwind | ||
| bounds; assumptions and excluded boundary cases; Kani and bundled | ||
| compiler selection; target and data model; enabled features and | ||
| verifier flags; randomized-layout count or seed; the established | ||
| properties; and explicit non-goals. Shared configuration may be | ||
| factored into a nearby family or module scope only when every covered | ||
| harness refers to it unambiguously. | ||
|
Comment on lines
+87
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No existing proof family implements the scope documentation required here. For example, AGENTS.md reference: zerocopy/AGENTS.md:L37-L38 Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed across the dependent proof revisions. The layout family now documents each generator domain, pruning boundary, resource and unwind bound, oracle limitation, and harness theorem; common generation/checking is factored, covers witness the retained and excluded partitions, and the text explicitly excludes the custom/nested-DST algorithm issue in #3630 without inferring its failing partition. Authored by an AI agent acting on Josh Liebow-Feeser's behalf. |
||
| - **Bit validity:** `kani::any::<T>()` produces only valid instances of | ||
| `T`. To verify a byte validator, generate arbitrary bytes and decide | ||
| expected acceptance using an independent oracle before consulting the | ||
| target. Never materialize `T` merely because the validator under | ||
| proof accepts: that validator may be the bug. Construct `T` only | ||
| through an independently safe checked operation. If no such operation | ||
| exists, exercise only a non-materializing decision path for invalid | ||
| candidates and document that limitation. | ||
| - **Soundness boundary:** State which obligations Kani does not prove. | ||
| In particular, Kani does not completely check reference aliasing, | ||
| pointer provenance, invalid values, or uninitialized memory. Kani's | ||
| official [Rust feature support] table marks breaking pointer aliasing | ||
| rules and producing invalid values as unsupported (where unsupported | ||
| analyses "should not be trusted"), and describes uninitialized-memory | ||
| checking as partial and experimental. Its [undefined-behaviour guide] | ||
| also explains the corresponding reference-lifetime and invalid-value | ||
| gaps. Treat conclusions that depend on those semantics as TOOL/TCB | ||
| premises rather than proof results. | ||
| - **Layout randomization:** `--randomize-layout` checks one randomized | ||
| layout per run; it does not prove behavior for every layout or target. | ||
| - **Kani CI configuration:** The exact Kani release is the single | ||
| `kani-version` pin in `.github/workflows/ci.yml`; its bundled compiler is | ||
| the proof toolchain. CI runs on `x86_64-unknown-linux-gnu` (64-bit, | ||
| little-endian) with | ||
| `__internal_use_only_features_that_work_on_stable` (`alloc`, `derive`, | ||
| `simd`, and `std`), `-Zfunction-contracts`, and one layout selected by | ||
| `--randomize-layout` per invocation. Source-level proof scopes should | ||
| refer to this common configuration and state any deviations. | ||
| - **Compiler and documentation compatibility:** After installing the | ||
| pinned Kani release, inspect the `kani-compiler` executable in that | ||
| release's installation directory (normally | ||
| `~/.kani/kani-<version>/bin/kani-compiler`) with `--version --verbose`, | ||
| and inspect its data model with `--print cfg`. Proof premises must cite | ||
| versioned Rust Reference or standard-library documentation. When changing | ||
| the Kani pin, manually recheck every such premise against the new compiler | ||
| snapshot; mechanically changing citation versions does not establish that | ||
|
Comment on lines
+127
to
+130
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The recorded Rust 1.93 compatibility proposition is still not auditable because AGENTS.md reference: zerocopy/AGENTS.md:L37-L38 Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| a guarantee still applies. This compatibility check is a manual TOOL/TCB | ||
| premise: a successful Kani run does not itself establish that the cited | ||
| documentation describes the bundled compiler snapshot. | ||
| - **Fail-closed audit synchronization:** `ci/check_actions.sh`, run by | ||
| pre-push and CI, requires the `kani-version` pin to equal the version named | ||
| by the recorded audit below. The scheduled Kani roller intentionally | ||
| changes only the executable pin, so its PR cannot pass this check until a | ||
| human completes the audit workflow. Do not mechanically update the audit | ||
| version label: first install the new release; replace the compiler, | ||
| target, CBMC, and option-behavior record; recheck every versioned Rust | ||
| contract against the new compiler snapshot; and rerun the complete Kani | ||
| suite. Only then update the label to the new pin. | ||
| - **Recorded toolchain audit for `kani-version: 0.67.0`:** On 2026-09-08, | ||
| `kani-compiler --version --verbose` reported `rustc 1.93.0-nightly`, commit | ||
| `53732d5e076329a62f71d3c6901886ce8a71e812` dated 2025-11-20, LLVM 21.1.5, | ||
| and host `x86_64-unknown-linux-gnu`; `kani-compiler --print cfg` reported | ||
| Linux/gnu, x86_64, little endian, 64-bit pointers, and panic unwinding. | ||
| The bundled `cbmc --version` reported CBMC 6.8.0, and its `--help` | ||
| reported `--no-malloc-may-fail disable potential malloc failure` and | ||
| `--malloc-may-fail allow malloc calls to return a null pointer`. The | ||
| admitted compatibility proposition is that the versioned Rust 1.93.0 | ||
| contracts cited by the current proofs describe the corresponding | ||
| behavior of this nightly snapshot. This was checked manually, not proved | ||
| by Kani. Kani 0.67 [does not model stack unwinding][Kani panic strategies] | ||
| even though | ||
| its bundled compiler's target cfg reports `panic="unwind"`; proofs may | ||
| use reachable panics as failed properties but may not infer cleanup or | ||
| post-panic behavior. | ||
|
|
||
| [Rust feature support]: https://model-checking.github.io/kani/rust-feature-support.html | ||
| [undefined-behaviour guide]: https://model-checking.github.io/kani/undefined-behaviour.html | ||
| [Kani panic strategies]: https://github.com/model-checking/kani/blob/kani-0.67.0/docs/src/rust-feature-support.md#panic-strategies | ||
|
|
||
| Before running proofs locally, install the Kani version pinned in | ||
| `.github/workflows/ci.yml`. Run Kani locally through the required repository | ||
| wrapper with: | ||
|
|
||
| <!-- FIXME: Describe how to ensure that a Kani proof is "total" (esp wrt function inputs). --> | ||
| ```bash | ||
| ./cargo.sh +stable kani \ | ||
| --package zerocopy \ | ||
| --features __internal_use_only_features_that_work_on_stable \ | ||
| --output-format=terse \ | ||
| -Zfunction-contracts \ | ||
| --randomize-layout | ||
| ``` | ||
|
|
||
| At this intermediate commit, CI invokes `cargo-kani` directly while the | ||
| wrapper injects project source-selection cfgs. Consequently, the local and CI | ||
| source-selection configurations are not identical. | ||
|
|
||
| ## Feature Gates | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current head still contradicts this new requirement:
prove_split_at_uncheckedinsrc/byte_slice.rsderives the expected right pointer with unsafeptr.add(mid)(lines 387–388 and 402–403), which is also the primitive used by the mutable implementation at lines 245–295, rather than obtaining the expected partitions from safeslice::split_at. Thus a shared pointer-arithmetic/modeling defect can affect both the target and its oracle. Fresh evidence relative to the resolved thread is thatca0e3c37retains this unchanged harness; replace these expected values with the safe standard-library split before presenting this as the repository's oracle rule.AGENTS.md reference: zerocopy/AGENTS.md:L37-L38
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in the dependent split-proof revision. Checked and unchecked slice,
Ref, andRefMutproofs now obtain result classification and expected partitions from safe Rust 1.93split_at_checked,split_at, orsplit_at_mut; expected mutation frames also use safe slice operations. The oracle no longer reconstructs the expected right pointer with rawadd.Authored by an AI agent acting on Josh Liebow-Feeser's behalf.