Fix: LIBC/HAKMEM mixed allocation crashes (0% → 80% success)
**Problem**: 4T Larson crashed 100% due to "free(): invalid pointer" **Root Causes** (6 bugs found via Task Agent ultrathink): 1. **Invalid magic fallback** (`hak_free_api.inc.h:87`) - When `hdr->magic != HAKMEM_MAGIC`, ptr came from LIBC (no header) - Was calling `free(raw)` where `raw = ptr - HEADER_SIZE` (garbage!) - Fixed: Use `__libc_free(ptr)` instead 2. **BigCache eviction** (`hakmem.c:230`) - Same issue: invalid magic means LIBC allocation - Fixed: Use `__libc_free(ptr)` directly 3. **Malloc wrapper recursion** (`hakmem_internal.h:209`) - `hak_alloc_malloc_impl()` called `malloc()` → wrapper recursion - Fixed: Use `__libc_malloc()` directly 4. **ALLOC_METHOD_MALLOC free** (`hak_free_api.inc.h:106`) - Was calling `free(raw)` → wrapper recursion - Fixed: Use `__libc_free(raw)` directly 5. **fopen/fclose crash** (`hakmem_tiny_superslab.c:131`) - `log_superslab_oom_once()` used `fopen()` → FILE buffer via wrapper - `fclose()` calls `__libc_free()` on HAKMEM-allocated buffer → crash - Fixed: Wrap with `g_hakmem_lock_depth++/--` to force LIBC path 6. **g_hakmem_lock_depth visibility** (`hakmem.c:163`) - Was `static`, needed by hakmem_tiny_superslab.c - Fixed: Remove `static` keyword **Result**: 4T Larson success rate improved 0% → 80% (8/10 runs) ✅ **Remaining**: 20% crash rate still needs investigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -81,8 +81,10 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) {
|
||||
AllocHeader* hdr = (AllocHeader*)raw;
|
||||
if (hdr->magic != HAKMEM_MAGIC) {
|
||||
if (g_invalid_free_log) fprintf(stderr, "[hakmem] ERROR: Invalid magic 0x%X (expected 0x%X)\n", hdr->magic, HAKMEM_MAGIC);
|
||||
// CRITICAL FIX: Free raw (allocated address), not ptr (user pointer after header)
|
||||
if (g_invalid_free_mode) { goto done; } else { free(raw); goto done; }
|
||||
// CRITICAL FIX: When magic is invalid, allocation came from LIBC (NO header)
|
||||
// Therefore ptr IS the allocated address, not raw (ptr - HEADER_SIZE)
|
||||
// MUST use __libc_free to avoid infinite recursion through free() wrapper
|
||||
if (g_invalid_free_mode) { goto done; } else { extern void __libc_free(void*); __libc_free(ptr); goto done; }
|
||||
}
|
||||
if (HAK_ENABLED_CACHE(HAKMEM_FEATURE_BIGCACHE) && hdr->class_bytes >= 2097152) {
|
||||
if (hak_bigcache_put(ptr, hdr->size, hdr->alloc_site)) goto done;
|
||||
@ -96,13 +98,21 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) {
|
||||
switch (hdr->method) {
|
||||
case ALLOC_METHOD_POOL: if (HAK_ENABLED_ALLOC(HAKMEM_FEATURE_POOL)) { hkm_ace_stat_mid_free(); hak_pool_free(ptr, hdr->size, hdr->alloc_site); goto done; } break;
|
||||
case ALLOC_METHOD_L25_POOL: hkm_ace_stat_large_free(); hak_l25_pool_free(ptr, hdr->size, hdr->alloc_site); goto done;
|
||||
case ALLOC_METHOD_MALLOC: hak_free_route_log("malloc_hdr", ptr); free(raw); break;
|
||||
case ALLOC_METHOD_MALLOC:
|
||||
// CRITICAL FIX: raw was allocated with __libc_malloc, so free with __libc_free
|
||||
// Using free(raw) would go through wrapper → infinite recursion
|
||||
hak_free_route_log("malloc_hdr", ptr);
|
||||
extern void __libc_free(void*);
|
||||
__libc_free(raw);
|
||||
break;
|
||||
case ALLOC_METHOD_MMAP:
|
||||
#ifdef __linux__
|
||||
if (HAK_ENABLED_MEMORY(HAKMEM_FEATURE_BATCH_MADVISE) && hdr->size >= BATCH_MIN_SIZE) { hak_batch_add(raw, hdr->size); goto done; }
|
||||
if (hkm_whale_put(raw, hdr->size) != 0) { hkm_sys_munmap(raw, hdr->size); }
|
||||
#else
|
||||
free(raw);
|
||||
// CRITICAL FIX: Same as ALLOC_METHOD_MALLOC
|
||||
extern void __libc_free(void*);
|
||||
__libc_free(raw);
|
||||
#endif
|
||||
break;
|
||||
default: fprintf(stderr, "[hakmem] ERROR: Unknown allocation method: %d\n", hdr->method); break;
|
||||
|
||||
Reference in New Issue
Block a user