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

276 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PathEditor 代码审查修复日志
> 审查日期:2026-04-28
> 审查范围:全项目代码质量审查
> 修复状态:29/29 已完成
---
## 一、高严重度问题(7 项)
### 1.1 add_string_list 中 realloc 失败导致内存泄漏
- **文件**`src/utils/string_ext.c`
- **问题**`realloc` 返回 NULL 时,原 `list->items` 指针被覆盖为 NULL,导致原有数组及其中所有字符串指针永久泄漏
- **修复**:使用临时变量保存 `realloc` 结果,失败时保留原数据不变
```c
// 修复前
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])`
```c
// 修复前
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_cb``ExportData imported``system``user` 从未调用 `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`
- **修复**:检查返回值,备份失败时提示用户是否继续保存
```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`
- **问题**`TABTITLE0``TABTITLE1``IupTabs` 属性,不是 `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.c``src/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`
- **修复**:改用 `_stricmp`MSVC/MinGW 都支持)
### 3.12 localtime 可能返回 NULL
- **修复**:改用 `localtime_s`,无需 NULL 检查
### 3.13 main.c 中 _() 嵌套调用可能崩溃
- **文件**`src/main.c`
- **问题**`_(lua_config_get_string(...))` 嵌套调用,若配置键不存在,`gettext(NULL)` 行为未定义
- **修复**:先将结果保存到临时变量并检查非 NULL
```c
// 修复前
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` | 添加新源文件 |
---
## 六、编译验证
```bash
cmake -B build -G "MinGW Makefiles"
cmake --build build
```
**结果**:编译通过,无错误,无警告。
---
## 七、剩余已知问题(设计决策,非 Bug)
| 问题 | 原因 | 建议 |
|------|------|------|
| IUP 指针存储模式 | IUP 框架标准用法 | 保持现状 |
| 日志线程安全 | 当前是单线程应用 | 多线程时再处理 |
| localtime 线程安全 | 已改用 localtime_s | 已修复 |
---
*审查完成于 2026-04-28*