diff --git a/core/box/hak_alloc_api.inc.h b/core/box/hak_alloc_api.inc.h index 8228b00d..c5869bdd 100644 --- a/core/box/hak_alloc_api.inc.h +++ b/core/box/hak_alloc_api.inc.h @@ -29,7 +29,24 @@ inline void* hak_alloc_at(size_t size, hak_callsite_t site) { HKM_TIME_END(HKM_CAT_TINY_ALLOC, t_tiny); #endif if (tiny_ptr) { hkm_ace_track_alloc(); return tiny_ptr; } + + // Phase 7: If Tiny rejects size <= TINY_MAX_SIZE (e.g., 1024B needs header), + // skip Mid/ACE and route directly to malloc fallback +#if HAKMEM_TINY_HEADER_CLASSIDX + if (size <= TINY_MAX_SIZE) { + // Tiny rejected this size (likely 1024B), use malloc directly + static int log_count = 0; + if (log_count < 3) { + fprintf(stderr, "[DEBUG] Phase 7: tiny_alloc(%zu) rejected, using malloc fallback\n", size); + log_count++; + } + void* fallback_ptr = hak_alloc_malloc_impl(size); + if (fallback_ptr) return fallback_ptr; + // If malloc fails, continue to other fallbacks below + } +#else static int log_count = 0; if (log_count < 3) { fprintf(stderr, "[DEBUG] tiny_alloc(%zu) returned NULL, falling back\n", size); log_count++; } +#endif } hkm_size_hist_record(size); diff --git a/core/tiny_free_fast_v2.inc.h b/core/tiny_free_fast_v2.inc.h index 4c4dde96..06d78224 100644 --- a/core/tiny_free_fast_v2.inc.h +++ b/core/tiny_free_fast_v2.inc.h @@ -53,13 +53,12 @@ static inline int hak_tiny_free_fast_v2(void* ptr) { // 1. Read class_idx from header (2-3 cycles, L1 hit) int class_idx = tiny_region_id_read_header(ptr); -#if !HAKMEM_BUILD_RELEASE - // Debug: Validate header + // CRITICAL: Always validate header (even in release) + // Reason: Mid/Large allocations don't have headers, reading ptr-1 would SEGV if (__builtin_expect(class_idx < 0, 0)) { // Invalid header - route to slow path (non-header allocation) return 0; } -#endif // 2. Check TLS freelist capacity (optional, for bounded cache) // Note: Can be disabled in release for maximum speed diff --git a/core/tiny_region_id.h b/core/tiny_region_id.h index a9c0b31c..95161572 100644 --- a/core/tiny_region_id.h +++ b/core/tiny_region_id.h @@ -67,21 +67,27 @@ static inline int tiny_region_id_read_header(void* ptr) { if (!ptr) return -1; uint8_t* header_ptr = (uint8_t*)ptr - 1; + uint8_t header = *header_ptr; -#if !HAKMEM_BUILD_RELEASE - // Debug: Validate magic byte + // CRITICAL: Always validate magic byte (even in release builds) + // Reason: Mid/Large allocations don't have headers, must detect and reject them uint8_t magic = header & 0xF0; if (magic != HEADER_MAGIC) { - // Invalid header - likely non-header allocation + // Invalid header - likely non-header allocation (Mid/Large) + static int invalid_count = 0; + if (invalid_count < 5) { + fprintf(stderr, "[HEADER_INVALID] ptr=%p, header=%02x, magic=%02x (expected %02x)\n", + ptr, header, magic, HEADER_MAGIC); + invalid_count++; + } return -1; } -#endif int class_idx = (int)(header & HEADER_CLASS_MASK); -#if !HAKMEM_BUILD_RELEASE - // Debug: Validate class_idx range + // CRITICAL: Always validate class_idx range (even in release builds) + // Reason: Corrupted headers could cause out-of-bounds array access #ifndef TINY_NUM_CLASSES #define TINY_NUM_CLASSES 8 #endif @@ -89,7 +95,6 @@ static inline int tiny_region_id_read_header(void* ptr) { // Corrupted header return -1; } -#endif return class_idx; }