fix(vpi): 参数数上限哨兵 + declare 链遍历哨兵,定位 builtins.vp dump 卡死根因

dump 步数哨兵已定位卡死链路为 printf 的 Params 链异常。新增:
1. VpiReader _inject_function_declare/_inject_method_declare 参数数上限
   128(fail-fast):vpi tree 深层节点被覆盖损坏时 args_list.__len__()
   返回垃圾大数 → add_param 海量次 → Params 链超长,dump 误报成环
2. CallGenBase._ensure_method_declare FuncHead/Params 遍历步数上限
   (防 translate 期间死循环)
This commit is contained in:
TermiNexus committed 2026-08-18 08:10:18 +08:00
1 parent 453f428aab
commit 43470b6e4a
2 files changed
+27

No files matched your search

+16
View File
@@ -1139,6 +1139,15 @@ def _inject_function_declare(pool: memhub.MemBuddy | t.CPtr,
if args_node.args is not None:
args_list: list[ast.AST | t.CPtr] | t.CPtr = args_node.args
param_count = args_list.__len__()
# 参数数上限哨兵(fail-fast):vpi tree 深层节点在遍历处理过程中
# 可能被覆盖损坏(见本文件顶部注释),fd.args 悬空时 __len__()
# 返回垃圾大数 → for 循环 add_param 海量次 → Params 链超长,
# dump 时步数哨兵误报"链表成环"。超限立即报错定位。
if param_count < 0 or param_count > 128:
stdio.printf(
"[VPIS] 参数数异常: 函数名=%s param_count=%d(fd.args=%llu,tree 可能被覆盖,终止)\n",
fd.name, param_count, t.CUInt64T(fd.args))
stdlib.exit(1)
pi: t.CSizeT
for pi in range(param_count):
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(args_list.get(pi))
@@ -1257,6 +1266,13 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr,
if args_node.args is not None:
args_list: list[ast.AST | t.CPtr] | t.CPtr = args_node.args
param_count = args_list.__len__()
# 参数数上限哨兵(fail-fast):与 _inject_function_declare 同因
# (vpi tree 深层节点被覆盖损坏时 __len__() 返回垃圾大数)。
if param_count < 0 or param_count > 128:
stdio.printf(
"[VPIS] 参数数异常: 方法名=%s.%s param_count=%d(m_fd.args=%llu,tree 可能被覆盖,终止)\n",
cls_name, m_fd.name, param_count, t.CUInt64T(m_fd.args))
stdlib.exit(1)
pi: t.CSizeT
for pi in range(param_count):
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(args_list.get(pi))
+11
View File
@@ -504,9 +504,17 @@ class CallGenBase:
"""
if pool is None or mod is None or call_name is None:
return
# 链遍历哨兵(fail-fast):FuncHead/Params 的 Next 被越界写破坏成环时
# 无上限遍历会死循环(builtins.vp dump 卡死根因排查),超限即报错终止。
DECLARE_CHAIN_LIMIT: int = 100000
# 检查模块中是否已有同名函数(declare 或 define)
existing: llvmlite.Function | t.CPtr = mod.FuncHead
existing_steps: int = 0
while existing is not None:
existing_steps += 1
if existing_steps > DECLARE_CHAIN_LIMIT:
stdio.printf("[CALLGEN] 链表异常: module funcs(call_name=%s,遍历超限,终止)\n", call_name)
stdlib.exit(1)
if existing.Name is not None:
if string.strcmp(existing.Name, call_name) == 0:
# 已存在:仅当是 declare 且参数数量不足时追加缺失参数
@@ -521,6 +529,9 @@ class CallGenBase:
cur_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(existing)
while cur_p is not None:
cur_count += 1
if cur_count > DECLARE_CHAIN_LIMIT:
stdio.printf("[CALLGEN] 链表异常: func params(call_name=%s,参数链遍历超限,终止)\n", call_name)
stdlib.exit(1)
cur_p = cur_p.Next
# 只追加缺失的参数(cur_count < param_count 时)
if cur_count < param_count: