Restrict ss_fast_lookup to validated Tiny pointer paths only

Safety fix: ss_fast_lookup masks pointer to 1MB boundary and reads
memory at that address. If called with arbitrary (non-Tiny) pointers,
the masked address could be unmapped → SEGFAULT.

Changes:
- tiny_free_fast(): Reverted to safe hak_super_lookup (can receive
  arbitrary pointers without prior validation)
- ss_fast_lookup(): Added safety warning in comments documenting when
  it's safe to use (after header magic 0xA0 validation)

ss_fast_lookup remains in LARSON_FIX paths where header magic is
already validated before the SuperSlab lookup.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm (CI)
2025-11-27 12:55:40 +09:00
parent 64ed3d8d8c
commit 7a03a614fd
2 changed files with 12 additions and 5 deletions

View File

@ -15,6 +15,12 @@ extern _Atomic uint64_t g_ss_active_dec_calls;
// Purpose: Replace expensive hak_super_lookup() with O(1) mask calculation // Purpose: Replace expensive hak_super_lookup() with O(1) mask calculation
// Invariant: All SuperSlabs are aligned to at least SUPERSLAB_SIZE_MIN (1MB) // Invariant: All SuperSlabs are aligned to at least SUPERSLAB_SIZE_MIN (1MB)
// Cost: ~5-10 cycles (vs 50-100 cycles for registry lookup) // Cost: ~5-10 cycles (vs 50-100 cycles for registry lookup)
//
// ⚠️ SAFETY: Only use when pointer is ALREADY VALIDATED as Tiny allocation!
// This function masks to 1MB boundary and reads memory at that address.
// If the masked address is unmapped, it will SEGFAULT.
// Safe to use: After header magic (0xA0) validation in LARSON_FIX paths
// NOT safe: In tiny_free_fast() or other paths with arbitrary pointers
static inline SuperSlab* ss_fast_lookup(void* ptr) static inline SuperSlab* ss_fast_lookup(void* ptr)
{ {
if (__builtin_expect(!ptr, 0)) return NULL; if (__builtin_expect(!ptr, 0)) return NULL;

View File

@ -215,11 +215,12 @@ static inline void tiny_free_fast(void* ptr) {
} }
// 1. SuperSlab-backed tiny pointer? // 1. SuperSlab-backed tiny pointer?
if (__builtin_expect(g_use_superslab != 0, 1)) { if (__builtin_expect(g_use_superslab != 0, 1)) {
// Phase 12 optimization: Use fast mask-based lookup instead of registry // NOTE: Use safe hak_super_lookup here (not ss_fast_lookup) because
// ss_fast_lookup does: mask + magic check + range check (~5-10 cycles vs 50-100) // tiny_free_fast() can receive arbitrary pointers without prior validation.
void* base = (void*)((uint8_t*)ptr - 1); // Convert USER → BASE first // ss_fast_lookup masks to 1MB boundary and reads magic - would crash on unmapped memory.
SuperSlab* ss = ss_fast_lookup(base); SuperSlab* ss = hak_super_lookup(ptr);
if (__builtin_expect(ss != NULL, 1)) { if (__builtin_expect(ss != NULL && ss->magic == SUPERSLAB_MAGIC, 0)) {
void* base = (void*)((uint8_t*)ptr - 1); // Convert USER → BASE
int slab_idx = slab_index_for(ss, base); int slab_idx = slab_index_for(ss, base);
uint32_t self_tid = tiny_self_u32(); uint32_t self_tid = tiny_self_u32();