| name | rust-adapters-failure |
| description | Fires when a kyzo boundary crossing is about to be hand-rolled instead of built as the matching construct in rust-adapters-success — unwrap/expect/panic! on external input, a hand-indexed byte parser with no bounds check or fuzz target, an unowned grammar rule, a second serialization path for a value that already has one, a reply-inspection function choosing a variant before ordered construction, or an untyped/unnamed refusal with no reason or span. |
Adapters — failure patterns
Ways a boundary crossing gets hand-rolled instead of built as a boundary decode, owned parse rule, wire envelope, or ordered TryFrom lift (rust-adapters-success).
Panic on untrusted input
.unwrap()/.expect() on a parse or lookup driven by external bytes assumes the input is already trusted — exactly the thing a boundary crossing is not.
let tag = Tag::try_from(bytes[0]).unwrap();
Unbounded recursion or allocation
A recursive-descent decoder with no depth bound, or an allocation sized directly from an input-declared length with no validation, lets adversarial input exhaust the stack or the heap.
fn parse_expr(bytes: &[u8]) -> Expr {
}
let mut buf = Vec::with_capacity(declared_len);
Second serialization path
A hand-written encode/decode that duplicates what the canonical encoding (rust-order-success) or an existing wire envelope already does creates a second byte authority for the same value — forbidden outright, never a case-by-case judgment call.
Reply-inspection before construction
A function that peeks at a foreign reply's shape or fields to decide which variant to build restates the selection an ordered TryFrom chain should perform through construction itself.
fn classify(raw: &RawReply) -> ReplyKind {
if raw.error_code.is_some() { ReplyKind::Error } else { ReplyKind::Ok }
}
Untyped error at a boundary
A String/anyhow::Error-typed refusal with no structured reason or span forces every caller to string-match instead of matching on a typed variant.
fn decode(bytes: &[u8]) -> Result<Value, String> {
Unowned grammar rule
A grammar rule with no corresponding success type and no corresponding typed refusal variant is a case nothing in the error type or the domain accounts for.
Decoder shipped without a fuzz target
Adversarial totality is proven by fuzzing, never by review. A decoder (or parse lift over untrusted bytes) with no fuzz target is a totality claim, not a fact.
Sentinel default on parse failure
A .unwrap_or_default()/.unwrap_or(fallback) on a fallible foreign parse manufactures a value nothing in the domain actually proved, silently masking a refusal as success.
let quantity = Quantity::try_from(raw_field).unwrap_or(Quantity::ZERO);
Standing ban: unsafe
#![forbid(unsafe_code)] applies repo-wide across every rust-* group. unsafe is never a legal shortcut here — not to transmute untrusted bytes directly into a typed value, not to skip bounds checks in a decoder for speed. If a boundary crossing seems to need unsafe to exist, the construct is wrong, not the ban.