Skip to content

fix(scanner): prune .mcpp from glob walks; never throw on unnarrowable names (#230)#231

Merged
Sunrisepeak merged 4 commits into
mainfrom
fix/win-scanner-escape-230
Jul 18, 2026
Merged

fix(scanner): prune .mcpp from glob walks; never throw on unnarrowable names (#230)#231
Sunrisepeak merged 4 commits into
mainfrom
fix/win-scanner-escape-230

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

修复 #230:windows mcpp test --workspace 静默 exit 127

根因(三层,全部修复)

真实退出码是 0xC0000409(fastfail),git-bash 把它显示成 127。通过在 CI runner 上开启 WER 全内存 dump 并解析崩溃栈,拿到了被转换的字符串本体:

.mcpp\.xlings\data\compat\mcpp-0.0.95-windows-x86_64\registry\data\
xim-pkgindex\.github\ISSUE_TEMPLATE\bug-report---问题反馈.md

链条:

  1. 0.0.95 扫描器新增 follow_directory_symlink(feat(manifest): 声明式清单能力 — features.sources / generated_files / cfg 条件 sources / per-glob flags #223),而项目本地 .mcpp/.xlings/data/<index> 是指回索引根的符号链接(config.cppm 创建)→ glob walk 逃逸出成员目录,走遍整个索引 checkout(CI 里含解压的 mcpp 发行版及其 vendored xim-pkgindex)。
  2. path_matches_globgeneric_string() 把宽路径拼成窄串;MSVC 在非 CJK ANSI 代码页(runner ACP=1252)下遇到中文文件名std::system_error(linux/macos 无此转换,所以只有 windows 崩)。
  3. 异常一路逃出 main 未被捕获 → std::terminate__fastfail → 0xC0000409,无任何错误输出。

0.0.94 绿是因为它不跟随目录符号链接,从未走进该树。

修复

  • expand_glob/expand_dir_glob:按名剪枝 .mcpp 目录——它是 mcpp 自己的元数据目录,永远不是源码目录;从源头切断符号链接逃逸(顺带避免每个成员都把整个索引树白走一遍)。
  • path_matches_glob:名字无法窄化 → 视为"不匹配"并跳过,而不是让转换异常摧毁整次构建。
  • main() 增加最后防线 catch:逃逸异常现在会打印真实错误并以 70 退出,不再是静默 fastfail/127。

验证

  • linux 行为对照:release 0.0.95 会顺着 .mcpp 符号链接把项目外的 extra.cpp 编进来(链接期 duplicate main);修复版剪枝后构建干净。
  • 新增 e2e 113_scanner_mcpp_dir_prune.sh 固化两条断言(符号链接逃逸剪枝 + CJK 文件名不致命)。
  • 35/35 单元测试通过。
  • 复现/取证记录:mcpplibs/mcpp-index 分支 debug/mcpp230-windows-repro(五轮插桩:原始退出码 → minidump → cdb 栈 → 全内存 dump 字符串取证)。

发布 0.0.96 后,mcpp-index 即可撤掉 windows 钉回 0.0.94 的临时补丁,全平台统一到最新(mcpp-index#74 正在等待)。

…e names (#230)

Root cause of the windows-latest 'exit 127' (really 0xC0000409): 0.0.95's
scanner walks globs with follow_directory_symlink, and the project-local
`.mcpp/.xlings/data/<index>` entry is a symlink back to the index root —
so the walk escapes into the entire index checkout. In mcpp-index CI that
tree contains a vendored xim-pkgindex whose issue template has a CJK
filename; path_matches_glob spelled it narrow via generic_string(), which
on MSVC under a non-CJK ANSI codepage throws std::system_error. The
exception escaped main uncaught -> std::terminate -> __fastfail
(0xC0000409), which git-bash reports as a bare exit 127.

Three layers, all fixed:
- expand_glob/expand_dir_glob prune directories named .mcpp — mcpp's own
  metadata dir is never a source dir, and pruning it severs the symlink
  escape at its origin (also stops walking the whole index per member).
- path_matches_glob treats a name with no narrow spelling as 'no match'
  instead of letting the conversion tear down the build.
- main() gains a last-resort catch: an escaped exception now names itself
  and exits 70 instead of a silent fastfail.

Evidence: full-memory WER dump from the CI runner shows the throw chain
scan_one_into -> expand_glob -> path_matches_glob -> _Convert_wide_to_narrow
with the wide string
'.mcpp\.xlings\data\compat\mcpp-0.0.95-windows-x86_64\registry\data\
xim-pkgindex\.github\ISSUE_TEMPLATE\bug-report---<CJK>.md'.
Behavioral control on linux: release 0.0.95 compiles an out-of-tree
extra.cpp through the .mcpp symlink (duplicate main at link); the fixed
binary prunes it and builds clean. e2e 113 encodes both assertions.
35/35 unit tests pass.
d2learn-org and others added 3 commits July 18, 2026 08:41
Version bump + CHANGELOG entry for the release notes extractor; also
backfill a pointer entry for 0.0.95 (released without one).
@Sunrisepeak
Sunrisepeak merged commit df985df into main Jul 18, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants