Files
PathEditor/docs/CHANGELOG_REVIEW.md
T
Serendipity 3bc2f00cb1 feat(backup): 增强备份失败时的用户提示和错误处理
- 在备份失败时显示具体原因(如无法获取AppData路径、创建备份目录失败等)
- 改进备份函数的错误处理,添加详细的日志记录
- 备份失败时允许用户选择是否继续保存操作
- 修复备份目录创建失败时的错误码返回
- 添加备份过程的详细文档说明
2026-04-28 22:40:50 +08:00

9.5 KiB
Raw Blame History

PathEditor 代码审查修复日志

审查日期:2026-04-28 审查范围:全项目代码质量审查 修复状态:29/29 已完成


一、高严重度问题(7 项)

1.1 add_string_list 中 realloc 失败导致内存泄漏

  • 文件src/utils/string_ext.c
  • 问题realloc 返回 NULL 时,原 list->items 指针被覆盖为 NULL,导致原有数组及其中所有字符串指针永久泄漏
  • 修复:使用临时变量保存 realloc 结果,失败时保留原数据不变
// 修复前
list->items = (char **)realloc(list->items, list->capacity * sizeof(char *));

// 修复后
char **new_items = (char **)realloc(list->items, new_capacity * sizeof(char *));
if (!new_items)
    return; // 失败时保留原数据
list->items = new_items;

1.2 add_string_list 中 _strdup 失败未检查

  • 文件src/utils/string_ext.c
  • 问题_strdup 可能返回 NULL,但代码未检查就存入数组并递增 count,后续字符串操作会崩溃
  • 修复:检查 _strdup 返回值,失败时不递增 count

1.3 string_list_set 中先 free 后 strdup 导致数据丢失

  • 文件src/utils/string_ext.c
  • 问题:先释放旧字符串,然后 _strdup 可能失败,导致旧数据丢失且无法恢复
  • 修复:先调用 _strdup 获取新字符串,成功后再释放旧字符串

1.4 wcsftime 缓冲区大小以字节而非宽字符数传入

  • 文件src/utils/os_env.c
  • 问题sizeof(timestamp) 返回字节数(128),而 wcsftime 期望宽字符数(64),可能导致栈缓冲区溢出
  • 修复:改用 sizeof(timestamp) / sizeof(timestamp[0])
// 修复前
wcsftime(timestamp, sizeof(timestamp), L"%Y%m%d_%H%M%S", tm_info);

// 修复后
wcsftime(timestamp, sizeof(timestamp) / sizeof(timestamp[0]), L"%Y%m%d_%H%M%S", &tm_info);

1.5 load_single_path 在 malloc 失败时仍返回 ERR_OK

  • 文件src/core/registry_service.c
  • 问题malloc 失败时跳过数据读取,但仍返回 ERR_OK,调用者认为加载成功
  • 修复malloc 失败时返回 ERR_OUT_OF_MEMORY

1.6 导入数据内存泄漏

  • 文件src/controller/callbacks_io.c
  • 问题btn_import_cbExportData importedsystemuser 从未调用 clear_string_list 释放
  • 修复:在函数所有返回路径前调用 clear_string_list 释放导入数据

1.7 JSON 导入解析器完全失效

  • 文件src/core/import_export.c
  • 问题:键名检测逻辑被 in_string 状态翻转拦截,"system""user" 的检测永远无法触发
  • 修复:重写 JSON 解析器,在字符串结束时检测键名,合并重复的数组解析逻辑

二、中严重度问题(9 项)

2.1 backup_registry 部分备份成功时错误报告为完全成功

  • 文件src/utils/os_env.c
  • 修复:分别跟踪系统和用户 PATH 的备份状态

2.2 btn_ok_cb 未检查 backup_registry 返回值

  • 文件src/controller/callbacks_sys.c
  • 修复:检查返回值,备份失败时提示用户是否继续保存
// 修复后
ErrorCode backup_result = backup_registry();
if (backup_result != ERR_OK)
{
    int choice = IupAlarm("警告", "备份失败!是否继续保存?",
                          "继续保存", "取消", NULL);
    if (choice != 1)
        return IUP_DEFAULT;
}

2.3 TABTITLE 设置在 Dialog 而非 Tabs 控件上

  • 文件src/ui/main_window.c
  • 问题TABTITLE0TABTITLE1IupTabs 属性,不是 IupDialog 属性,导致语言切换后选项卡标题不更新
  • 修复:先获取 Tabs 控件句柄,再设置 TABTITLE

2.4 list_dropfiles_cb 使用 ANSI 版本 API

  • 文件src/controller/callbacks_search.c
  • 问题GetFileAttributesA 无法正确处理中文等 Unicode 字符路径
  • 修复:改用 utf8_to_wide + GetFileAttributesW

2.5 load_all_paths 用户路径加载失败时未通知用户

  • 文件src/controller/callbacks_sys.c
  • 修复:添加 else 分支,在用户路径加载失败时弹出提示

2.6 escape_json_string 未处理所有控制字符

  • 文件src/core/import_export.c
  • 问题:只处理了 \\"\n\r\t,其他 0x00-0x1F 控制字符未转义
  • 修复:添加 \b\f 处理,其他控制字符使用 \uXXXX 格式

2.7 CreateDirectoryW 不创建中间目录

  • 文件src/utils/os_env.c
  • 修复:改用 SHCreateDirectoryExW 递归创建目录

2.8 ExportData 浅拷贝隐患

  • 文件include/core/import_export.h
  • 修复:添加文档注释说明只读语义,防止误用 clear_string_list

2.9 export_paths_to_file 未检查 fprintf 返回值

  • 文件src/core/import_export.c
  • 修复:在 fclose 后检查 ferror(fp),发现错误时返回 ERR_FAILED

三、低严重度问题(13 项)

3.1 JSON 解析器代码重复

  • 文件src/core/import_export.c
  • 修复:合并 system/user 数组解析逻辑为统一的键名检测机制

3.2 get_app_context_from_dlg 依赖指针到字符串的不安全转换

  • 状态:保留现状(IUP 框架标准用法)

3.3 putenv 使用字符串字面量的可移植性问题

  • 文件src/main.c
  • 修复:改用 _wputenv_s

3.4 path_manager_clean 时间复杂度为 O(n³)

  • 文件src/core/path_manager.c
  • 修复:使用标记+批量删除优化为 O(n²)

3.5 全局日志状态非线程安全

  • 状态:保留现状(当前是单线程 GUI 应用)

3.6 localtime 返回静态缓冲区指针,非线程安全

  • 文件src/utils/os_env.csrc/core/import_export.c
  • 修复:改用 localtime_s

3.7 JSON 解析器原地修改输入缓冲区

  • 修复:重写解析器时已解决,不再修改原始缓冲区

3.8 JSON 解析器对 \\" 场景处理错误

  • 修复:重写解析器时已解决,使用 is_quote_escaped 检查连续反斜杠

3.9 TXT 格式导入只能导入到系统路径

  • 文件src/controller/callbacks_io.c
  • 修复:添加选择对话框,允许用户选择导入到系统变量或用户变量

3.10 trim_whitespace 未检查 NULL 输入

  • 文件src/core/import_export.c
  • 修复:添加防御性 NULL 检查

3.11 is_json_file 使用 strcasecmp 限制可移植性

  • 文件src/core/import_export.c
  • 修复:改用 _stricmpMSVC/MinGW 都支持)

3.12 localtime 可能返回 NULL

  • 修复:改用 localtime_s,无需 NULL 检查

3.13 main.c 中 _() 嵌套调用可能崩溃

  • 文件src/main.c
  • 问题_(lua_config_get_string(...)) 嵌套调用,若配置键不存在,gettext(NULL) 行为未定义
  • 修复:先将结果保存到临时变量并检查非 NULL
// 修复前
IupMessage(_("Warning"), _(lua_config_get_string("status", "admin_warning")));

// 修复后
const char *admin_msg = lua_config_get_string("status", "admin_warning");
IupMessage(_("Warning"), admin_msg ? _(admin_msg) : "需要管理员权限才能编辑环境变量");

四、第一轮修复(原10条锐评)

# 问题 状态
1 core层用了iup.h(架构矛盾) 已修复
2 main.c管理员权限检测代码灾难 已修复
3 refresh_main_window_ui重复代码 已修复
4 字符串溢出风险(buffer不统一) 已修复
5 错误码乱用(ERR_NULL_PTR误用) 已修复
6 硬编码字符串满天飞 已修复
7 backup_registry未实现 已修复
8 callbacks.c 600行回调地狱 已拆分
9 StringList封装不透明 已修复
10 refresh_single_list_style黑盒 已修复

五、修改文件清单

文件 修改类型
include/utils/string_ext.h 添加访问器函数声明
include/utils/ui_constants.h 新建,控件名称常量
include/core/import_export.h 添加文档注释
include/controller/callbacks_internal.h 新建,内部辅助函数声明
src/utils/string_ext.c 修复 realloc/strdup 安全性
src/utils/os_env.c 修复 wcsftime、localtime、目录创建
src/core/registry_service.c 修复 malloc 错误处理
src/core/import_export.c 重写 JSON 解析器、修复转义函数
src/core/path_manager.c 优化清理算法、修复错误码
src/main.c 修复 putenv、_() 嵌套调用
src/ui/main_window.c 修复 TABTITLE 设置位置
src/controller/callbacks.c 拆分后只保留辅助函数
src/controller/callbacks_basic.c 新建,基础 CRUD 回调
src/controller/callbacks_nav.c 新建,导航回调
src/controller/callbacks_search.c 新建,搜索/拖拽回调
src/controller/callbacks_io.c 新建,导入导出回调
src/controller/callbacks_sys.c 新建,系统操作回调
CMakeLists.txt 添加新源文件

六、编译验证

cmake -B build -G "MinGW Makefiles"
cmake --build build

结果:编译通过,无错误,无警告。


七、剩余已知问题(设计决策,非 Bug)

问题 原因 建议
IUP 指针存储模式 IUP 框架标准用法 保持现状
日志线程安全 当前是单线程应用 多线程时再处理
localtime 线程安全 已改用 localtime_s 已修复

审查完成于 2026-04-28