4.7 KiB
FAIL
crates/ely-files/src/recovery.rs:145 — [P1] 加密恢复点分两次发布 .enc 和 .nonce,枚举却只凭 .enc 认定恢复点存在,上一轮的完整提交缺陷仍存在于加密路径。隔离探针让 nonce 写入失败,留下已发布密文;移除故障后,points() 与后续 write_once() 均持续返回 NotFound,连已有有效恢复点也无法列出。第 258 行先删 nonce 再删密文,清理中断同样复现。修复方向:以完整恢复点为单位原子提交,枚举识别提交状态,清理中断保持可恢复,并覆盖发布与删除各阶段的故障测试。
crates/ely-files/src/recovery.rs:107 — [P1] 容量预检遗漏加密包的 4 字节长度头、16 字节认证标签和 12 字节 nonce,上一轮“清空全部恢复点后仍报告成功”仍可复现。容量设为 40 字节,先写入 old!,再写入 123456789:第二点实际占 41 字节,清理删除两点,结果却为 Ok(Some(path)),last_ok 更新且 points() 为空。修复方向:按实际完整落盘大小做提交前容量校验,超限保留旧点,确认新点仍可恢复后才更新成功状态;补加密容量边界回归。
crates/ely-files/src/recovery.rs:53 — [P1] open() 使用默认 64 MiB 容量先清理,再允许调用方通过 with_limits 应用用户设置,会删除用户容量范围内的有效恢复点。实测以 70 MiB 上限写入 65 MiB 内容,随后执行 Recovery::open(dir, now)?.with_limits(20, 70 MiB),恢复列表变空、文件已删除。修复方向:打开和清理前接收用户容量设置,保证重启前后的保留策略一致,并补自定义容量重开测试。
crates/ely-files/src/recovery.rs:419 — [P1] 系统恢复密钥的读取与创建存在覆盖竞态,且所有读取错误都进入生成新密钥的分支。两个应用首次同时读取同一 SERVICE/ACCOUNT,均读到缺失后各自生成密钥;所用 set_generic_password 会更新已有项,因此最后只保留一把密钥。对原样抽取的 RecoveryKey::load 使用隔离 Keychain 替身和屏障实测,两次调用均成功、返回密钥不同,其中一个应用生成的恢复点在使用持久密钥重开时返回 InvalidData。另注入读取 PermissionDenied,后续写入可成功时会直接替换旧密钥。修复方向:只对明确的条目缺失创建密钥,采用排他创建,竞态失败后读取已建立的密钥;其他读取错误原样暴露。补并发初始化及拒绝访问回归。
crates/ely-files/src/recovery.rs:441 — [P1] 上一轮要求的系统密钥保护路径在 Windows、Linux 仍为空实现,RecoveryKey::load() 无条件返回 Unsupported。两平台即使系统凭据库可用、文档已解锁,也无法通过当前接口建立可跨崩溃恢复的受保护密钥,违反 §18.2。Windows、Linux 编译检查通过仅证明该拒绝分支可编译。修复方向:接入 Windows 系统凭据能力和 Linux Secret Service,并验证跨进程密钥读取、加密恢复往返及凭据库不可用时的明确失败。
crates/ely-files/src/recovery.rs:80 — [P2] 上一轮的后台调度缺陷仍存在:新增 tick() 仅返回到期布尔值,全项目只有测试调用;全部写入和清理仍同步完成,缺少实际执行的 10 秒后台恢复任务。重放时 tick(100) 本身没有写入,时间 100 秒与 101 秒的两次 write_once 仍立即产生两点;running 仍只在持有独占 &mut self 的同步调用内变化,并发测试继续直接修改私有字段。修复方向:落实后台周期调度及同文档任务占用管理,以可控时钟和延迟写入验证真实调度、重叠跳过及失败后的继续执行。
crates/ely-files/src/recovery.rs:60 — [P2] 七天保留修复仅覆盖普通 open();加密入口 sensitive() 和恢复列表读取均跳过过期清理,上一轮的超期保留场景仍成立。实测写入时间为当前时间减八天的加密恢复点,销毁后以同一密钥重新创建 Recovery::sensitive,points() 仍列出该点且文件仍在;已打开后长期没有新写入的目录也缺少维护路径。修复方向:在加密与普通恢复的打开、扫描或维护流程统一执行年龄限制,并补无新写入的加密重启与持续打开测试。
crates/ely-files/src/recovery.rs:194 — [P2] 加密点把缺失光标编码为空串,解密枚举又无条件包装为 Some,丢失 §6.3 要求的恢复能力区分。实测 Recovery::sensitive(...).write_once(content, None, time) 后,points()[0].cursor 为 Some("");上层据此判断有光标恢复数据时会得到虚假状态。修复方向:在加密包中保留光标是否存在的信息,完整往返 None 与 Some,补未提供光标时的回归。