依据 T97 决定性结果,修复了 CVoid 严格验证,other_ty 有效性验证,fallback 不依赖 kind() 实现

This commit is contained in:
TermiNexus committed 2026-08-06 23:00:01 +08:00
1 parent f440bda421
commit c876df7907
2 files changed
+85 -2

No files matched your search

+40 -1
View File
@@ -152,8 +152,25 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy | t.CPtr,
ast._lexer_init(lx, vpi_buf, pool)
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
tree: ast.AST | t.CPtr = ast.parse_tokens(pool, tokens)
stdlib.free(vpi_buf)
# vpi_buf 延迟释放:AST 字符串字段可能引用 vpi_buf 内部(token 零拷贝),
# 提前 free 会导致 Name.id/Attribute.attr 等悬空 → 后续解析返回错误类型。
# 在 ParseVpiIntoModule 末尾统一释放。
# [DBG-T96] 临时诊断:定位 vpi AST 有效性(定位后移除)
k96: int = -1
if tree is not None:
k96 = tree.kind()
stdio.printf("[DBG-T96] vpi tree kind=%d children=", k96)
if tree is not None and tree.children is not None:
n96: t.CSizeT = tree.children.__len__()
stdio.printf("%d\n", n96)
if n96 > 0:
c96: ast.AST | t.CPtr = tree.children.get(0)
if c96 is not None:
stdio.printf("[DBG-T96] child0 kind=%d\n", c96.kind())
else:
stdio.printf("0\n")
if tree is None:
stdlib.free(vpi_buf)
return 0
# 提取源模块 SHA1(用于函数名混淆,在 AST 解析成功后提取避免提前返回时泄漏)
@@ -234,6 +251,8 @@ def ParseVpiIntoModule(pool: memhub.MemBuddy | t.CPtr,
# 释放 SHA1 缓冲区(_extract_sha1_from_path 用 stdlib.malloc 分配)
if src_sha1 is not None:
stdlib.free(src_sha1)
# vpi_buf 延迟到全部 tree 处理完成后释放(见解析处注释)
stdlib.free(vpi_buf)
return 1
@@ -420,6 +439,26 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr,
if ret_ty is None:
ret_ty = i32_ty
# [DBG-T97] 临时诊断:定位 args.get_str 类型退化(定位后移除)
if string.strcmp(m_fd.name, "parse_args") == 0:
vis97: int = HandlesStruct.is_struct_visible("ParsedArgs")
gst97: t.CChar | t.CPtr = stdlib.malloc(128)
if gst97 is not None:
gty97: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type("ParsedArgs")
if gty97 is not None:
llvmlite.TypePrint(gst97, 128, gty97, pool)
else:
viperlib.snprintf(gst97, 128, "NULL")
ot97: t.CChar | t.CPtr = stdlib.malloc(128)
if ot97 is not None:
if ret_ty is not None:
llvmlite.TypePrint(ot97, 128, ret_ty, pool)
else:
viperlib.snprintf(ot97, 128, "NULL")
stdio.printf("[DBG-T97] vis=%d gst=%s ret=%s\n", vis97, gst97, ot97)
stdlib.free(ot97)
stdlib.free(gst97)
# 创建 declare
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, mangled_name, ret_ty)
+45 -1
View File
@@ -1550,12 +1550,56 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
if left_is_cptr != 0:
other_node = bop.right
# 检测另一边是否是 t.CVoid (void* = i8*)
other_is_cvoid: int = _is_cvoid_marker(other_node, imported_modules)
# 严格验证完整形式(Attribute(t.CVoid) 的 value 是 Name("t"),
# 或裸名 CVoid 且 t 已导入),防止解析异常节点被误判为 CVoid。
other_is_cvoid: int = 0
if other_node is not None:
if other_node.kind() == ast.ASTKind.Attribute:
oat2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(other_node)
if oat2.attr is not None and string.strcmp(oat2.attr, "CVoid") == 0:
if oat2.value is not None and oat2.value.kind() == ast.ASTKind.Name:
ov2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(oat2.value)
if ov2.id is not None and string.strcmp(ov2.id, "t") == 0:
other_is_cvoid = 1
elif other_node.kind() == ast.ASTKind.Name:
onm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node)
if onm2.id is not None and string.strcmp(onm2.id, "CVoid") == 0:
if HandlesImports.is_module_imported(imported_modules, "t") != 0:
other_is_cvoid = 1
if other_is_cvoid != 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
other_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
pool, other_node, imported_modules, from_imports, trans)
# other_ty 必须是已注册的结构体类型才算有效:
# X | t.CPtr 的 X 是类名,解析结果应为 struct 类型。
# 若节点异常导致解析出基础类型/垃圾(如 Int8 → Ptr(i8)),
# 不应直接返回,需走下方回退按类名查全局表。
# (str | t.CPtr 解析为 Ptr(i8) 非 struct,回退 get_struct_type
# 查不到 str → 仍返回 Ptr(i8),结果一致,不受影响。)
if other_ty is not None:
if HandlesStruct.find_struct_by_type(other_ty) is not None:
return llvmlite.Ptr(pool, other_ty)
other_ty = None
if other_ty is None:
# 严格模式(App 文件)下裸类名不可见时,回退到全局
# struct 注册表按类名查找。X | t.CPtr 是明确的指针包装
# 注解(如 vpi stub 的 "ParsedArgs | t.CPtr"),X 已注册
# 时不应静默退化为 i8*——i8* 会让方法返回值的无注解变量
# (如 args = parser.parse_args())类型退化,后续 obj.method
# get_class_name_by_type 查不到类名,误报
# "跨模块调用 'args.get_str' 找不到模块 SHA1"。
# 不检查 kind():vpi 解析的节点在后续处理中可能已损坏
# (kind() 读取异常),直接按 Name 布局读取 id,
# 由 get_struct_type 兜底校验(无效类名返回 None)。
other_cls_nm: str = None
if other_node is not None:
other_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node)
if other_nm.id is not None:
other_cls_nm = other_nm.id
if other_cls_nm is not None:
other_cls_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(other_cls_nm)
if other_cls_ty is not None:
return llvmlite.Ptr(pool, other_cls_ty)
# CPtr 单独使用或其他无效类型 → i8*
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
return llvmlite.Ptr(pool, other_ty)