feb5ae709f
- C1: placement.rs 删除列偏移特殊处理 (col==6→5),place_bit 已自动跳过保留区 - C2: version.rs V5-H 纠错表 h_g1: 4→2 (总码字数 200→134) - C3: mode.rs Kanji 编码删除冗余 if/else 重复分支 - C4: galois.rs div() 返回 Option<u8> 替代 panic!
101 lines
3.5 KiB
Markdown
101 lines
3.5 KiB
Markdown
# QRGen 全面代码审查报告
|
||
|
||
**日期**: 2026-06-17
|
||
**审查方式**: 三重并行审查(算法正确性 + 安全性 + 架构/代码质量)
|
||
**测试状态**: 69 tests pass | clippy: 14 风格警告
|
||
|
||
---
|
||
|
||
## CRITICAL — 必须立即修复
|
||
|
||
### C1. placement.rs:20 — 数据排列列偏移 bug(所有版本)
|
||
|
||
当 zigzag 扫描到 `col == 6`(时序图案列)时,代码改为 `col = 5` 并处理列 (5, 4)。下一轮 `col = 4` 处理列 (4, 3)。**列 4 被写入两次**,第一次写入的数据被覆盖丢失。
|
||
|
||
**修复**: 删除特殊处理。`place_bit` 已自动跳过保留区:
|
||
|
||
```rust
|
||
// 错误:
|
||
let actual_col = if col == 6 { 5 } else { col as usize };
|
||
// 正确:
|
||
let actual_col = col as usize;
|
||
```
|
||
|
||
### C2. version.rs:273 — V5-H 纠错表数据错误
|
||
|
||
`h_g1: 4` 应为 `h_g1: 2`。当前值导致总码字数不匹配 (200 ≠ 134),Version 5 + H 级生成的 QR 码数据错乱。
|
||
|
||
### C3. mode.rs:165-181 — Kanji Shift-JIS 编码 if/else 分支完全相同
|
||
|
||
`unicode_to_shift_jis` 中的 `if sjis <= 0x9FFC { ... } else { ... }` 两个分支代码完全一致。`else` 分支应使用 `h - 0xC1` 替代 `h - 0x81`。
|
||
|
||
### C4. galois.rs:75 — 库函数中 panic!()
|
||
|
||
`div(a, b)` 中 `b == 0` 时 panic。库函数不应 panic,应返回 `Option<u8>` 或 `Result`。
|
||
|
||
---
|
||
|
||
## HIGH — 应尽快修复
|
||
|
||
### H1. patterns.rs — 定位图案分隔符未标记为保留区
|
||
|
||
ISO 18004 要求定位图案周围有 1 模块宽的白色分隔符。当前未 `reserve()`,数据可能写入该区域,导致扫码器识别失败。
|
||
|
||
### H2. gui/src-frontend/src/hooks/useQrEncode.ts — setTimeout 未在组件卸载时清理
|
||
|
||
React Strict Mode 下或快速切换模式时,stale callback 可能在 unmount 后触发 dispatch。
|
||
|
||
### H3. version.rs — 1352 行超 800 行限制
|
||
|
||
VERSION_TABLE 占 ~1100 行。建议拆出 `version/table.rs`。
|
||
|
||
### H4. 缺少 Kanji 编码单元测试
|
||
|
||
`encode_kanji` 和 `unicode_to_shift_jis` 零直接测试。
|
||
|
||
### H5. 历史记录未持久化
|
||
|
||
`AppState.history` 仅存内存,重启丢失。`tauri-plugin-store` 已注册但未接线。
|
||
|
||
### H6. 14 个 clippy 警告(12 个可 auto-fix)
|
||
|
||
---
|
||
|
||
## MEDIUM
|
||
|
||
| # | 文件 | 问题 |
|
||
|---|------|------|
|
||
| M1 | QrPreview.tsx:20 | `dangerouslySetInnerHTML` — 如 SVG 渲染器未来嵌入用户文本则有 XSS 风险 |
|
||
| M2 | ExportPanel.tsx / useQrEncode.ts | 3 处 `console.error` 在生产代码中 |
|
||
| M3 | App.tsx | 缺少 React Error Boundary |
|
||
| M4 | mode.rs:148 | Kanji 编码是"近似映射",非完整 Shift JIS 转换 |
|
||
| M5 | gui/lib.rs | 边距参数无上限验证 (0-255),极端值可导致 OOM |
|
||
| M6 | svg.rs | SVG 渲染用大量 `format!` 拼接,大版本效率低 |
|
||
|
||
---
|
||
|
||
## LOW
|
||
|
||
| # | 文件 | 问题 |
|
||
|---|------|------|
|
||
| L1 | render/png.rs:38 | `.expect()` 而非错误传播 |
|
||
| L2 | galois.rs | `OnceLock` 可替换为 `LazyLock` |
|
||
| L3 | mask.rs:188 | 不必要的 `matrix.clone()` |
|
||
| L4 | version.rs | `ec_info()` 每次都分配 Vec |
|
||
| L5 | App.tsx:20 | emoji 在标题栏 |
|
||
|
||
---
|
||
|
||
## 已验证正确
|
||
|
||
- ✅ Galois GF(2⁸) 四则运算 + exp/log 表
|
||
- ✅ Reed-Solomon 生成多项式 + 长除法 + 交错
|
||
- ✅ 四种编码模式的比特计数(符合 ISO 18004)
|
||
- ✅ 比特流终止符 + 0xEC/0x11 填充
|
||
- ✅ 版本容量表(除 V5-H 外全部数学验证通过)
|
||
- ✅ BCH(15,5) + BCH(18,6) 编码
|
||
- ✅ 8 种掩码 + 四规则惩罚评分
|
||
- ✅ 定位/对齐/时序图案位置
|
||
- ✅ 格式信息 XOR 掩码 0x5412
|
||
- ✅ 零 `unsafe` 块 | 零硬编码密钥 | 零命令注入
|