diff --git a/App/lib/StubGen/VpiReader.vp b/App/lib/StubGen/VpiReader.vp index 7eaae33..34620b6 100644 --- a/App/lib/StubGen/VpiReader.vp +++ b/App/lib/StubGen/VpiReader.vp @@ -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)) diff --git a/App/lib/core/Gen/CallGenBase.vp b/App/lib/core/Gen/CallGenBase.vp index 4ce776d..8f3c694 100644 --- a/App/lib/core/Gen/CallGenBase.vp +++ b/App/lib/core/Gen/CallGenBase.vp @@ -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: