Phase 7-1.1: Fix 1024B crash (header validation + malloc fallback)

Fixed critical bugs preventing Phase 7 from working with 1024B allocations.

## Bug Fixes (by Task Agent Ultrathink)

1. **Header Validation Missing in Release Builds**
   - `core/tiny_region_id.h:73-97` - Removed `#if !HAKMEM_BUILD_RELEASE`
   - Always validate magic byte and class_idx (prevents SEGV on Mid/Large)

2. **1024B Malloc Fallback Missing**
   - `core/box/hak_alloc_api.inc.h:35-49` - Direct fallback to malloc
   - Phase 7 rejects 1024B (needs header) → skip ACE → use malloc

## Test Results

| Test | Result |
|------|--------|
| 128B, 512B, 1023B (Tiny) | +39%~+436%  |
| 1024B only (100 allocs) | 100% success  |
| Mixed 128B+1024B (200) | 100% success  |
| bench_random_mixed 1024B | Still crashes  |

## Known Issue

`bench_random_mixed` with 1024B still crashes (intermittent SEGV).
Simple tests pass, suggesting issue is with complex allocation patterns.
Investigation pending.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Task Agent Ultrathink
This commit is contained in:
Moe Charm (CI)
2025-11-08 03:35:07 +09:00
parent 6b1382959c
commit 48fadea590
3 changed files with 31 additions and 10 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;
}