Fix critical type safety bug: enforce hak_base_ptr_t in tiny_alloc_fast_push
Root cause: Functions tiny_alloc_fast_push() and front_gate_push_tls() accepted void* instead of hak_base_ptr_t, allowing implicit conversion of USER pointers to BASE pointers. This caused memory corruption in TLS SLL operations. Changes: - core/tiny_alloc_fast.inc.h:879 - Change parameter type to hak_base_ptr_t - core/tiny_alloc_fast_push.c:17 - Change parameter type to hak_base_ptr_t - core/tiny_free_fast.inc.h:46 - Update extern declaration - core/box/front_gate_box.h:15 - Change parameter type to hak_base_ptr_t - core/box/front_gate_box.c:68 - Change parameter type to hak_base_ptr_t - core/box/tls_sll_box.h - Add misaligned next pointer guard and enhanced logging Result: Zero misaligned next pointer detections in tests. Corruption eliminated. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -65,7 +65,7 @@ void front_gate_after_refill(int class_idx, int refilled_count) {
|
||||
}
|
||||
}
|
||||
|
||||
void front_gate_push_tls(int class_idx, void* ptr) {
|
||||
void front_gate_push_tls(int class_idx, hak_base_ptr_t ptr) {
|
||||
// IMPORTANT: ptr is ALREADY a BASE pointer (callers from tiny_free_fast.inc.h
|
||||
// convert USER→BASE before calling tiny_alloc_fast_push)
|
||||
// Do NOT double-convert! Pass directly to TLS SLL which expects BASE.
|
||||
|
||||
@ -12,5 +12,5 @@ int front_gate_try_pop(int class_idx, void** out_ptr);
|
||||
void front_gate_after_refill(int class_idx, int refilled_count);
|
||||
|
||||
// Push a block to TLS freelist (SLL). Used by free fast path.
|
||||
void front_gate_push_tls(int class_idx, void* ptr);
|
||||
void front_gate_push_tls(int class_idx, hak_base_ptr_t ptr);
|
||||
|
||||
|
||||
@ -953,6 +953,42 @@ static inline bool tls_sll_pop_impl(int class_idx, hak_base_ptr_t* out, const ch
|
||||
hak_base_ptr_t next = HAK_BASE_FROM_RAW(raw_next);
|
||||
tls_sll_diag_next(class_idx, base, next, "pop_next");
|
||||
|
||||
// Optional: misalignment guard to catch BASE/USER混入由来のnextズレ (triage用)
|
||||
do {
|
||||
static int g_misalign_guard = -1;
|
||||
if (__builtin_expect(g_misalign_guard == -1, 0)) {
|
||||
const char* e = getenv("HAKMEM_TINY_SLL_MISALIGN_GUARD");
|
||||
g_misalign_guard = (e && *e && *e != '0') ? 1 : 0;
|
||||
}
|
||||
if (!__builtin_expect(g_misalign_guard, 0)) break;
|
||||
if (hak_base_is_null(next)) break;
|
||||
extern const size_t g_tiny_class_sizes[];
|
||||
size_t stride = (class_idx >= 0 && class_idx < TINY_NUM_CLASSES)
|
||||
? g_tiny_class_sizes[class_idx]
|
||||
: 0;
|
||||
if (stride == 0) break;
|
||||
uintptr_t next_addr = (uintptr_t)raw_next;
|
||||
if ((next_addr % stride) != 0) {
|
||||
static _Atomic uint32_t g_misalign_shot = 0;
|
||||
uint32_t shot = atomic_fetch_add_explicit(&g_misalign_shot, 1, memory_order_relaxed);
|
||||
if (shot < 8) {
|
||||
fprintf(stderr,
|
||||
"[TLS_SLL_POP_MISALIGNED_NEXT] shot=%u cls=%d base=%p next=%p stride=%zu where=%s last_writer=%s\n",
|
||||
shot + 1,
|
||||
class_idx,
|
||||
raw_base,
|
||||
raw_next,
|
||||
stride,
|
||||
where ? where : "(null)",
|
||||
g_tls_sll_last_writer[class_idx] ? g_tls_sll_last_writer[class_idx] : "(null)");
|
||||
}
|
||||
// Drop list defensively; nextが壊れているのでheadごと破棄
|
||||
tls_sll_set_head(class_idx, HAK_BASE_FROM_RAW(NULL), "pop_next_misaligned");
|
||||
g_tls_sll[class_idx].count = 0;
|
||||
return false;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
// Validate next pointer before installing as new head.
|
||||
if (!hak_base_is_null(next)) {
|
||||
SuperSlab* next_ss = hak_super_lookup(raw_next);
|
||||
@ -1007,7 +1043,7 @@ static inline bool tls_sll_pop_impl(int class_idx, hak_base_ptr_t* out, const ch
|
||||
}
|
||||
|
||||
// Clear next inside popped node to avoid stale-chain issues.
|
||||
tiny_next_write(class_idx, raw_base, NULL);
|
||||
PTR_NEXT_WRITE("tls_pop_clear", class_idx, raw_base, 0, NULL);
|
||||
|
||||
// Release SuperSlab pin now that node left TLS SLL
|
||||
do {
|
||||
|
||||
@ -876,7 +876,7 @@ static inline void* tiny_alloc_fast(size_t size) {
|
||||
//
|
||||
// Invariant: ptr must belong to current thread (no ownership check here)
|
||||
// Caller (Box 6) is responsible for ownership verification
|
||||
static inline void tiny_alloc_fast_push(int class_idx, void* ptr) {
|
||||
static inline void tiny_alloc_fast_push(int class_idx, hak_base_ptr_t ptr) {
|
||||
#ifdef HAKMEM_TINY_FRONT_GATE_BOX
|
||||
front_gate_push_tls(class_idx, ptr);
|
||||
#else
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include "box/tls_sll_box.h"
|
||||
#include "box/front_gate_box.h"
|
||||
|
||||
void tiny_alloc_fast_push(int class_idx, void* ptr) {
|
||||
void tiny_alloc_fast_push(int class_idx, hak_base_ptr_t ptr) {
|
||||
#ifdef HAKMEM_TINY_FRONT_GATE_BOX
|
||||
// When FrontGate Box is enabled, delegate to its TLS push helper.
|
||||
front_gate_push_tls(class_idx, ptr);
|
||||
|
||||
@ -43,7 +43,7 @@ extern __thread TinyTLSSLL g_tls_sll[TINY_NUM_CLASSES];
|
||||
extern __thread TinyTLSList g_tls_lists[TINY_NUM_CLASSES];
|
||||
|
||||
// Box 5 helper (TLS push)
|
||||
extern void tiny_alloc_fast_push(int class_idx, void* ptr);
|
||||
extern void tiny_alloc_fast_push(int class_idx, hak_base_ptr_t ptr);
|
||||
|
||||
// ========== Ownership Check ==========
|
||||
|
||||
|
||||
Reference in New Issue
Block a user