Subject
base64 is a no-std-friendly Rust library for encoding and decoding the
base64 transfer encoding (RFC 4648). It exposes an Engine trait and a
table-driven GeneralPurpose implementation parameterised by Alphabet
and GeneralPurposeConfig (padding behaviour, trailing-bits tolerance,
padding mode). The crate ships in-memory APIs (encode/decode to
String/Vec, slice-in/slice-out variants), streaming wrappers
(read::DecoderReader, write::EncoderWriter, EncoderStringWriter),
and a display::Base64Display fmt::Display adapter. Six pre-defined
alphabets (STANDARD, URL_SAFE, CRYPT, BCRYPT, IMAP_MUTF7, BIN_HEX) are
provided as constants.
Methodology
The published crate contents were compared against the upstream Git
repository at the commit recorded in .cargo_vcs_info.json using
diff. All 21 source files in src/ (~6500 lines including the
templated test harness) were read in full, along with the
integration tests in tests/, the example in examples/, and the
fuzzer entry points kept in the VCS-only fuzz/ directory. Manifest
metadata, the clippy.toml, the .gitignore, and the crate-level
deny/forbid attributes were inspected to bound the crate's runtime
surface.
The review focused on parser/encoder soundness (panic-freedom on
adversarial input, correct error reporting, no out-of-bounds access),
adherence to RFC 4648, malleability handling (non-canonical padding
and trailing bits), and the streaming decoder's behaviour at
arbitrary buffer boundaries.
Results
The diff between the published crate and the upstream commit shows
only cargo's standard Cargo.toml normalisation, the auto-generated
.cargo_vcs_info.json, and a Cargo.lock cargo adds on publish; the
upstream fuzz/ workspace is excluded from the published crate,
which is normal. No source files differ.
The crate sets #![forbid(unsafe_code)] at the crate root, which
rules out unsafe blocks, FFI, and raw-pointer code throughout the
library and supports uses-unsafe. The manifest declares no
build.rs, no [lib] proc-macro = true, no [build-dependencies],
and no runtime dependencies, justifying has-build-exec and
has-install-exec, and has-binaries (the crate ships only Rust
source, two licence files, the SVG sponsor icon, and the standard
markdown documentation). The codebase performs no network, file,
process, or environment access (justifying uses-network,
uses-filesystem, uses-exec, uses-environment), spawns no threads
and uses no async runtime (justifying uses-concurrency); there is no dynamic code execution, JIT, or embedded interpreter (justifying uses-jit and uses-interpreter), and does
not implement or call into any cryptographic primitive (justifying
uses-crypto and impl-crypto). The GeneralPurpose engine
documents that it is not constant-time and steers cryptographic-key
use cases to a forthcoming constant-time engine.
The decoder is a table-driven parser that validates each input byte
against a 256-entry decode_table and reports the offending offset
on the first invalid byte; the final-quad handler in
decode_suffix.rs enumerates the four classes of malformed padding
and uses a bit mask to detect non-canonical trailing bits per
DecodePaddingMode. All buffer accesses use safe slice indexing,
and encoded_len performs its arithmetic with checked_mul /
checked_add, returning None on usize overflow (the crate-level
docs document the corresponding panic). The streaming
DecoderReader re-bases error offsets onto the cumulative
input_consumed_len and remembers the first padding byte seen so
that errors discovered in a later chunk are reported at the
position users would expect from non-streaming decode. Together
these support parser-impl-safe, parser-impl-correct,
algorithm-impl-safe, algorithm-impl-correct, and
algorithm-impl-bounds (the crate implements the RFC 4648 base64
codec, justifying impl-parser and impl-algorithm, and does not
implement a data structure, interpreter, JIT, protocol, or any
concurrency primitive, justifying impl-datastructure,
impl-interpreter, impl-jit, impl-protocol, and impl-concurrency) (the encoder and decoder are strictly linear
in input length and allocate at most a single output buffer).
Testing is comprehensive. The engine test suite uses
rstest_reuse to fan every test across three EngineWrapper
implementations (production GeneralPurpose, a deliberately-simple
Naive reference, and DecoderReader), giving a strong
cross-validation property: each behavioural test runs against the
naive implementation as a reference oracle. The suite covers RFC
4648 vectors, randomised roundtrip (~10000 inputs of up to 1000
bytes), exhaustive last-symbol validity for the
two-and three-symbol-suffix cases, malleability across all padding
modes, slice sizing edge cases, and the streaming reader's
behaviour across all input-split positions. The crate ships in-module #[cfg(test)] blocks throughout src/
and an extensive tests/ directory exercising the public API,
justifying has-unit-tests and has-integration-tests. Four
cargo-fuzz fuzzers in the upstream repo
(roundtrip, roundtrip_no_pad, roundtrip_random_config,
decode_random) provide ongoing randomised testing, justifying
has-fuzz-tests and supporting parser-impl-tested and
algorithm-impl-tested. The crate has no
dedicated proptest/quickcheck property tests, hence
has-property-tests is false; the rstest-driven and randomised
tests cover similar ground in practice.
No findings were raised. No malicious patterns, obfuscation, or
unexpected side effects were observed, justifying is-benign.
Conclusion
base64 is a small, focused, audit-friendly library that does only
what its name says. The crate has no runtime dependencies, no
unsafe code, no build-time or install-time code execution, no IO
surface, and a thorough cross-validated test suite. It is safe to
deploy.