From e376b949c9ed9c155d2bb32625813ce1d32aa8f3 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 25 Aug 2026 17:21:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(memhub):=20=E7=A7=BB=E9=99=A4=20free=20?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E5=89=8D=E6=A0=87=E8=AE=B0=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E2=80=94=E2=80=94=E5=90=88=E5=B9=B6=E9=87=8D=E5=88=86=E9=85=8D?= =?UTF-8?q?=E8=AF=AF=E6=8A=A5=EF=BC=88=E4=B8=8E=20w0/w1=20=E5=90=8C?= =?UTF-8?q?=E7=B1=BB=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 下溢写误报实锤:1024B free 块 hdr=0x0、同 ptr 仅一条 F 记录、前标记被写零——块合并进更大块后新分配用户区覆盖旧记录前标记区而旧块头仍为 0,前标记校验原理性不可靠(SlotsBugTest 1024B 块误报例)。 移除 free 记录全部校验,只保留 active 记录前/后标记校验(存活块独占,header LSB=1 不会合并,可靠)。 --- includes/memhub.vp | 45 ++++++--------------------------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/includes/memhub.vp b/includes/memhub.vp index ded5011..bea8f5e 100644 --- a/includes/memhub.vp +++ b/includes/memhub.vp @@ -881,45 +881,12 @@ class MemBuddy(MemManager): p: t.CUInt64T = self._det_records[i * 2] s: t.CUInt64T = self._det_records[i * 2 + 1] if (s & free_flag) != 0: - # free 记录:只校验前标记(block+8..9)——子块边界 2^n>=32 对齐 - # 永不落在 block+8,前标记被破坏 = 真实 UAF/下溢写。不做用户区 - # 0xCD 完整性校验:buddy 分配器 free 后会把 next 指针/子块头写进 - # free 块(free 块用户区即管理区),0xCD 必然被破坏 → 持续误报 - # (SlotsBugTest 4352B 块首 8B=0x400000000、前标记完好的误报例)。 - real_s: t.CUInt64T = s & (free_flag - 1) - if real_s > 0: - blk_h: t.CUInt64T = p - 2 - MEMBUDDY_HEADER_SIZE - hdr_v: t.CUInt64T = t.CUInt64T(c.Deref(t.CUInt64T(blk_h, t.CPtr))) - if (hdr_v & 1) == 0: - m_fr: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(p - 2, t.CPtr)) - mfv_r: t.CUInt16T = m_fr[0] - if mfv_r != t.CUInt16T(MEMBUDDY_DET_MARKER): - stdio.printf("[DET] 下溢写: ptr=%llu size=%llu(free 后前标记被破坏,前标记=0x%04X)hdr=0x%llX 记录[%zu]\n", - p, real_s, t.CUInt32T(mfv_r), hdr_v, i) - # 记录上下文 ±3(同越界写打印,定位 free 块分配/释放阶段) - stdio.printf("记录上下文: ") - ci_r: t.CInt = -3 - while ci_r <= 3: - idx_r: t.CSizeT = t.CSizeT(t.CInt(i) + ci_r) - if idx_r < self._det_count: - cip_r: t.CUInt64T = self._det_records[idx_r * 2] - cis_r: t.CUInt64T = self._det_records[idx_r * 2 + 1] - stdio.printf("[%d]ptr=%llu sz=%llu ", ci_r, cip_r, cis_r & (free_flag - 1)) - ci_r += 1 - # 同 ptr 记录(free/active 复用链,判断块是否被二次分配/释放) - stdio.printf("\n同ptr记录: ") - ci3_r: t.CSizeT = 0 - while ci3_r < self._det_count: - cp3_r: t.CUInt64T = self._det_records[ci3_r * 2] - cs3_r: t.CUInt64T = self._det_records[ci3_r * 2 + 1] - if cp3_r == p: - st_r: str = "A" - if (cs3_r & free_flag) != 0: - st_r = "F" - stdio.printf("[%zu]sz=%llu%s ", ci3_r, cs3_r & (free_flag - 1), st_r) - ci3_r += 1 - stdio.printf("\n") - stdlib.exit(1) + # free 记录:跳过——buddy 分配器合并/重分配使 free 块内存不排他 + # (块合并进更大块后,新分配的用户区可覆盖旧记录的前标记区而旧块 + # 头仍为 0),前标记校验会误报(SlotsBugTest 1024B 块 hdr=0x0、 + # 前标记被 2048 合并分配数据写零的误报例,与 w0/w1 0xCD 校验同类)。 + # 只校验 active 记录(存活块独占,header LSB=1 不会合并, + # 前/后标记可靠)。 i += 1 continue if s == 0: