Fix audit findings: soundness, coverage reporting, docs, and review follow-ups #1
3 changed files with 73 additions and 56 deletions
docs: trim the README and move the performance roadmap to docs/
The README listed 11 of fold's 17 detectors, never explained the confidence tiers every finding carries, did not mention the new exit code 2 / coverage reporting, and spent half its length on a performance roadmap. It now says what fold is, defines the five tiers (from include/fold/report/finding.hpp, including concrete-witness and latent), what "bounded" means after the loop-exit fix, a quick start, output formats and exit codes (0 none, 1 any unsuppressed finding, 2 unwritable report or any unanalysed translation unit), and links. The detector list defers to the complete table in docs/USAGE.md. The performance section moves to docs/architecture/performance.md, with one correction: the gold set was derived from fold's own reviewed output and is matched by detector kind and file, so it catches drift rather than measuring precision/recall independently. The lint pre-commit hook note moves to BUILD.md.
commit
2945e59bc2
3
BUILD.md
3
BUILD.md
|
|
@ -8,6 +8,9 @@
|
||||||
# tests: meson test -C build/release
|
# tests: meson test -C build/release
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`setup.sh` also enables the tracked lint pre-commit hook
|
||||||
|
(`.githooks/pre-commit`).
|
||||||
|
|
||||||
Linux users without root can validate against a clean container:
|
Linux users without root can validate against a clean container:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
|
||||||
95
README.md
95
README.md
|
|
@ -1,72 +1,57 @@
|
||||||
# fold
|
# fold
|
||||||
|
|
||||||
Bounded symbolic SAST for C++ — clone detection, dead-branch analysis,
|
Bounded symbolic static analysis for C++: dead-branch and hazard detection
|
||||||
and security vulnerability scanning via Clang LibTooling and Z3.
|
(null dereference, division by zero, integer overflow, out-of-bounds, and more),
|
||||||
|
clone and equivalence detection, and taint tracking, built on Clang LibTooling
|
||||||
|
and the Z3 solver. Rust (HIR), Swift and binary scan modes also exist; the Rust
|
||||||
|
detectors are heuristic today.
|
||||||
|
|
||||||
## Build
|
Every finding carries a confidence tier that says how it was established:
|
||||||
|
|
||||||
|
| Tier | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `concrete-witness` | A fuzzer ran the solver's witness under a sanitizer and produced a correlated crash. |
|
||||||
|
| `proved` | An exact bounded model proved it: SAT for a hazard witness, or UNSAT for a negated invariant. |
|
||||||
|
| `latent` | Proved inside the function, but only reachable if a caller supplies a value the callee never guards. |
|
||||||
|
| `heuristic` | Some part of the model was over-approximated. |
|
||||||
|
| `syntactic` | An AST pattern or hash match only. |
|
||||||
|
|
||||||
|
"Bounded" is literal: loops are unrolled to a fixed depth, and a condition that
|
||||||
|
depends on a loop's exit is never reported as proved. The contract behind each
|
||||||
|
tier is in [docs/research/soundness.md](docs/research/soundness.md).
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./setup.sh release
|
./setup.sh release # needs LLVM/Clang 18+ and libz3 headers; Conan handles the rest
|
||||||
```
|
|
||||||
|
|
||||||
Requires system-installed LLVM/Clang 18+ and `libz3` development
|
|
||||||
headers; Conan handles the rest (spdlog, CLI11, nlohmann_json,
|
|
||||||
sqlite3, Catch2). **See [BUILD.md](BUILD.md) for per-platform
|
|
||||||
apt/brew install lines and a Docker validation harness.** Setup also enables
|
|
||||||
the tracked lint pre-commit hook (`.githooks/pre-commit`).
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
fold scan --compile-db compile_commands.json \
|
fold scan --compile-db compile_commands.json \
|
||||||
--detectors null-deref --detectors div-by-zero \
|
--detectors null-deref --detectors div-by-zero \
|
||||||
--format sarif --output findings.sarif
|
--format sarif --output findings.sarif
|
||||||
```
|
|
||||||
|
|
||||||
Detectors: `clone`, `equiv`, `class-dup`, `dead`, `null-deref`,
|
|
||||||
`div-by-zero`, `int-overflow`, `oob`, `int-truncation`, `sign-conversion`,
|
|
||||||
`taint-track`.
|
|
||||||
|
|
||||||
Output formats: `sarif`, versioned native `findings-json`, and `markdown`.
|
|
||||||
`json` remains a deprecated compatibility alias for SARIF. Query existing Fold
|
|
||||||
reports without scanning raw source text:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
fold grep "null pointer" findings.sarif --field message --ignore-case
|
fold grep "null pointer" findings.sarif --field message --ignore-case
|
||||||
```
|
```
|
||||||
|
|
||||||
See `docs/USAGE.md` for the full CLI and MCP/LSP reference, and
|
Per-platform install lines and a Docker validation harness are in
|
||||||
`docs/compatibility.md` for deprecated-name migrations and removal criteria.
|
[BUILD.md](BUILD.md).
|
||||||
|
|
||||||
## Research docs
|
Output formats are `sarif`, versioned `findings-json`, and `markdown`. Both
|
||||||
|
machine formats record which translation units were analysed. A scan exits `0`
|
||||||
|
with no findings, `1` with any unsuppressed finding, and `2` when a report could
|
||||||
|
not be written or any translation unit was not analysed (compile errors,
|
||||||
|
frontend failure, crash, timeout): no findings from an incomplete scan is not
|
||||||
|
evidence of no bugs.
|
||||||
|
|
||||||
`docs/research/` — architecture, benchmarks, prior art, frontier roadmap,
|
## Documentation
|
||||||
soundness proofs, and audit artifacts.
|
|
||||||
|
|
||||||
## Performance architecture
|
- [Usage](docs/USAGE.md): the full CLI (scan modes, scopes, confirmation,
|
||||||
|
fuzzing), every detector with its CWE and method, MCP/LSP, and project
|
||||||
Optimization is measurement-first and gate-guarded. Every candidate
|
evaluation.
|
||||||
change runs through the manifest-driven evaluation harness
|
- [MCP tools](docs/mcp-tools.md) and [compatibility](docs/compatibility.md)
|
||||||
(`tests/benchmarks/projects/*.json`), which enforces finding-fingerprint
|
(deprecated names and removal criteria).
|
||||||
stability, gold precision/recall (`bench/gold/`), reviewed dispositions, and
|
- [Positioning](docs/positioning.md) and [prior art](docs/research/prior-art.md):
|
||||||
wall/RSS regression baselines. A full ledger of measured wins and closed
|
how fold relates to other analyzers.
|
||||||
hypotheses lives in
|
- [Performance](docs/architecture/performance.md): the evaluation gates and the
|
||||||
[`docs/research/optimization-loop-2026-07-30.md`](docs/research/optimization-loop-2026-07-30.md).
|
single-pass graph-building plan.
|
||||||
|
- [Architecture](docs/architecture/) and [research](docs/research/) notes.
|
||||||
The one structural work on the roadmap is **single-pass graph building**.
|
|
||||||
Today a source scan parses each translation unit twice — once to build the
|
|
||||||
project call graph, once to run detectors — because the detector pass consumes
|
|
||||||
the graph (cross-TU candidate expansion and summary priming). The planned
|
|
||||||
change collapses these into one parse per TU that produces graph contributions
|
|
||||||
and runs the intra-TU detectors in the same pass, retaining only light per-TU
|
|
||||||
edge/signature records, and runs the cross-TU-dependent closure after every TU.
|
|
||||||
This is deliberately chosen over precompiled-header/module caching to
|
|
||||||
**preserve portability**: it introduces no clang-version-locked serialized
|
|
||||||
artifacts, no SDK/toolchain-locked module cache, and no `-std`/`-I`/`-D`
|
|
||||||
flag-matching bug surface — every machine that consumes a
|
|
||||||
`compile_commands.json` today keeps working unchanged. Correctness parity for
|
|
||||||
the deferred closure is policed by the existing finding-fingerprint and gold
|
|
||||||
gates.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
29
docs/architecture/performance.md
Normal file
29
docs/architecture/performance.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Performance
|
||||||
|
|
||||||
|
Optimization is measurement-first and gate-guarded. Every candidate change runs
|
||||||
|
through the manifest-driven evaluation harness
|
||||||
|
(`tests/benchmarks/projects/*.json`), which enforces finding-fingerprint
|
||||||
|
stability, reviewed dispositions, wall-time and RSS regression baselines, and a
|
||||||
|
gold set (`bench/gold/`). The gold set was derived from fold's own reviewed
|
||||||
|
output and is matched by detector kind and file, so it catches drift; it is not
|
||||||
|
an independent precision or recall measure. A ledger of measured wins and
|
||||||
|
closed hypotheses is in
|
||||||
|
[the optimization loop](../research/optimization-loop-2026-07-30.md).
|
||||||
|
|
||||||
|
## Single-pass graph building
|
||||||
|
|
||||||
|
The one structural item on the roadmap is single-pass graph building. A source
|
||||||
|
scan currently parses each translation unit twice: once to build the project
|
||||||
|
call graph, and once to run detectors, because the detector pass consumes the
|
||||||
|
graph (cross-TU candidate expansion and summary priming). The planned change
|
||||||
|
collapses these into one parse per TU that produces graph contributions and runs
|
||||||
|
the intra-TU detectors in the same pass, keeping only light per-TU edge and
|
||||||
|
signature records, then runs the cross-TU-dependent closure after every TU. See
|
||||||
|
[the design](../research/single-pass-graph-design.md).
|
||||||
|
|
||||||
|
This is chosen over precompiled-header or module caching to preserve
|
||||||
|
portability: it introduces no Clang-version-locked serialized artifacts, no
|
||||||
|
SDK- or toolchain-locked module cache, and no `-std`/`-I`/`-D` flag-matching
|
||||||
|
bug surface, so every machine that consumes a `compile_commands.json` today
|
||||||
|
keeps working. Correctness parity for the deferred closure is policed by the
|
||||||
|
existing finding-fingerprint and gold gates.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue