open-standards/joule-code/joule-code-rs/crates
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science c6520f8e54
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 10s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m18s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 2m5s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 6m32s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 1m47s
jwp: a zstd payload over the cap is rejected, not truncated
The `CompressionStrategy` trait documents its third argument as
"`max_output` caps the decompressed size to prevent decompression
bombs". `ZstdCompression::decompress` implemented that as

    decoder.take(max_output as u64).read_to_end(&mut output)?;
    Ok(output)

`Read::take(n)` plus `read_to_end` does not detect the cap being hit.
It yields exactly `n` bytes and reports success, discarding the rest,
so the bomb case — the one condition `max_output` exists for — came
back as a value rather than a failure, and the caller could not tell a
complete payload from a truncated prefix of an arbitrarily larger one.

The consequence is not confined to the strategy. `AdaptiveCodec::decode`
calls `decompress(&raw_payload, MAX_PAYLOAD_LEN)` with a 16 MiB cap,
and on `Ok` goes on to rewrite the header — `payload_length:
payload.len() as u32`, commented "Normalize payload_length to
decompressed size" — and to fold that length into the connection
statistics via `observe_frame`. A peer frame whose zstd payload expands
to 20 MiB was therefore accepted as a well-formed, complete 16 MiB
frame, with the truncation recorded nowhere.

`Lz4Compression::decompress`, behind the same trait, has always
returned `CompressionError` for exactly this condition, so the two
implementations had opposite semantics. Only the lz4 side was tested
(`lz4_rejects_oversized_decompression`), which is why the divergence
was invisible.

Read one byte past the cap and reject when it arrives. That
distinguishes "exactly at the cap", which is valid and still returns
the whole payload, from "over the cap", which is now an error — and
brings zstd into line with lz4. The limit is computed with
`saturating_add` so a `max_output` of `usize::MAX` cannot wrap it.

Tests: `zstd_rejects_oversized_decompression` mirrors the lz4 test and
asserts on the fixture actually exceeding the cap, so it cannot pass
vacuously; `zstd_accepts_output_exactly_at_the_cap` pins the boundary
the extra byte must not break.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-17 04:36:53 -04:00
..
joule-code-cargo joule-code: stand up the Joule Code standard (v0.1.0 draft) 2026-06-02 14:07:00 -04:00
joule-code-cascade joule-code: add generic FnStage to the cascade (L1/L2/L3 binding) 2026-06-03 12:50:43 -04:00
joule-code-collab lockstep-quic: distributed BFT consensus over the real-QUIC transport 2026-06-27 07:12:43 -04:00
joule-code-conformance joule-code: close the two gaps its conformance gate cannot see 2026-10-10 17:20:38 -04:00
joule-code-identity joule-code-identity: a Roster — resolve did:key → {label, kind} for audit 2026-06-11 19:27:37 -04:00
joule-code-jcp joule-code: repair jcp_schema::Grant literals — second cross-workspace break 2026-07-22 10:29:18 -04:00
joule-code-joulecontract joulecontract v0.8: the implementability amendment — round five seals the pack 2026-06-10 16:21:44 -04:00
joule-code-receipt specs: a vendor counter is a hardware reading only while it is demonstrably live 2026-10-01 01:10:36 -04:00
joule-code-release joule-code-release: the whole chain end to end, as one runnable artifact 2026-06-11 00:32:56 -04:00
joule-code-remediate joule-code-remediate: formal_fix prints each proof figure with its grade, not as "measured" 2026-10-14 20:01:38 -04:00
joule-code-review family: the methodology layer, made auditable — spec, review, vericoding 2026-06-10 17:45:47 -04:00
joule-code-reviewer tooling: meter-cmd (energy bracket) + gen-fixture (review fixtures) 2026-06-12 07:04:06 -04:00
joule-code-schema joule-code: stand up the Joule Code standard (v0.1.0 draft) 2026-06-02 14:07:00 -04:00
joule-code-spec family: the methodology layer, made auditable — spec, review, vericoding 2026-06-10 17:45:47 -04:00
joule-moq joule-moq: clippy's style notes on the draft-22 code 2026-10-16 10:22:34 -04:00
jwp jwp: a zstd payload over the cap is rejected, not truncated 2026-10-17 04:36:53 -04:00
lockstep-quic lockstep-quic: correct the root cause — macOS launch context, not a quinn bug 2026-06-27 07:12:43 -04:00