diff --git a/asm.vp b/asm.vp index 2179d3d..2b13600 100644 --- a/asm.vp +++ b/asm.vp @@ -74,7 +74,7 @@ def io_wait(): # 的 clobber 列表**不允许声明 RSP**(保留寄存器)⇒ 编译器无从得知 RSP 已被改写, # 若两块之间出现任何编译器生成的栈使用(spill/调用),会覆盖刚压栈的寄存器值。 # 故只可在**编译期不产生任何栈使用**的上下文(如 naked 汇编区)里成对使用。 -inline def pushall(): +def pushall() -> t.CInline | t.CVoid: c.Asm(f""" push rax push rbx @@ -94,7 +94,7 @@ inline def pushall(): [t.ASM_DESCR.CLOBBER_MEMORY] ) -inline def popall(): +def popall() -> t.CInline | t.CVoid: c.Asm(f""" pop r15 pop r14 diff --git a/memhub.vp b/memhub.vp index f21d55f..22b1c2a 100644 --- a/memhub.vp +++ b/memhub.vp @@ -337,7 +337,7 @@ class MemSlab(MemManager): size, self.block_size) return None block: t.CPtr = self.free_list - self.free_list = t.CPtr(c.Deref(t.CUInt64T(block))) + self.free_list = t.CPtr(c.Deref((t.CUInt64T | t.CPtr)(block))) self.used_count += 1 idx: t.CSizeT = (t.CUInt64T(block) - t.CUInt64T(self.usable)) / self.block_size self.alloc_map[idx / 8] = self.alloc_map[idx / 8] | t.CUInt8T(1 << (idx % 8)) @@ -1269,7 +1269,14 @@ class MemBuddy(MemManager): # 块尾 canary 校验:越界写穿数据区会破坏块尾哨兵, # 立即定位到越界写发生的文件(崩溃点漂移的关键哨兵)。 # 与 alloc 写入点统一使用编译期常量 MEMBUDDY_CANARY_PATTERN(同值同宽)。 - can_stored: t.CPtr = t.CPtr(c.Deref((t.CUInt64T | t.CPtr)(block) + bs - MEMBUDDY_CANARY)) + # 【地址口径】必须与 alloc 的写入点逐字一致:先把 block 转成整数, + # 再做整数加/减(t.CUInt64T + i64 = 字节语义),最后才转指针。 + # 不可写成 (t.CUInt64T | t.CPtr)(block) + bs - MEMBUDDY_CANARY: + # 联合转换 (T | t.CPtr)(x) 按 LLVMTypeMapper 映射为 T*(此处 i64*), + # 指针 + 整数走 GEP ⇒ 每单位前进 sizeof(T)=8 字节 + # ⇒ 实际读到 block + 8*bs - 64(order0/bs=32 时 = block+192), + # 读到的是别的块(池内其它路径缓冲)的数据 ⇒ 假阳性 rc=6。 + can_stored: t.CPtr = t.CPtr(c.Deref(t.CPtr(t.CUInt64T(block) + bs - MEMBUDDY_CANARY))) if t.CUInt64T(can_stored) != t.CUInt64T(MEMBUDDY_CANARY_PATTERN): # [TEMP-DIAG] 越界写现场:块尾 canary 被写穿(rc=6 的判据)。 # 原实现只回 rc(int),调用方拿不到块/阶/实际值 → 无法定位。