fix(memhub): detection 记录表满时 realloc 扩容 - 原 32MB/16B=2M 条满后新 alloc 无记录,is_alive 误报读取悬空(hdr=0x5 活跃块不在记录表);改为 stdlib.realloc 翻倍扩容(对齐 chk_stack),保证 is_alive/_det_probe 全程覆盖

This commit is contained in:
TermiNexus committed 2026-08-25 15:39:09 +08:00
1 parent b3b82a8093
commit 40f10f6348
1 file changed
+18 -4
+18 -4
View File
@@ -323,6 +323,7 @@ class MemBuddy(MemManager):
# detection=1 → alloc 前后 2 字节 0xCDCD 标记 + 记录表 + 每次 alloc 后探测
detection: t.CInt = 0
detection_size: t.CSizeT = MEMBUDDY_DET_RECORD_SIZE
_det_arena: t.CVoid | t.CPtr = None # 记录区基址(stdlib.malloc,供 realloc 扩容)
_det_records: t.CUInt64T | t.CPtr = None # 记录表(每 2×u64 = 1 条:{ptr, size})
_det_count: t.CSizeT = 0 # 已记录条数
_det_cap: t.CSizeT = 0 # 记录容量(条)
@@ -410,6 +411,7 @@ class MemBuddy(MemManager):
det_arena: t.CVoid | t.CPtr = t.CVoid(
stdlib.malloc(self.detection_size), t.CPtr)
if det_arena is not None:
self._det_arena = det_arena
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(det_arena, t.CPtr))
self._det_cap = self.detection_size // 16
self._det_count = 0
@@ -657,10 +659,22 @@ class MemBuddy(MemManager):
tail_d: t.CUInt64T = base_ret_d + 2 + t.CUInt64T(size)
m_t_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(tail_d, t.CPtr))
m_t_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
if self._det_records is not None and self._det_count < self._det_cap:
self._det_records[self._det_count * 2] = base_ret_d + 2
self._det_records[self._det_count * 2 + 1] = t.CUInt64T(size)
self._det_count += 1
if self._det_records is not None:
if self._det_count >= self._det_cap:
# 记录表满:stdlib.realloc 翻倍扩容(防 is_alive/_det_probe
# 因容量耗尽漏检——SlotsBugTest 编译 includes 超 2M 次 alloc,
# 满后新块无记录 → is_alive 误报"读取悬空")
new_cap: t.CSizeT = self._det_cap * 2
new_rec: t.CVoid | t.CPtr = t.CVoid(
stdlib.realloc(self._det_arena, new_cap * 16), t.CPtr)
if new_rec is not None:
self._det_arena = new_rec
self._det_records = (t.CUInt64T | t.CPtr)(t.CVoid(new_rec, t.CPtr))
self._det_cap = new_cap
if self._det_count < self._det_cap:
self._det_records[self._det_count * 2] = base_ret_d + 2
self._det_records[self._det_count * 2 + 1] = t.CUInt64T(size)
self._det_count += 1
self._det_probe()
result = t.CVoid(base_ret_d + 2, t.CPtr)
if result is None: