fix(stubgen): vpi 落盘入口统一重建文件级名字窗口,修复 FileFuncNames 悬垂野读崩溃

Phase1 1b-pre / 1b 兜底 / BuildPipeline / Repl 为生成 vpi 各自重新 parse 出独立 AST,但不走 register_file_funcs,导致 is_file_func(range)(_PushInductionEntry)仍读到上一个文件的表 + 已被 reset 的池 → 悬垂指针,ASan access-violation 崩在 HashTable._slot_hash。将 reset_file_name_window + register_file_func_names 收敛到 _GeneratePyiFromAst 唯一入口,覆盖全部 vpi 落盘调用点;Phase2 的重复调用随之移除。
This commit is contained in:
TermiNexus committed 2026-10-10 14:00:41 +08:00
1 parent c1d3f62bf0
commit f2cbb658e1
2 files changed
+12 -6

No files matched your search

+2 -6
View File
@@ -679,12 +679,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
continue
pyi_buf_vp2: bytes = stdlib.malloc(PYI_BUF_SIZE_P2)
if pyi_buf_vp2 is not None:
# 文件级名字窗口:本阶段为生成 vpi 重新解析出 tree_vp2,但**不走** register_file_funcs;
# 而 _PyiFunction → compute_escape_summary → _ScanEscapes → _PushInductionEntry 会问
# is_file_func("range")。不清窗口就会读到"上一个文件的表 + 已被 reset 的池"→
# 悬垂指针(ASan access-violation / 非 ASan 静默错答)。见 StructGenMixin.reset_file_name_window。
GenApi.reset_file_name_window()
GenApi.register_file_func_names(mb, tree_vp2)
# 文件级名字窗口(FileFuncNames 等)由 _GeneratePyiFromAst 入口统一 reset+重建,
# 不再在此处重复调用;契约见 StructGenMixin.reset_file_name_window。
pyi_pos_vp2: sizet = StubConverter._GeneratePyiFromAst(mb, tree_vp2, ent_vp2.Path, pyi_buf_vp2, PYI_BUF_SIZE_P2)
if pyi_pos_vp2 > 0:
pyi_path_vp2: str = StubMergerCollect._sliced_path(temp_dir, td_len_vpa, ent_vp2.Sha1, "vpi")
+10
View File
@@ -708,6 +708,16 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf
# an absolute path (fatal_error opens it directly). Set once at entry to cover all branches.
if rel_path is not None: GenApi.set_current_file_type(rel_path)
# 文件级名字窗口:本函数是 vpi 落盘的**唯一入口**,而各调用方只为落盘各自重新 parse 出
# 独立 AST、**不走** register_file_funcs。但 _PyiFunction → compute_escape_summary →
# _ScanEscapes → _PushInductionEntry 会问 is_file_func("range")("本文件自己定义过 range
# 就放弃区间推断")。若不清窗口再重建表,就会读到"上一个文件的表 + 已被 reset 的池" =
# 悬垂指针(ASan access-violation 崩在 HashTable._slot_hash / 非 ASan 静默错答)。
# 契约见 StructGenMixin.reset_file_name_window:任何文件级入口必须先清再重建。
# 收敛到本入口可一次性覆盖 Phase1 1b-pre / Phase1 1b 兜底 / BuildPipeline / Repl / Phase2。
GenApi.reset_file_name_window()
GenApi.register_file_func_names(mb, tree)
pos: sizet = 0
# Pre-pass: register this file's CDefines into the _g_pyi cache in declaration order