Skip to content

Latest commit

 

History

History
97 lines (83 loc) · 4.79 KB

File metadata and controls

97 lines (83 loc) · 4.79 KB

Panic Policy

base64-ng treats runtime panics in public scalar APIs as denial-of-service risk. Public encode, decode, validation, length, in-place, streaming, and profile APIs should report malformed input and size failures with Result or Option rather than unwinding.

This policy is enforced by:

scripts/validate-panic-policy.sh

The validator scans non-test source before Kani/test-only modules and fails on new panic!, unreachable!, assert!, .unwrap(), or .expect() sites unless they match an allowlisted pattern documented here. debug_assert! is allowed for internal invariant documentation because it is not a release-mode panic surface. Root src/*_tests.rs files are exempt only when the validator can also prove that each file is declared behind #[cfg(test)] in src/lib.rs; the filename convention alone is not enough. Remaining bounded indexing invariants are documented in INVARIANTS.md.

Allowed Non-Test Sites

The current reviewed exceptions are:

  • Engine::encode_array may panic during const evaluation when the caller supplies an output array length that does not match the compile-time encoded length, or when that const length calculation overflows. This is documented as a const-array API contract and is not used for runtime untrusted length metadata. Calling it at runtime with a mismatched const output length can also unwind; do not route attacker-controlled sizing decisions through this API.
  • LineWrap::new may panic when line_len == 0. It is intended for fixed, trusted values and profile constants. This remains true when the const fn is called at runtime: passing attacker-controlled or externally supplied zero values can unwind. Use LineWrap::checked_new when a line length comes from runtime configuration, file metadata, network input, a database row, or another untrusted source.
  • ExposedEncodedArray::from_array and ExposedDecodedArray::from_array may panic when a caller supplies len > CAP. These constructors are explicit escape-hatch wrappers around caller-provided arrays; callers must pass the actual visible initialized length.
  • Internal remainder matches use _ => unreachable!() after matching len % 3 or equivalent remainder values. The preceding arithmetic bounds make those arms unreachable.
  • String::from_utf8 conversions after Base64 encoding use a reviewed unreachable! because crate encoders produce ASCII bytes by construction. Secret string conversions do not use this exception; if an already validated secret byte vector somehow fails UTF-8 conversion, the helper wipes the bytes and returns an empty string rather than panicking or using unchecked UTF-8.
  • encode_vec_infallible, encode_string_infallible, profile variants, and the top-level encode_infallible may panic if the underlying fallible encode API returns an error, including encoded length overflow. On 32-bit targets, inputs larger than roughly 1.5 GiB can overflow the encoded length. These helpers are explicit convenience APIs for ordinary byte-to-Base64 paths where every byte sequence is encodable and a failure indicates an internal length/allocation invariant break. Do not use them for untrusted length metadata, constrained allocation environments, or code paths that require recoverable errors; use the fallible encode helpers instead.
  • Core stream and Tokio writer get_ref, get_mut, and into_inner internal helpers use unreachable! if a wrapper has already consumed its inner value. The public API consumes self for into_inner/finish, so this state is not reachable through safe public calls.

Test code, doctest examples, and Kani proof harnesses may use unwrap, expect, or panic-like macros when they are asserting expected outcomes.

Caller Guidance

For untrusted input and untrusted length metadata, prefer:

  • checked_encoded_len
  • encoded_len
  • checked_wrapped_encoded_len
  • wrapped_encoded_len
  • decoded_capacity
  • decoded_len
  • caller-owned encode_slice and decode_slice
  • in-place APIs that return Result

Compile-time array encoding is intentionally stricter: an incorrect destination array length fails const evaluation so the mistake cannot silently produce a truncated or oversized static value.

Use Engine::encode_array for fixed-size static data and compile-time checked arrays. For runtime data, especially data sized from packet headers, file metadata, network frames, or other untrusted sources, use checked length helpers and caller-owned slice APIs instead.

Compile-time array decoding is intentionally Result-based: Engine::decode_array reports malformed input, padding errors, and undersized output arrays with DecodeError rather than adding another reviewed panic exception. It is still a strict decoder, not a constant-time-oriented secret decoder.