Subject
anyhow 1.0.102, authored by David Tolnay, is a Rust error-handling library. It exposes anyhow::Error, a single-word owning pointer to any dyn StdError + Send + Sync + 'static value, along with anyhow::Result<T>, the Context trait for attaching contextual messages, and the anyhow!, bail!, and ensure! macros. The crate targets both std (default) and no_std (with a global allocator) environments. It has no runtime dependencies.
Methodology
All source files under contents/src/ were read in full: lib.rs, error.rs, ptr.rs, backtrace.rs, chain.rs, context.rs, ensure.rs, fmt.rs, kind.rs, macros.rs, nightly.rs, wrapper.rs (3918 lines total). build.rs and Cargo.toml/Cargo.toml.orig were also read in full. README.md was reviewed for context.
Source surveys were run for unsafe blocks, FFI, network, filesystem, process execution, environment variables, cryptographic patterns, RNG, and concurrency. A diff -rq contents vcs was run to verify byte-equivalence between the published crate and the VCS checkout. Tools: openvet 0.6.0, grep, diff, git.
Results
The diff between contents/ and vcs/ shows only expected differences: Cargo.toml normalisation, .cargo_vcs_info.json, Cargo.lock, Cargo.toml.orig, and test files present in VCS but not published. No source file diverges between published and VCS. is-benign: no obfuscated code, no network endpoints, no base64 blobs, no telemetry.
The crate has no runtime dependencies and no I/O. Network (uses-network=false), filesystem (uses-filesystem=false), environment (uses-environment=false), concurrency (uses-concurrency=false), process execution (uses-exec=false), JIT (uses-jit=false), interpreter (uses-interpreter=false), and cryptographic (uses-crypto=false) patterns are all absent from the runtime source. No pre-compiled binaries are included (has-binaries=false) and no install-time execution is configured (has-install-exec=false).
The crate implements no cryptographic algorithms (impl-crypto=false), no parser (impl-parser=false), no interpreter (impl-interpreter=false), no JIT (impl-jit=false), no protocol (impl-protocol=false), no data structure (impl-datastructure=false), no algorithm (impl-algorithm=false), and no concurrency primitives (impl-concurrency=false).
The build.rs script (has-build-exec=true) invokes rustc on a probe file to detect nightly error_generic_member_access support. It reads only Cargo-standard environment variables, writes only to OUT_DIR/probe, makes no network requests, and emits cargo:rustc-cfg directives (build-exec-safe=true, build-exec-no-network=true, build-exec-no-write-out=true, build-exec-minimal=true, build-exec-deterministic=true).
The crate uses unsafe extensively (uses-unsafe=true) to implement its type-erasure design. Error stores a thin Own<ErrorImpl> pointer (a #[repr(transparent)] wrapper around NonNull). ErrorImpl<E> is #[repr(C)] with vtable first, so error.rs's vtable() function can read the vtable via a raw pointer cast to the first field. Every vtable function pointer in ErrorVTable is unsafe fn and each is documented with a // Safety: requires layout of *e to match ErrorImpl<E> comment. Call sites in error.rs carry their own // Safety: annotations. The invariants hold: casts from ErrorImpl to ErrorImpl<E> are sound because the vtable pointers are always populated at the same construction step as the E value, and #[repr(C)] ensures stable field offsets. The downcast paths compare TypeId before any pointer cast, preventing unsound casts to the wrong type. The ManuallyDrop pattern in downcast correctly separates value extraction from deallocation. The crate's unsafe is unsafe-minimal=true and unsafe-safe=true.
However, src/ptr.rs and src/ensure.rs contain unsafe blocks without // SAFETY: comments (unsafe-documented=false). The unsafe impl Send and unsafe impl Sync for Own<T> in ptr.rs (lines 13-15) have no justification comment; soundness depends on E: Send + Sync being enforced at Error::construct, which is not stated at the impl site. The Buf::as_str and write_str methods in ensure.rs use str::from_utf8_unchecked, slice::from_raw_parts, and copy_nonoverlapping without safety annotations. A quality finding was raised.
unsafe-tested=false: the published package contains no fuzzer or Miri CI configuration, and no fuzz tests (has-fuzz-tests=false) or property tests (has-property-tests=false) are present.
Testing: the crate ships 73 #[test] functions across 14 integration test files (has-integration-tests=true) covering downcasting, chain traversal, context, formatting, FFI, macros, repr, and more. Unit tests appear in src/fmt.rs (has-unit-tests=true).
Conclusion
anyhow 1.0.102 implements a type-erased error wrapper using a hand-rolled vtable for safe thin-pointer erasure. The design is sound: all pointer casts are guarded by TypeId comparison or enforced at construction, #[repr(C)] is used to fix field offsets that the vtable functions depend on, and the scope of unsafe is limited to the type-erasure mechanism and a small buffer in ensure.rs. One low-severity quality finding was raised: src/ptr.rs and src/ensure.rs contain unsafe blocks without // SAFETY: comments, unlike src/error.rs where every unsafe block is annotated. The crate has no runtime dependencies and no I/O.