Subject
block-buffer is a small, no_std Rust crate from the RustCrypto organisation that provides a fixed-size buffer for block-oriented data processing. It is the staging buffer used by most RustCrypto hash and stream/block primitives (SHA-1, SHA-2, BLAKE2, AES-CTR, and similar) to accumulate input until a full block is available, then call a user-supplied compression function on each block. The crate exposes two kinds of buffer (EagerBuffer, position in 0..BlockSize; LazyBuffer, position in 0..=BlockSize), Merkle-Damgård-style padding helpers (digest_pad, len64_padding_be/le, len128_padding_be), and a set_data helper for output-block-generating primitives.
Methodology
The published crate contents were compared against the upstream Git repository (RustCrypto/utils, at the commit recorded in .cargo_vcs_info.json, subfolder block-buffer/) using diff. The two source files (src/lib.rs, src/sealed.rs, ~420 lines combined) were read in full. The integration tests in tests/mod.rs (~200 lines) were read in full. The CI workflow at .github/workflows/block-buffer.yml in the VCS repository was reviewed to understand what is exercised on each commit. Every unsafe block was reviewed for soundness, with particular attention to the layout assumption it makes about generic_array::GenericArray<u8, N> and to the invariants it relies on for pos and BlockSize. The crate dependency graph (a single dependency on generic-array = "0.14") was reviewed against the dependency uses in code.
Results
The published crate matches the upstream VCS repository byte-for-byte in source and tests; the differences are confined to Cargo's automatic normalisation of Cargo.toml, the presence of Cargo.toml.orig, and the addition of .cargo_vcs_info.json.
The crate ships no binary or other non-textual artefacts, justifying has-binaries. There is no build.rs and no proc_macro declaration in Cargo.toml, justifying has-build-exec and has-install-exec. Source code uses only core and generic_array, with no I/O, no process spawning, no JIT or interpreter, no concurrency primitives, and no cryptography of its own, justifying uses-crypto, uses-exec, uses-jit, uses-interpreter, impl-crypto, impl-parser, impl-interpreter, impl-jit, impl-protocol, impl-algorithm, and impl-concurrency. The padding helpers implement the canonical Merkle-Damgård length-encoding pattern but do not themselves hash anything; they merely format bytes and call back into a user-supplied compression function.
The crate contains four unsafe blocks (one in src/lib.rs:200 using unreachable_unchecked to elide bounds checks, one in src/lib.rs:348 and two in src/sealed.rs reinterpreting &[u8]/&mut [u8] as block slices), justifying uses-unsafe. Each carries a SAFETY comment (justifying unsafe-documented) and exists only to elide bounds checks or panic branches that the optimiser cannot otherwise remove, which is a legitimate minimal use (justifying unsafe-minimal). The soundness of the slice-reinterpretation casts depends on GenericArray<u8, N> having the same layout as [u8; N], which is a documented and widely-relied-upon invariant of generic-array 0.14; combined with the BlockSize > 0 runtime check in Default::default and try_new (added in 0.10.4 in response to the unsoundness fixed in RustCrypto/utils#844) and the type-level constraint that BlockSize < 256, the unsafe blocks are sound (justifying unsafe-safe). The crate also implements a simple block-oriented data structure (justifying impl-datastructure); its invariants on pos are upheld by all constructors and internal mutators, its operations are bounds-correct, and it has no advertised time/space bounds beyond O(1) buffer operations and O(n) data shuffling, all of which hold trivially (justifying datastructure-impl-safe, datastructure-impl-correct, datastructure-impl-bounds).
Tests: tests/mod.rs contains five integration tests covering eager and lazy digest_blocks, set_data, the BE/LE 64-bit and 128-bit padding helpers, and try_new bounds. There are no inline #[cfg(test)] unit tests in the source files, justifying has-unit-tests = false, but the file-level test suite covers the public API, justifying has-integration-tests. There are no fuzz tests, no property tests, and no Miri job in CI, justifying has-fuzz-tests = false, has-property-tests = false, and unsafe-tested = false (see FINDING-2). The fixed-input test coverage is sufficient to assert datastructure-impl-tested at this granularity, but additional randomized testing would meaningfully raise confidence.
Two low-severity findings were recorded. FINDING-1 notes that try_new is declared as Result-returning but panics on BlockSize == 0 instead of returning Err; this is a minor API inconsistency, not a real-world hazard, because zero block sizes are a type-level misconfiguration. FINDING-2 notes the absence of randomized testing for the unsafe code paths.
No malicious code, data exfiltration, time-bombs, or other suspicious behaviour was observed (justifying is-benign).
Conclusion
block-buffer 0.10.4 is a small, focused utility crate. Its unsafe code is minimal, documented, and sound given the established layout guarantees of generic-array and the runtime guard against zero block sizes added in this very release. The two findings are low-severity quality observations.