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
|
// IMPORTANT: ptr is ALREADY a BASE pointer (callers from tiny_free_fast.inc.h
|
||||||
// convert USER→BASE before calling tiny_alloc_fast_push)
|
// convert USER→BASE before calling tiny_alloc_fast_push)
|
||||||
// Do NOT double-convert! Pass directly to TLS SLL which expects BASE.
|
// 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);
|
void front_gate_after_refill(int class_idx, int refilled_count);
|
||||||
|
|
||||||
// Push a block to TLS freelist (SLL). Used by free fast path.
|
// 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);
|
hak_base_ptr_t next = HAK_BASE_FROM_RAW(raw_next);
|
||||||
tls_sll_diag_next(class_idx, base, next, "pop_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.
|
// Validate next pointer before installing as new head.
|
||||||
if (!hak_base_is_null(next)) {
|
if (!hak_base_is_null(next)) {
|
||||||
SuperSlab* next_ss = hak_super_lookup(raw_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.
|
// 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
|
// Release SuperSlab pin now that node left TLS SLL
|
||||||
do {
|
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)
|
// Invariant: ptr must belong to current thread (no ownership check here)
|
||||||
// Caller (Box 6) is responsible for ownership verification
|
// 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
|
#ifdef HAKMEM_TINY_FRONT_GATE_BOX
|
||||||
front_gate_push_tls(class_idx, ptr);
|
front_gate_push_tls(class_idx, ptr);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
#include "box/tls_sll_box.h"
|
#include "box/tls_sll_box.h"
|
||||||
#include "box/front_gate_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
|
#ifdef HAKMEM_TINY_FRONT_GATE_BOX
|
||||||
// When FrontGate Box is enabled, delegate to its TLS push helper.
|
// When FrontGate Box is enabled, delegate to its TLS push helper.
|
||||||
front_gate_push_tls(class_idx, ptr);
|
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];
|
extern __thread TinyTLSList g_tls_lists[TINY_NUM_CLASSES];
|
||||||
|
|
||||||
// Box 5 helper (TLS push)
|
// 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 ==========
|
// ========== Ownership Check ==========
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user