跳转至

运行时文件 Base64 填充

带填充的运行时文件写入长度必须能被四整除。空字符串以及长度模四等于零、二或三的无填充 Base64 仍然有效。 此更改恰好拒绝此前被接受的、包含尾部填充且总长度模四为二或三的字符串。它不强制规范化的未使用填充位,也不更改字母表。

边界证据

输入 之前 之后
A= 接受 拒绝
AA== 接受 接受
AAA= 接受 接受
AAAA 接受 接受
'' 接受 接受
A 拒绝 拒绝
== 接受 拒绝
AA=A(内部填充) 拒绝 拒绝
AA= 接受 拒绝
A== 接受 拒绝
AAAA== 接受 拒绝
AA、AAA(无填充) 接受 接受

Buffer.from('A=', 'base64') 解码为零字节。在 RPC 边界拒绝格式错误的填充,可防止一个被接受的请求静默写入不同的字节。

调用方普查

调用方 / 接口面 可达性与兼容性结论
桌面端 runtime-file-import-client.ts → uploadRuntimeFileWithoutClobber → writeRuntimeBase64File files.writeBase64 和 files.writeBase64Chunk 的唯一生产环境生产者。filesystem-runtime-upload-staging.ts 中的暂存使用 buffer.toString('base64') 编码完整文件;新拒绝的值无法被生成。
桌面端单帧上传 当暂存字符串长度最多为 512 × 1024 个字符时,原样发送该字符串。标准 Node Base64 的长度始终能被四整除。空文件仍被接受。
桌面端分块上传 在 512 × 1024 = 524,288 个字符处切分编码流,该长度能被四整除。每个偏移量和每个完整分块都与四元组对齐。最后一个分块是两个四的倍数之差,即使它以 = 或 == 结尾也是如此。不会额外组装最后一个分块,也不会添加逐分块填充。
stageExternalPathsForRuntimeUpload 的 Web 实现 返回空源列表;不会生成文件写入负载。
移动端文件编辑器 使用 files.writeTerminalArtifact 配合文本内容及其独立模式。不会到达此谓词。
移动端剪贴板 / 图片附件 使用 clipboard.startImageUpload、clipboard.appendImageUploadChunk、clipboard.commitImageUpload 以及 clipboard.saveImageAsTempFile 回退。它们的验证器是 clipboard-params.ts 中的 isValidBase64,而不是 isValidRuntimeFileBase64。保持不变,包括移动端规范化器现有的宽松填充行为。
CLI 没有任一 Base64 文件写入方法的生产者。src/cli/handlers/file.ts 中的文件命令调用 files.open / files.openDiff;其他 CLI RPC 调用点不会构造 Base64 文件写入。
生成的参数目录 引用两个模式;RpcParams 消费者使用推断类型。移动端的入口点仅为 export type,因此不会发生新的客户端解析。
RPC 分发 files-mutation-methods.ts 注册两个模式。分块模式扩展整个文件模式;这些是该谓词唯一的运行时消费者。直接运行时/提供者调用不会解析这些模式。
调用方 / 接口面 可达性与兼容性结论

仓库范围的搜索覆盖了方法名、模式名、谓词及其模式,以及上传/暂存函数的所有调用方。针对 HEAD 在 mobile/src 下的定向历史搜索未发现受影响方法或谓词的引入/移除。本地发布引用 mobile-ios-v0.0.27 和 mobile-v0.0.13 也不包含任一 Base64 文件写入方法的调用方;iOS 引用使用了上述独立的剪贴板和终端产物方法。本次源码/历史审计未发现已发布的移动端生产者会生成新被拒绝的值。

远程与工作区兼容性

使用受审计生产者的旧桌面客户端会向新主机发送有效四元组。新客户端仍会向旧主机发送相同字节。方法、字段、操作码或主机发布的内容均未发生变化。这遵循 remote-wire-compatibility.md 中的混合版本要求。

RPC 验证在工作区解析和提供者选择之前运行,因此相同规则适用于文件夹工作区、git worktree、本地主机和 SSH 主机。SSH 所有权围栏和提供者写入保持不变。任意发送格式错误填充的外部 RPC 调用方现在将收到验证错误;有效的填充和无填充负载仍会被接受。

回归证据

src/main/runtime/rpc/methods/files-base64-padding.test.ts 验证了两个实际 RPC 注册,断言被拒绝的输入永远不会到达写入器,并验证被接受的内容原样转发。使用原始谓词时,测试运行产生了 16 个失败 / 16 个通过;全部 16 个失败都是旧实现接受的新被拒绝的填充形状。这是在编辑谓词之前运行的。

现有的桌面外部导入测试现在在 524,288 字符的首个块之后使用最终的 AA== 块,固定真实上传路径中填充最终块的转发。无需更改生产者或剪贴板验证。

验证结果

所有测试/类型检查命令均使用 ORCA_BACKGROUND_LAUNCH=1。

  • pnpm tc:退出码 0;所有根类型检查项目通过。
  • pnpm exec vitest run src/main/runtime/rpc:277 个文件通过,1 个失败; 2,419 个测试通过,2 个超时,1 个跳过。两个超时都位于未更改的 terminal-output-frame-chunks-equivalence.test.ts 中(5 秒代理范围测试和 30 秒 800 负载模糊测试)。
  • pnpm --dir mobile typecheck:退出码 0(tsc --noEmit)。
  • pnpm run check:code-quality:changed:退出码 0;代码质量、类型感知代码 质量和 React Doctor 在三个源文件中均报告零新增发现。
  • 使用 --config config/vitest.config.ts --maxWorkers=2 的聚焦运行:全部三个 文件 / 58 个测试通过,覆盖填充、桌面外部导入,以及初始运行中超时的 终端输出等效文件。
  • 使用 --maxWorkers=2 的完整 RPC 重跑:退出码 0;全部 278 个文件通过, 2,421 个测试通过,1 个跳过(198.34 秒)。无需超时覆盖。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 orca48/orca