From 2e6c37294d38427699a934c8c8b27f2dd8c41a6b Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 23 Aug 2026 12:38:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpv):=20=E4=BF=AE=E5=A4=8D=20vpi=20CDefine?= =?UTF-8?q?=20=E5=90=8D=E7=BC=93=E5=AD=98=20list.get=20=E8=A2=AB=E8=AF=AF?= =?UTF-8?q?=E5=88=86=E6=B4=BE=E4=B8=BA=20HashTable.get=20=E7=9A=84=20ASan?= =?UTF-8?q?=20=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converter.vp _g_pyi_cdef_names 由 list[str]|t.CPtr 改为 str|t.CPtr(i8** 字符串 指针数组),读写改用 argparse 同款可靠模式 t.CPtr(base+i*8)+e[0]:list 联合 接收者的 .get 会被分派为 HashTable.get(self, key, default),索引 inttoptr 成 key 指针传给 _fnv1a_hash 解引用零页崩溃(1.LOG)。 TranslatorGenMixin handle_module_level_var 对模块级 str|bytes 联合全局设置 IsPtrElement(8 字节指针步长),对齐 TPC global_var_ptr_element。 --- App/lib/Stub/StubGen/Converter.vp | 32 +++++++++++++++++--------- App/lib/core/Gen/TranslatorGenMixin.vp | 13 +++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index a0797b9..1543ac9 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -123,10 +123,16 @@ _g_pyi_cdefine_found: int = 0 # HandlesType 全局表为空 → BinOp 内 Name 引用查表失败退化为 0(ZDEFLATE # WINDOW_SIZE = 1<<0 = 1、MASK = 0-1 = -1,跨模块读回错误常量根因)。 # _GeneratePyiFromAst 开头按声明顺序注册到本缓存,Name 引用先查缓存。 -# 值缓存用 C 数组(t.CInt64T*)而非 list[int]:TPC 对 list[int].get 会误解析为 -# list[str].get(返回元素指针 i8*)→ ptrtoint 返回元素地址而非值 → MASK 变成 -# 20323785277439(地址-1)。C 数组索引 [i] 直接返回 i64 值,可靠。 -_g_pyi_cdef_names: list[str] | t.CPtr = None +# 缓存一律用 C 数组而非 list[T]: +# - 值缓存用 C 数组(t.CInt64T*)而非 list[int]:TPC 对 list[int].get 会误解析 +# 为 list[str].get(返回元素指针 i8*)→ ptrtoint 返回元素地址而非值 → MASK +# 变成 20323785277439(地址-1)。C 数组索引 [i] 直接返回 i64 值,可靠。 +# - 名缓存用 C 数组(str|t.CPtr = i8**,字符串指针数组)而非 list[str]: +# list[str] | t.CPtr 联合类型接收者的 .get 会被 TPC/TPV 误分派为 +# HashTable.get(self, key, default) —— 索引被 inttoptr 成 key 指针传给 +# _fnv1a_hash → 解引用零页 access-violation(1.LOG ASan 崩溃根因)。 +# 读写沿用 argparse.vp 遍历 argv 的可靠模式:t.CPtr(base + i*8) + e[0]。 +_g_pyi_cdef_names: str | t.CPtr = None _g_pyi_cdef_vals: t.CInt64T | t.CPtr = None _g_pyi_cdef_count: t.CInt = 0 @@ -137,14 +143,17 @@ def _lookup_cdefine_for_pyi(name: str) -> t.CInt64T: # 优先查本文件 CDefine 缓存(vpi 生成早于翻译阶段注册,全局表为空) if _g_pyi_cdef_names is not None and _g_pyi_cdef_vals is not None: # 循环上限用 _g_pyi_cdef_count 而非 len(_g_pyi_cdef_names): - # list[str] | t.CPtr 联合类型下 TPV 的 len() 回退 strlen(把 list 对象 - # 指针当字符串算长度 → 垃圾小值 → 靠后注册项查不到,ZDEFLATE_HASH_MASK - # = lookup(HASH_SIZE) 失败 = 0-1 = -1 根因;WINDOW_MASK 查位置 1 恰好 - # 在 strlen 结果内所以碰巧正确)。 + # i8** 指针数组上 TPV 的 len() 回退 strlen(把基址指针当字符串算长度 + # → 垃圾小值 → 靠后注册项查不到,ZDEFLATE_HASH_MASK = lookup(HASH_SIZE) + # 失败 = 0-1 = -1 根因;WINDOW_MASK 查位置 1 恰好落在 strlen 结果内所以 + # 碰巧正确)。且绝不能对 _g_pyi_cdef_names 调 .get —— list 联合接收者 + # 会被误分派为 HashTable.get,索引 inttoptr 成 key 指针读零页崩溃 + # (1.LOG)。用 t.CPtr(base + i*8) + e[0] 取第 i 个名字指针(argparse 模式)。 pn: t.CSizeT = t.CSizeT(_g_pyi_cdef_count) pi: t.CSizeT for pi in range(pn): - pnm: str = _g_pyi_cdef_names.get(pi) + entry_pc: str | t.CPtr = t.CPtr(t.CUInt64T(_g_pyi_cdef_names) + pi * 8) + pnm: str = entry_pc[0] if pnm is not None and string.strcmp(pnm, name) == 0: _g_pyi_cdefine_found = 1 return _g_pyi_cdef_vals[pi] @@ -609,7 +618,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy | t.CPtr, tree: ast.AST | t.CPtr, _g_pyi_cdef_count += 1 pci0 += 1 if _g_pyi_cdef_count > 0: - _g_pyi_cdef_names = list[str](mb, t.CSizeT(_g_pyi_cdef_count)) + _g_pyi_cdef_names = (str | t.CPtr)(mb.alloc(t.CSizeT(_g_pyi_cdef_count) * 8)) _g_pyi_cdef_vals = (t.CInt64T | t.CPtr)(mb.alloc(t.CSizeT(_g_pyi_cdef_count) * 8)) # 第二遍:按声明顺序注册(BinOp 内 Name 引用依赖先前注册项) pci: t.CSizeT = 0 @@ -625,7 +634,8 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy | t.CPtr, tree: ast.AST | t.CPtr, ann_pc: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(aa_pc.annotation) if ann_pc.attr is not None and string.strcmp(ann_pc.attr, "CDefine") == 0: if _g_pyi_cdef_names is not None and _g_pyi_cdef_vals is not None: - _g_pyi_cdef_names.append(tgt_pc.id) + slot_pc: str | t.CPtr = t.CPtr(t.CUInt64T(_g_pyi_cdef_names) + cdi * 8) + slot_pc[0] = tgt_pc.id _g_pyi_cdef_vals[cdi] = _eval_cdefine_value_cache(aa_pc.value) cdi += 1 pci += 1 diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index a4b1d4c..92f95b0 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -572,6 +572,19 @@ class TranslatorGenMixin: if cls_nm_ml is not None: self.Gen.VarGen.set_var_annot_class_name( trans.SymTab, var_name, cls_nm_ml) + # 模块级 str|t.CPtr / bytes|t.CPtr 全局:标记 IsPtrElement + # (i8** 语义,var[i] 按 8 字节指针步长),对齐 TPC 的 + # global_var_ptr_element(_argv 等字符串指针数组)。否则 + # var[i] 退化为 1 字节字符步长 GEP + load i8 截断指针。 + if aa_ml.annotation.kind() == ast.ASTKind.BinOp: + bop_ml: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(aa_ml.annotation) + if bop_ml.op == ast.OpKind.BitOr: + if self.Gen.AssignGen._annotation_contains_name( + aa_ml.annotation, "str") != 0 \ + or self.Gen.AssignGen._annotation_contains_name( + aa_ml.annotation, "bytes") != 0: + self.Gen.VarGen.set_var_ptr_element( + trans.SymTab, var_name) return 1 return 0