redhat-et / redhat-et/ripwire

`ripwire --doctor` should detect a binary whose translation units disagree on struct layout

Open
#162 1 comment 0 reactions 0 assignees View on GitHub
good first issue help wanted
Dominant language
C++
Stars
2.1k
Forks
125
Avg merge
5h 28m
Merged PRs (30d)
163

Description

## What is missing

If `src/model.h` changes while a build is running, some object files end up compiled against the old
`Symbol` layout and some against the new one. Their mtimes are newer than the header, so `make`
concludes everything is up to date and never recompiles them — the build reports success, exit 0, no
warnings, forever. Nothing in CMake can repair this, and `test/g1freshcheck.sh` cannot see it,
because the binary is *newer* than its sources and only its contents are stale. The ask is for
`ripwire --doctor` to say it in one line: each translation unit records the struct layouts it was
compiled with, and the doctor reports when they disagree.

## The evidence

`CLAUDE.md` records three incidents from this failure mode, all from building across or editing
under a branch switch:

- A sanitizer build finishing after a checkout that changed `Symbol` produced a genuine
AddressSanitizer heap-buffer-overflow report for a bug that did not exist. The overflowing region
was 1344 bytes — exactly 14 × 96, a multiple of the *previous* struct size.
- A header's mirrored constant kept emitting its old value through repeated successful rebuilds; a
gate failed with `parserVer=41, expected 12/42` and looked like a missed mirror update.
- Ten identical uncaught `std::length_error` aborts in one morning of worktree churn, thrown from a
`resize( symbols.size() )`, with zero repro in 38 runs on clean rebuilds of the same commit.

Facts read from the tree that the kit rests on:

- The `ripwire` target is `src/main.cpp` plus `src/ingest.cpp`, `src/pagerank.cpp` and
`src/infra/diagnostics.cpp`; `IngestResult` carries vectors of `Symbol`, `Reference` and eight
other structs across that boundary.
- `Symbol` is pinned by `static_assert( sizeof( Symbol ) == 64 + 2 * sizeof( std::string ) )` — which
every translation unit checks against *its own* view of the header, so it passes in both halves of
a mixed binary. `Reference` has no size pin at all.
- `--doctor` (`src/verbs_doctor.h`) emits one `` row per check and exits 1 when any fails;
`test/doctorcheck.sh` asserts a named row set.
- `--layout` and `--stray-content --abi` model struct layout from source text ("a MODEL, NOT THE
ABI") and cannot see what a compiler actually produced.

## Size

**Good first issue.** One recording header, one registry, one doctor row, one gate, and a short
audit of the cache-format size pins. No external corpus, no network, no API keys — a C++23
toolchain and CMake able to produce both the plain dev build and a Release build, because the
records must survive `NDEBUG` and LTO.

## Where to start

`prompts/help-wanted/struct-layout-doctor.md` is a self-contained prompt for a coding agent. It
carries the hazard and its three recorded incidents, the translation units involved, why a header
`static_assert` cannot catch it, how to reproduce it safely in a scratch tree, the recording and
comparison design space (internal linkage, a per-unit identity, surviving Release and LTO, comparing
for agreement rather than pinning numbers), the doctor row's three states, the gate arms, the
acceptance criteria and the traps. Like every prompt in `prompts/`, **it ends by writing a plan and
stopping** — a maintainer agrees the plan before any code is written.

Build the gate first: a two-translation-unit fixture whose struct definitions differ must make the
comparator report a disagreement before the real row exists.

Comment here to claim it.

Contributor guide

Open the contributing guide

Research direction

Start with prompts/help-wanted/struct-layout-doctor.md, then inspect src/verbs_doctor.h and test/doctorcheck.sh. Build the two-translation-unit fixture first and verify that it detects disagreement before adding the real doctor row. Done means the recording, comparison, gate, Release/LTO behavior, and cache-format size-pin audit meet the prompt’s acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
cmake, cpp
Domain
build-system, cli, testing-qa
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.