Repository navigation
fix: 修复字符串分割生命周期与更新线程启动崩溃 - #598
Open
greenhat616 wants to merge 1 commit into
Open
greenhat616 wants to merge 1 commit into
greenhat616 wants to merge 1 commit into
Conversation
Return owning strings from BNString::split so callers do not read destroyed substring temporaries. Reject empty delimiters to avoid an infinite loop. Catch standard and unknown exceptions at the detached remote-update thread boundary, including failures while handling a fallback source. Add regression coverage for long URLs, source lifetime and delimiter cases. Validated with AddressSanitizer, updater exception injection, an x64 Release build, and an isolated CloudMusic startup test with Segment Heap enabled.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
远程插件源返回非 JSON 内容时,BetterNCM 的备用源处理可能读到已释放的字符串;若重试或字符转换再次抛出异常,异常会逃出 detached 更新线程,使网易云启动时退出。这次修复让分割结果拥有自己的内存,并在更新线程入口兜底异常。
复现环境与原始异常
0xDDEEDDEE。plugins.json返回 HTTP 403;先捕获到nlohmann::json::parse_error,首字符为<,随后又捕获到 JSON 解析异常及字符转换相关的std::system_error。msimg32.dll路径中进入std::terminate → abort,异常码为0xC0000409,异常参数为7。以下是修复前捕获的原始致命调用栈,已移除本机文件路径及进程/线程标识,保留原始地址和帧顺序。原版 DLL 没有匹配的 PDB,因此 BetterNCM 帧中的
TransparentBlt + ...是 LLDB 使用最近导出符号生成的标签,不能据此认定崩溃发生在该导出函数内部。原始致命崩溃堆栈
修复思路
1. 修复
BNString::split()的释放后读取原实现返回
std::vector<std::wstring_view>,但将this->substr(...)生成的临时std::wstring放入容器。每个临时字符串在该语句结束时销毁,返回的视图随即悬空,即使原始BNString仍然存活也无法保证安全。备用源处理会在
onlineConfig.split(L"\n")[0]后复制该视图并调用utf8(),因此会使用失效的数据。std::vector<std::wstring>,让每个结果拥有数据。std::invalid_argument,避免原实现无法前进的循环。auto,可直接接收拥有数据的字符串。直接引用修复前的原始头文件,使用两行插件源 URL 做独立 AddressSanitizer 复现,得到:
ASan 将分配及释放位置都定位到原始
BNString.hpp:209的substr临时字符串,读取发生在复制split()返回值时。该内存生命周期缺陷已独立证实;Segment Heap 是否是启动崩溃的必要触发条件,尚未通过切换堆配置验证。2. 防止备用源异常逃出后台更新线程
performForceInstallAndUpdateSync()的原有catch内仍可能在读取/转换备用配置或重试时抛出异常。这些异常不会被同一个catch再次捕获,最终会逃出 detached 线程。在
performForceInstallAndUpdateAsync()的线程函数外层增加catch (const std::exception&)和catch (...),将失败记录到窄字符错误输出,避免网络或备用源处理失败终止整个客户端。验证
tests/bnstring_split.cpp,覆盖长 URL、临时源销毁后的结果读取、空字段、空源、多字符分隔符及空分隔符拒绝。npm run build通过。BetterNCMII.vcxproj的 Release/x64 构建通过(MSVC v143 14.36.32532,仍有原项目既有警告)。启动验证使用内置 PluginMarket,未穷尽第三方插件、播放和长时间运行场景。远程源的可用性仍取决于服务端。
本地完整构建的环境适配
使用项目 CI 固定的 vcpkg ports 提交
69efe9cc2df0015f0bb2d37d55acde4a75c9a25b、对应旧版工具和 CMake 3.25.1。由于部分旧 MSYS 归档已下线,本地构建复用了 pkgconf 2.3.0,并对 FLTK 1.3.8 的构建覆盖限制 Fontconfig 依赖及查找到非 Windows 平台(Windows 仍使用 GDI,OpenGL 保持启用)。这些构建环境适配没有包含在此 PR 中。项目自动部署步骤已关闭。AI 辅助说明
本修复的分析、代码修改及验证使用 6.1-sol 辅助完成。