Phase E1-CORRECT: Fix USER/BASE pointer conversion bugs in slab_index_for calls
CRITICAL BUG FIX: Phase E1 introduced 1-byte headers for ALL size classes (C0-C7), changing the pointer contract. However, many locations still called slab_index_for() with USER pointers (storage+1) instead of BASE pointers (storage), causing off-by-one slab index calculations that corrupted memory. Root Cause: - USER pointer = BASE + 1 (returned by malloc, points past header) - BASE pointer = storage start (where 1-byte header is written) - slab_index_for() expects BASE pointer for correct slab boundary calculations - Passing USER pointer → wrong slab_idx → wrong metadata → freelist corruption Impact Before Fix: - bench_random_mixed crashes at ~14K iterations with SEGV - Massive C7 alignment check failures (wrong slab classification) - Memory corruption from writing to wrong slab freelists Fixes Applied (8 locations): 1. core/hakmem_tiny_free.inc:137 - Added USER→BASE conversion before slab_index_for() 2. core/hakmem_tiny_ultra_simple.inc:148 - Added USER→BASE conversion before slab_index_for() 3. core/tiny_free_fast.inc.h:220 - Added USER→BASE conversion before slab_index_for() 4-5. core/tiny_free_magazine.inc.h:126,315 - Added USER→BASE conversion before slab_index_for() (2 locations) 6. core/box/free_local_box.c:14,22,62 - Added USER→BASE conversion before slab_index_for() - Fixed delta calculation to use BASE instead of USER - Fixed debug logging to use BASE instead of USER 7. core/hakmem_tiny.c:448,460,473 (tiny_debug_track_alloc_ret) - Added USER→BASE conversion before slab_index_for() (2 calls) - Fixed delta calculation to use BASE instead of USER - This function is called on EVERY allocation in debug builds Results After Fix: ✅ bench_random_mixed stable up to 66K iterations (~4.7x improvement) ✅ C7 alignment check failures eliminated (was: 100% failure rate) ✅ Front Gate "Unknown" classification dropped to 0% (was: 1.67%) ✅ No segfaults for workloads up to ~33K allocations Remaining Issue: ❌ Segfault still occurs at iteration 66152 (allocs=33137, frees=33014) - Different bug from USER/BASE conversion issues - Likely capacity/boundary condition (further investigation needed) Testing: - bench_random_mixed_hakmem 1K-66K iterations: PASS - bench_random_mixed_hakmem 67K+ iterations: FAIL (different bug) - bench_fixed_size_hakmem 200K iterations: PASS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -440,12 +440,14 @@ extern int g_use_superslab;
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
static inline void tiny_debug_track_alloc_ret(int cls, void* ptr) {
|
||||
if (!ptr) return;
|
||||
// ✅ Phase E1-CORRECT: ptr is USER pointer, convert to BASE
|
||||
void* base_ptr = ptr ? (void*)((uint8_t*)ptr - 1) : NULL;
|
||||
if (g_use_superslab && __builtin_expect(tiny_refill_failfast_level() >= 2, 0)) {
|
||||
SuperSlab* ss = hak_super_lookup(ptr);
|
||||
if (!(ss && ss->magic == SUPERSLAB_MAGIC)) {
|
||||
tiny_failfast_abort_ptr("alloc_ret_lookup", ss, -1, ptr, "lookup_fail");
|
||||
} else {
|
||||
int slab_idx = slab_index_for(ss, ptr);
|
||||
int slab_idx = slab_index_for(ss, base_ptr);
|
||||
if (slab_idx < 0) {
|
||||
tiny_failfast_abort_ptr("alloc_ret_slabidx", ss, slab_idx, ptr, "slab_idx_mismatch");
|
||||
} else {
|
||||
@ -455,7 +457,7 @@ static inline void tiny_debug_track_alloc_ret(int cls, void* ptr) {
|
||||
}
|
||||
size_t blk = g_tiny_class_sizes[cls];
|
||||
uintptr_t base = (uintptr_t)tiny_slab_base_for(ss, slab_idx);
|
||||
uintptr_t delta = (uintptr_t)ptr - base;
|
||||
uintptr_t delta = (uintptr_t)base_ptr - base;
|
||||
if (blk == 0 || (delta % blk) != 0) {
|
||||
tiny_failfast_abort_ptr("alloc_ret_align", ss, slab_idx, ptr, "misaligned");
|
||||
} else if (delta / blk >= ss->slabs[slab_idx].capacity) {
|
||||
@ -468,7 +470,7 @@ static inline void tiny_debug_track_alloc_ret(int cls, void* ptr) {
|
||||
if (!g_use_superslab) return;
|
||||
SuperSlab* ss = hak_super_lookup(ptr);
|
||||
if (!(ss && ss->magic == SUPERSLAB_MAGIC)) return;
|
||||
int slab_idx = slab_index_for(ss, ptr);
|
||||
int slab_idx = slab_index_for(ss, base_ptr);
|
||||
if (slab_idx >= 0) {
|
||||
tiny_remote_track_on_alloc(ss, slab_idx, ptr, "alloc_ret", 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user