Skip to content

Pay the clippy debt in walgit-proto - #23

Open
ethanstoner wants to merge 1 commit into
tobi:mainfrom
ethanstoner:fix/proto-panic-paths
Open

Pay the clippy debt in walgit-proto#23
ethanstoner wants to merge 1 commit into
tobi:mainfrom
ethanstoner:fix/proto-panic-paths

Conversation

@ethanstoner

Copy link
Copy Markdown

Follow-up to #15, which says the gate is red "until the existing debt is paid ... fixing is left to follow-up commits." This pays walgit-proto's share — 27 of the workspace's 74 errors — after which the crate is clean under -D warnings.

Deliberately one crate. The rest of the debt (walgit-config has 45, plus walgit-server/build.rs) is untouched here so each slice stays reviewable, and so this does not collide with #17, #19 or #20.

What is in it

19 × doc_markdown inside mod v1. prost reproduces the doc comments written in wal.proto, so the lint is judging the schema's prose rather than ours. Targeted allow on the module.

frame::encode_entryexpect on encode, which fails only on insufficient capacity, and reserve(encoded_len()) runs immediately above. Cargo.toml's own note says known-infallible cases should "say so with a targeted #[allow] or an expect() naming the invariant"; this now does both.

frame::decode_entries — indexed and sliced a buffer read from the bucket and narrowed a u64 frame length with as. Rewritten in checked operators: get(pos..), usize::try_from, get(..len), each falling out of the loop exactly where a short read already did.

time::from_system / to_systemas across the signed boundary becomes cast_signed/cast_unsigned. to_system clamps to zero first, so neither cast can change the value it carries.

On the parser rewrite — not a bug fix

I want to be exact about this, because "checked operators" invites the reading that something was broken. Nothing was.

The bounds were already established: pos = buf.len() - probe.len() + len after a remaining() >= len check cannot exceed buf.len(), and &probe[..len] was guarded by that same check. Even the u64 → usize narrowing was harmless, since a truncated length still failed the remaining() test on both 32- and 64-bit. These were theoretical panic paths that the lint flags and the code never took.

So the added test passes against the old body as well, by construction. It is not there to catch a regression that existed; it is there so the rewrite is provably behaviour-preserving, which is the only claim I can make honestly. If you would rather this PR not carry a test that cannot fail against main, say so and I will drop it.

Verification

Check Result
cargo clippy -p walgit-proto --all-targets -- -D warnings clean
Workspace clippy errors 74 on main → 47
cargo fmt --check -p walgit-proto clean
cargo test -p walgit-proto 4 pass
cargo test -p walgit-wal -p walgit-store -p walgit-bundle 9 suites, all green

just clippy still fails overall, as expected — the remaining 47 live in the crates this PR does not touch. Happy to take those in the same shape if this one lands the way you want it.

5ccc405 turned on the strict gate and left the existing debt to follow-up
commits. This is walgit-proto's share: 27 of the workspace's 74 errors,
after which the crate is clean under `-D warnings`.

Nineteen were `doc_markdown` inside `mod v1`, where prost reproduces the
doc comments written in wal.proto — the lint is judging the schema's prose,
not ours, so the module carries a targeted allow.

The rest are hand-written:

  - `frame::encode_entry` expects on `encode`, which fails only when the
    buffer lacks capacity — and `reserve(encoded_len())` runs immediately
    above. The invariant is now stated in an allow rather than implied.

  - `frame::decode_entries` indexed and sliced a buffer read from the
    bucket, and narrowed a `u64` frame length to `usize` with `as`. The
    bounds were in fact all established — `pos` never exceeds `buf.len()`
    and the length was checked against `remaining()` first — so this is a
    rewrite in checked operators, not a fix: `get(pos..)`, `usize::try_from`
    and `get(..len)`, each falling out of the loop the way a short read
    already did. A test pins that contract so the rewrite is provably
    behaviour-preserving; it passes against the old body too, by design.

  - `time::from_system` / `to_system` used `as` across the signed boundary.
    `cast_signed`/`cast_unsigned` say the same thing and are checked by the
    reader instead of the compiler; `to_system` clamps to zero first, so
    neither cast can change the value it carries.

walgit-proto is clippy-clean, `cargo fmt --check` is clean, its four tests
pass, and walgit-wal, walgit-store and walgit-bundle are unchanged-green.
@0bserver07

Copy link
Copy Markdown

Ran this here on rust 1.97.1: cargo clippy -p walgit-proto --all-targets --no-deps -- -D warnings is clean and the 4 tests pass. The decode_entries rewrite reads as equivalent to me: each early break lands where the old remaining() < len check did, and the usize::try_from case can only fire where the old cast would have failed that check anyway. I'm doing walgit-config in the same shape (see #24), so we won't step on each other.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants