archmeld 1.3.0

Secure, memory-safe, type-safe CLI for multi-format archive extraction, inspection and decompression
Documentation
//! archmeld CLI entry point.

// Upstream transitive dependencies pull in multiple
// crate versions; not fixable at the leaf crate level.
#![allow(clippy::multiple_crate_versions)]

use std::process::ExitCode;

#[cfg(feature = "secure-alloc")]
use mimalloc::MiMalloc;

/// Secure-mode mimalloc (skills/rust-hardening).
///
/// archmeld's whole job is parsing untrusted archive bytes, so the allocator is
/// directly on the attack path. Secure mode adds guard pages between blocks,
/// encodes free-list pointers, and randomises placement — turning several
/// classes of heap corruption from exploitable into a crash.
///
/// **Disabled under `AddressSanitizer`, deliberately.** `ASan` detects heap errors
/// by replacing `malloc`; a custom `#[global_allocator]` routes around those
/// interceptors and, per `skills/rust-asan-ubsan`, "makes `ASan` blind". Leaving
/// mimalloc installed for a sanitizer build would produce a green run that
/// checked almost nothing — the exact false-green this gate exists to prevent.
/// The feature is DEFAULT-ON, so every ordinary build and every release still
/// gets the secure allocator; only `--no-default-features` (the sanitizer
/// job) drops it. `cfg(sanitize)` would be tidier but is nightly-only, and
/// archmeld builds on stable.
#[cfg(feature = "secure-alloc")]
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

fn main() -> ExitCode {
    match archmeld::cli::run() {
        // `run` returns the process exit code so the self-update contract's
        // distinct codes (10 = update available, 3 = refused by policy) survive
        // all the way out of the process. See `skills/rust-self-update`.
        Ok(code) => ExitCode::from(code),
        Err(e) => {
            eprintln!("Error: {e:#}");
            ExitCode::FAILURE
        },
    }
}