memkit 0.1.0-beta.1

Deterministic, intent-driven memory allocation for systems requiring predictable performance
Documentation
//! Sentinel Mode: Debug Hardening for Memkit.
//!
//! Provides memory poisoning, hazard detection, and trace logging.
//! Enabled via the `sentinel` feature flag.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::fmt;

/// Patterns used for memory poisoning.
pub mod patterns {
    /// Pattern for newly allocated memory (Accumulating).
    pub const ALLOC: u8 = 0xAA;
    /// Pattern for freed memory (Dead).
    pub const FREE: u8 = 0xDD;
}

/// Hazard classification for memory errors.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MkHazard {
    /// Memory leak (allocated but never freed).
    Leak(usize), // bytes leaked
    /// Use after free (accessing freed memory).
    UseAfterFree,
    /// Double free (freeing already freed memory).
    DoubleFree,
    /// Buffer overflow (write past end).
    Overflow,
    /// Unaligned access.
    Unaligned,
}

impl fmt::Display for MkHazard {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            MkHazard::Leak(bytes) => write!(f, "LEAK: {} bytes remain allocated", bytes),
            MkHazard::UseAfterFree => write!(f, "USE-AFTER-FREE: Accessing implementation-freed memory"),
            MkHazard::DoubleFree => write!(f, "DOUBLE-FREE: Attempting to free already freed pointer"),
            MkHazard::Overflow => write!(f, "OVERFLOW: Write beyond allocation boundary"),
            MkHazard::Unaligned => write!(f, "UNALIGNED: Pointer alignment requirement violated"),
        }
    }
}

/// Sentinel manager for tracking allocation validity.
pub struct MkSentinel;

static ACTIVE_ALLOCATIONS: AtomicUsize = AtomicUsize::new(0);
static ACTIVE_BYTES: AtomicUsize = AtomicUsize::new(0);

impl MkSentinel {
    /// Poison memory on allocation.
    #[inline]
    pub unsafe fn poison_alloc(ptr: *mut u8, size: usize) {
        if cfg!(feature = "sentinel") {
            std::ptr::write_bytes(ptr, patterns::ALLOC, size);
            ACTIVE_ALLOCATIONS.fetch_add(1, Ordering::Relaxed);
            ACTIVE_BYTES.fetch_add(size, Ordering::Relaxed);
            
            // Optional: Trace logging
            // eprintln!("[ALLOC] {:p} ({} bytes)", ptr, size);
        }
    }

    /// Poison memory on deallocation.
    #[inline]
    pub unsafe fn poison_free(ptr: *mut u8, size: usize) {
        if cfg!(feature = "sentinel") {
            // Check for double free signature (if we want robust checking, we'd need a map)
            // For now, fast path just poisons.
            std::ptr::write_bytes(ptr, patterns::FREE, size);
            
            ACTIVE_ALLOCATIONS.fetch_sub(1, Ordering::Relaxed);
            ACTIVE_BYTES.fetch_sub(size, Ordering::Relaxed);
            
            // eprintln!("[FREE] {:p} ({} bytes)", ptr, size);
        }
    }
    
    /// Report a hazard.
    pub fn report(hazard: MkHazard, ptr: Option<*const u8>) {
        if cfg!(feature = "sentinel") {
            let addr = ptr.map(|p| format!("{:p}", p)).unwrap_or_else(|| "N/A".to_string());
            eprintln!("\n⚠️  [MEMKIT HAZARD] {} @ {}", hazard, addr);
            
            match hazard {
                MkHazard::UseAfterFree => {
                    eprintln!("   > Hint: Check for dangling references or race conditions.");
                    eprintln!("   > Memory was poisoned with 0x{:02X}", patterns::FREE);
                }
                MkHazard::Leak(_) => {
                    eprintln!("   > Hint: Objects were created but never dropped.");
                }
                _ => {}
            }
        }
    }
    
    /// Verify zero leaks on shutdown.
    pub fn verify_leaks() {
        if cfg!(feature = "sentinel") {
            let info_allocs = ACTIVE_ALLOCATIONS.load(Ordering::Relaxed);
            let info_bytes = ACTIVE_BYTES.load(Ordering::Relaxed);
            
            if info_allocs > 0 {
                Self::report(MkHazard::Leak(info_bytes), None);
                eprintln!("   > {} active allocations remaining.", info_allocs);
            } else {
                eprintln!("\n🛡️  [MEMKIT SENTINEL] Clean shutdown. No leaks detected.");
            }
        }
    }
}