fix: 全面代码审查修复 — 安全/类型/持久化/代码质量 (28项)
🔴 CRITICAL (1): - tauri.conf.json: CSP 从 null 改为最小权限策略 🟠 HIGH (6): - 新建 capabilities/default.json: Tauri v2 权限约束(store/dialog/clipboard) - cli: 路径遍历防护 — 拒绝含 ParentDir 组件的输出路径 - HistoryList: 删除/清空同步持久化到 store,历史点击用 formData 回填 - ExportPanel: 移除 console.warn,getCurrentText any→QrState - useQrEncode: WiFi 密码在历史中脱敏显示(P:***),Store 实例缓存 🟡 MEDIUM (10): - mode.rs: Kanji fallback 从 UTF-8 字节改为 13-bit 零值占位(段内模式一致) - mode.rs: Shift JIS 第二字节跳过 0x7F 空洞,修正行内索引 - mode.rs: encode_numeric/alphanumeric 添加 debug_assert! 前置条件 - mask.rs: best_matrix.unwrap()→expect() 附错误信息 - version.rs: ec_info 仅返回 count>0 的 BlockInfo,EcInfo/BlockInfo 加 Debug+Clone - types/index.ts: HistoryEntry.mode string→ModeType,新增 formData 字段 - qrContext.tsx: 使用缓存 Store 加载历史 🟢 LOW (11): - cargo fmt 全部文件 - svg.rs: String::new()→with_capacity() 预分配 - patterns.rs: encode_format_info 拆分为两行提高可读性 - png.rs: 提取 fill_module() 辅助函数降低嵌套 - ErrorBoundary: 添加 componentDidCatch 错误日志入口 - QrPreview: dangerouslySetInnerHTML→<img>+data URL(安全),loading 状态指示 - galois.rs/version.rs: 5 处 #[allow(clippy::indexing_slicing)]+安全文档 - 新建 utils/qrText.ts: 集中管理 6 种模式的文本构造,消除 ExportPanel/mode 间重复 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+21
-11
@@ -82,29 +82,36 @@ impl Version {
|
||||
row.h_g2_data,
|
||||
),
|
||||
};
|
||||
let mut blocks = Vec::new();
|
||||
if g1_blocks > 0 {
|
||||
blocks.push(BlockInfo {
|
||||
count: g1_blocks,
|
||||
data_codewords: g1_data,
|
||||
});
|
||||
}
|
||||
if g2_blocks > 0 {
|
||||
blocks.push(BlockInfo {
|
||||
count: g2_blocks,
|
||||
data_codewords: g2_data,
|
||||
});
|
||||
}
|
||||
|
||||
EcInfo {
|
||||
total_codewords: total,
|
||||
ec_per_block,
|
||||
blocks: vec![
|
||||
BlockInfo {
|
||||
count: g1_blocks,
|
||||
data_codewords: g1_data,
|
||||
},
|
||||
BlockInfo {
|
||||
count: g2_blocks,
|
||||
data_codewords: g2_data,
|
||||
},
|
||||
],
|
||||
blocks,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EcInfo {
|
||||
pub total_codewords: u16,
|
||||
pub ec_per_block: u8,
|
||||
pub blocks: Vec<BlockInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BlockInfo {
|
||||
pub count: u16,
|
||||
pub data_codewords: u16,
|
||||
@@ -1283,6 +1290,8 @@ fn init_capacity_table() -> [[u16; 4]; 40] {
|
||||
table
|
||||
}
|
||||
|
||||
// SAFETY: version.0 ∈ [1,40] 由 Version::new() 保证; level 是 4 变体枚举
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
pub fn get_data_capacity(version: Version, level: EcLevel) -> u16 {
|
||||
static CAPACITY: OnceLock<[[u16; 4]; 40]> = OnceLock::new();
|
||||
let cap = CAPACITY.get_or_init(init_capacity_table);
|
||||
@@ -1335,9 +1344,10 @@ mod tests {
|
||||
fn test_ec_info_blocks() {
|
||||
let info = Version(1).ec_info(EcLevel::M);
|
||||
// Version 1 M: 1 block × 16 data codewords, 10 ec per block
|
||||
// g2 组 count=0 已被过滤,仅保留 g1
|
||||
assert_eq!(info.total_codewords, 26);
|
||||
assert_eq!(info.ec_per_block, 10);
|
||||
assert_eq!(info.blocks.len(), 2);
|
||||
assert_eq!(info.blocks.len(), 1);
|
||||
assert_eq!(info.blocks[0].count, 1);
|
||||
assert_eq!(info.blocks[0].data_codewords, 16);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user